diff --git a/AscentChangelog.txt b/AscentChangelog.txt new file mode 100644 index 000000000..1aee2b439 --- /dev/null +++ b/AscentChangelog.txt @@ -0,0 +1,39 @@ +->> Features implemented in Ascent: +In-World: +* Idle time of avatars around you (Not perfect) +* Client tags/coloring for various clients, and extra client definitions +* Force Away button to fake being away if you really want to avoid someone :V +* Double-Click teleport (Not all the functionality of Emerald yet) +Preferences (Options are in Ascent Options): +* Disable Look At +* Disable Point At and beam end +* Fetch inventory in background on login (No waiting for caching when searching) +* Display your client tag to yourself +* Display your client tag color to yourself +* Rez objects as land group when possible +* Some settings can now be saved per account after changing an option in the preferences. Currently affected settings: + Edit Beam color + Client Tag Color +Communication Window: +- Friend List: + * Friend List Online/Total counts (Not perfect) + * Shows what rights your friends have given you (Mod, See on map, Online) +Parcel Window: +- General tab: +- Objects tab: + * In Sim/Online/Offline indicators for Parcel Object Owner listings (Online is currently wonky - This is an issue with SL, Emerald has the same problem.) +Build Window: +- General tab: + * Last Owner shown in Build "General" Tab + * Group object is set to has a "View" button to see the group's profile + * Copy Object Key button +- Build Tab: + * Copy/Paste Position buttons + * Copy/Paste Size buttons + * Copy/Paste Rotation buttons + * Copy/Paste Primitive Parameters buttons + +Known issues: +Online/Total counts in the friends list sometimes go haywire. Not often or by a large margin, but it happens. +Import/Export buttons don't work. Or they try to and break. Don't use 'em. +Skin menu doesn't work - On hold until we actually have some skins to show - Ascent will have its own "branded" skin at some point. \ No newline at end of file diff --git a/LICENSES/apr_suite.txt b/LICENSES/apr_suite.txt index 17e9556a2..be6d0951e 100644 --- a/LICENSES/apr_suite.txt +++ b/LICENSES/apr_suite.txt @@ -1,14 +1,784 @@ -Copyright 2000-2004 The Apache Software Foundation + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +APACHE PORTABLE RUNTIME SUBCOMPONENTS: + +The Apache Portable Runtime includes a number of subcomponents with +separate copyright notices and license terms. Your use of the source +code for the these subcomponents is subject to the terms and +conditions of the following licenses. + +From strings/apr_fnmatch.c, include/apr_fnmatch.h, misc/unix/getopt.c, +file_io/unix/mktemp.c, strings/apr_strings.c: + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +From network_io/unix/inet_ntop.c, network_io/unix/inet_pton.c: + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + +From dso/aix/dso.c: + + * Based on libdl (dlfcn.c/dlfcn.h) which is + * Copyright (c) 1992,1993,1995,1996,1997,1988 + * Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany. + * + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + +From strings/apr_strnatcmp.c, include/apr_strings.h: + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +From strings/apr_snprintf.c: + + * + * cvt - IEEE floating point formatting routines. + * Derived from UNIX V7, Copyright(C) Caldera International Inc. + * + + Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code and documentation must retain the above + copyright notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + All advertising materials mentioning features or use of this software + must display the following acknowledgement: + + This product includes software developed or owned by Caldera + International, Inc. + + Neither the name of Caldera International, Inc. nor the names of other + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT, + INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +APACHE PORTABLE RUNTIME SUBCOMPONENTS: + +The Apache Portable Runtime includes a number of subcomponents with +separate copyright notices and license terms. Your use of the source +code for the these subcomponents is subject to the terms and +conditions of the following licenses. + +For the include\apr_md5.h component: +/* + * This is work is derived from material Copyright RSA Data Security, Inc. + * + * The RSA copyright statement and Licence for that original material is + * included below. This is followed by the Apache copyright statement and + * licence for the modifications made to that material. + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + */ + +For the passwd\apr_md5.c component: + +/* + * This is work is derived from material Copyright RSA Data Security, Inc. + * + * The RSA copyright statement and Licence for that original material is + * included below. This is followed by the Apache copyright statement and + * licence for the modifications made to that material. + */ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + */ +/* + * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0 + * MD5 crypt() function, which is licenced as follows: + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +For the crypto\apr_md4.c component: + + * This is derived from material copyright RSA Data Security, Inc. + * Their notice is reproduced below in its entirety. + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD4 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD4 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +For the include\apr_md4.h component: + + * + * This is derived from material copyright RSA Data Security, Inc. + * Their notice is reproduced below in its entirety. + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD4 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD4 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +For the test\testmd4.c component: + + * + * This is derived from material copyright RSA Data Security, Inc. + * Their notice is reproduced below in its entirety. + * + * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All + * rights reserved. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +For the xml\expat\conftools\install-sh component: + +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# + +For the expat xml parser component: + +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + and Clark Cooper + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==================================================================== + +For the ldap/apr_ldap_url.c component: + +/* Portions Copyright 1998-2002 The OpenLDAP Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. A copy of this license is available at + * http://www.OpenLDAP.org/license.html or in file LICENSE in the + * top-level directory of the distribution. + * + * OpenLDAP is a registered trademark of the OpenLDAP Foundation. + * + * Individual files and/or contributed packages may be copyright by + * other parties and subject to additional restrictions. + * + * This work is derived from the University of Michigan LDAP v3.3 + * distribution. Information concerning this software is available + * at: http://www.umich.edu/~dirsvcs/ldap/ + * + * This work also contains materials derived from public sources. + * + * Additional information about OpenLDAP can be obtained at: + * http://www.openldap.org/ + */ + +/* + * Portions Copyright (c) 1992-1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ diff --git a/LICENSES/curl.txt b/LICENSES/curl.txt index edfff428c..12a41cee6 100644 --- a/LICENSES/curl.txt +++ b/LICENSES/curl.txt @@ -1,6 +1,6 @@ COPYRIGHT AND PERMISSION NOTICE -Copyright (c) 1996 - 2002, Daniel Stenberg, . +Copyright (c) 1996 - 2007, Daniel Stenberg, . All rights reserved. @@ -19,4 +19,3 @@ OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. - diff --git a/LICENSES/dbghelp.txt b/LICENSES/dbghelp.txt new file mode 100644 index 000000000..ffaa5f6e3 --- /dev/null +++ b/LICENSES/dbghelp.txt @@ -0,0 +1,138 @@ +MICROSOFT SOFTWARE LICENSE TERMS +MICROSOFT DEBUGGING TOOLS FOR WINDOWS +These license terms are an agreement between Microsoft Corporation (or based on where you live, one of +its affiliates) and you. Please read them. They apply to the software named above, which includes the +media on which you received it, if any. The terms also apply to any Microsoft +* updates, +* supplements, +* Internet-based services +* support services, and +* Debugging symbol files that you may access over the internet +for this software, unless other terms accompany those items. If so, those terms apply. +By using the software, you accept these terms. If you do not accept them, do not use the +software. +If you comply with these license terms, you have the rights below. +1. INSTALLATION AND USE RIGHTS. One user may install and use any number of copies of the +software on your devices to design, develop, debug and test your programs. +2. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS. +a. Distributable Code. The software contains code that you are permitted to distribute in programs +you develop if you comply with the terms below. +i. Right to Use and Distribute. The code and text files listed below are “Distributable Code.” +* REDIST.TXT Files. You may copy and distribute the object code form of code listed in +REDIST.TXT files. +* Sample Code. You may modify, copy, and distribute the source and object code form of +code marked as “sample.” +* Third Party Distribution. You may permit distributors of your programs to copy and +distribute the Distributable Code as part of those programs. +ii. Distribution Requirements. For any Distributable Code you distribute, you must +* add significant primary functionality to it in your programs; +* require distributors and external end users to agree to terms that protect it at least as much +as this agreement; +* display your valid copyright notice on your programs; and +* indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, +related to the distribution or use of your programs. +iii. Distribution Restrictions. You may not +* alter any copyright, trademark or patent notice in the Distributable Code; +* distribute any symbol files which you may access or use under these license terms for the +software; +* use Microsoft’s trademarks in your programs’ names or in a way that suggests your +programs come from or are endorsed by Microsoft; +* distribute Distributable Code to run on a platform other than the Windows platform; +* include Distributable Code in malicious, deceptive or unlawful programs; or +* modify or distribute the source code of any Distributable Code so that any part of it +becomes subject to an Excluded License. An Excluded License is one that requires, as a +condition of use, modification or distribution, that +* the code be disclosed or distributed in source code form; or +* others have the right to modify it. +3. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights +to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights +despite this limitation, you may use the software only as expressly permitted in this agreement. In +doing so, you must comply with any technical limitations in the software that only allow you to use it in +certain ways. You may not +* work around any technical limitations in the software; +* reverse engineer, decompile or disassemble the software, except and only to the extent that +applicable law expressly permits, despite this limitation; +* make more copies of the software than specified in this agreement or allowed by applicable law, +despite this limitation; +* publish the software for others to copy; +* rent, lease or lend the software; +* transfer the software or this agreement to any third party; or +* use the software for commercial software hosting services. +4. INTERNET-BASED SERVICES. Microsoft provides Internet-based services with the software. It may +change or cancel them at any time. +a. Consent for Internet-Based Services. The software contains features which may connect to +Microsoft or service provider computer systems over the Internet. In some cases, you will not +receive a separate notice when they connect. You may switch these features on or you may +choose not to use them. For more information about these features, see +http://www.microsoft.com/info/privacy/default.mspx. By using these features, you consent to the transmission of +this information. Microsoft does not use the information to identify or contact you. +b. Misuse of Internet-based Services. You may not use these services in any way that could +harm them or impair anyone else’s use of them. You may not use the services to try to gain +unauthorized access to any service, data, account or network by any means. + +5. BACKUP COPY. You may make one backup copy of the software. You may use it only to reinstall the +software. +6. DOCUMENTATION. Any person that has valid access to your computer or internal network may copy +and use the documentation for your internal, reference purposes. +7. EXPORT RESTRICTIONS. The software is subject to United States export laws and regulations. You +must comply with all domestic and international export laws and regulations that apply to the software. +These laws include restrictions on destinations, end users and end use. For additional information, see +www.microsoft.com/exporting. +8. SUPPORT SERVICES. Because this software is “as is,” we may not provide support services for it. +9. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based +services and support services that you use, are the entire agreement for the software and support +services. +10. APPLICABLE LAW. +a. United States. If you acquired the software in the United States, Washington state law governs +the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of +laws principles. The laws of the state where you live govern all other claims, including claims under +state consumer protection laws, unfair competition laws, and in tort. +b. Outside the United States. If you acquired the software in any other country, the laws of that +country apply. +11. LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the +laws of your country. You may also have rights with respect to the party from whom you acquired the +software. This agreement does not change your rights under the laws of your country if the laws of +your country do not permit it to do so. +12. DISCLAIMER OF WARRANTY. The software is licensed “as-is.” You bear the risk of using +it. Microsoft gives no express warranties, guarantees or conditions. You may have +additional consumer rights under your local laws which this agreement cannot change. To +the extent permitted under your local laws, Microsoft excludes the implied warranties of +merchantability, fitness for a particular purpose and non-infringement. +13. LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. You can recover from +Microsoft and its suppliers only direct damages up to U.S. $5.00. You cannot recover any +other damages, including consequential, lost profits, special, indirect or incidental +damages. +This limitation applies to +* anything related to the software, services, content (including code) on third party Internet sites, or +third party programs; and +* claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, +or other tort to the extent permitted by applicable law. +It also applies even if Microsoft knew or should have known about the possibility of the damages. The +above limitation or exclusion may not apply to you because your country may not allow the exclusion or +limitation of incidental, consequential or other damages. +Please note: As this software is distributed in Quebec, Canada, some of the clauses in this +agreement are provided below in French. +Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce +contrat sont fournies ci-dessous en français. +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de +ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez +bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat +ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, +d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de +dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation +pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de +bénéfices. +Cette limitation concerne : +* tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des +sites Internet tiers ou dans des programmes tiers ; et +* les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, +de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. +Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel +dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages +indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne +s’appliquera pas à votre égard. +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits +prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de +votre pays si celles-ci ne le permettent pas. diff --git a/LICENSES/freetype.txt b/LICENSES/freetype.txt index 225e1fafc..bbaba33f4 100644 --- a/LICENSES/freetype.txt +++ b/LICENSES/freetype.txt @@ -1,3 +1,169 @@ -Portions of this software are copyright (c) 2003 The FreeType -Project (www.freetype.org). All rights reserved. + The FreeType Project LICENSE + ---------------------------- + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + + +--- end of FTL.TXT --- diff --git a/LICENSES/gtk-atk-pango-glib.txt b/LICENSES/gtk-atk-pango-glib.txt new file mode 100644 index 000000000..07a2d156d --- /dev/null +++ b/LICENSES/gtk-atk-pango-glib.txt @@ -0,0 +1,182 @@ +http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + +LGPL v 2.1 + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. + + To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. + + Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. + + When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. + + We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. + + For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. + + Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + * a) The modified work must itself be a software library. + * b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + * c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + * d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + * a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + * b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. + * c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + * d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + * e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + * a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + * b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. +Copyright (C) year name of author + +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; either +version 2.1 of the License, or (at your option) any later version. + +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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in +the library `Frob' (a library for tweaking knobs) written +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! + diff --git a/LICENSES/license.txt b/LICENSES/license.txt new file mode 100644 index 000000000..7c7481e80 --- /dev/null +++ b/LICENSES/license.txt @@ -0,0 +1,33 @@ + GLUI User Interface Toolkit + --------------------------- + + (The ZLIB License) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + + History of GLUI's License: + -------------------------- + Originally, GLUI was licensed under LGPL because Paul Rademacher + just wanted something that was very permissive, and LGPL was the + thing he had heard of. I discussed the license with Paul at + SIGGRAPH 2006, where he told me the above, and also told me he was + supportive of changing the license to one of the less restrictive + open source licenses. So after contacting all the authors to get + their OK, GLUI is now under the ZLIB license. + + Bill Baxter -- November 2007 diff --git a/LICENSES/ndofdev.txt b/LICENSES/ndofdev.txt index e789ea9c6..d4d683f5a 100644 --- a/LICENSES/ndofdev.txt +++ b/LICENSES/ndofdev.txt @@ -1,23 +1,24 @@ -* Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com) -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * The name of its contributors may not be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY Jan Ciger ''AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL Jan Ciger BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the 3Dconnexion, Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/LICENSES/openSSL.txt b/LICENSES/openSSL.txt index efe806415..a2c4adcbe 100644 --- a/LICENSES/openSSL.txt +++ b/LICENSES/openSSL.txt @@ -1,116 +1,127 @@ -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -This package is an SSL implementation written -by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. + LICENSE ISSUES + ============== -This library is free for commercial and non-commercial use as long as -the following conditions are aheared to. The following conditions -apply to all code found in this distribution, be it the RC4, RSA, -lhash, DES, etc., code; not just the SSL code. The SSL documentation -included with this distribution is covered by the same copyright terms -except that the holder is Tim Hudson (tjh@cryptsoft.com). + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. -Copyright remains Eric Young's, and as such any Copyright notices in -the code are not to be removed. -If this package is used in a product, Eric Young should be given attribution -as the author of the parts of the library used. -This can be in the form of a textual message at program startup or -in documentation (online or textual) provided with the package. + OpenSSL License + --------------- -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - "This product includes cryptographic software written by - Eric Young (eay@cryptsoft.com)" - The word 'cryptographic' can be left out if the rouines from the library - being used are not cryptographic related :-). -4. If you include any Windows specific code (or a derivative thereof) from - the apps directory (application code) you must include an acknowledgement: - "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. + Original SSLeay License + ----------------------- -The licence and distribution terms for any publically available version or -derivative of this code cannot be changed. i.e. this code cannot simply be -copied and put under another distribution licence -[including the GNU Public Licence.] - -**************** -* SSLeay -**************** - -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. - -This package is an SSL implementation written -by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. - -This library is free for commercial and non-commercial use as long as -the following conditions are aheared to. The following conditions -apply to all code found in this distribution, be it the RC4, RSA, -lhash, DES, etc., code; not just the SSL code. The SSL documentation -included with this distribution is covered by the same copyright terms -except that the holder is Tim Hudson (tjh@cryptsoft.com). - -Copyright remains Eric Young's, and as such any Copyright notices in -the code are not to be removed. -If this package is used in a product, Eric Young should be given attribution -as the author of the parts of the library used. -This can be in the form of a textual message at program startup or -in documentation (online or textual) provided with the package. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - "This product includes cryptographic software written by - Eric Young (eay@cryptsoft.com)" - The word 'cryptographic' can be left out if the rouines from the library - being used are not cryptographic related :-). -4. If you include any Windows specific code (or a derivative thereof) from - the apps directory (application code) you must include an acknowledgement: - "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -The licence and distribution terms for any publically available version or -derivative of this code cannot be changed. i.e. this code cannot simply be -copied and put under another distribution licence -[including the GNU Public Licence.] +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ diff --git a/LICENSES/openjpeg.txt b/LICENSES/openjpeg.txt index 22ec8b89c..518281c8e 100644 --- a/LICENSES/openjpeg.txt +++ b/LICENSES/openjpeg.txt @@ -1,33 +1 @@ -http://www.openjpeg.org/BSDlicense.txt - -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - +/* * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium * Copyright (c) 2002-2007, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ \ No newline at end of file diff --git a/LICENSES/qt-4.5-linden-changes.txt b/LICENSES/qt-4.5-linden-changes.txt index a8800b3ae..d424824cb 100644 --- a/LICENSES/qt-4.5-linden-changes.txt +++ b/LICENSES/qt-4.5-linden-changes.txt @@ -2,5 +2,4 @@ The pristine version of Qt corresponding to this build is available at: http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/qt-all-opensource-src-4.5.2.tar.bz2 The patches we applied to the above package to get this build are available at: -http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/qtwebkit-linden-patches-20090709.tar.bz2 - +http://hg.secondlife.com/llqtwebkit/src/tip/qt_patches/ diff --git a/LICENSES/xmlrpc-epi.txt b/LICENSES/xmlrpc-epi.txt index 5614abc09..97d6b29c5 100644 --- a/LICENSES/xmlrpc-epi.txt +++ b/LICENSES/xmlrpc-epi.txt @@ -1,10 +1,22 @@ -Copyright 2000 Epinions, Inc. + Copyright 2000 Epinions, Inc. -Subject to the following 3 conditions, Epinions, Inc. permits you, free of charge, to (a) use, copy, distribute, modify, perform and display this software and associated documentation files (the "Software"), and (b) permit others to whom the Software is furnished to do so as well. + Subject to the following 3 conditions, Epinions, Inc. permits you, free + of charge, to (a) use, copy, distribute, modify, perform and display this + software and associated documentation files (the "Software"), and (b) + permit others to whom the Software is furnished to do so as well. -1) The above copyright notice and this permission notice shall be included without modification in all copies or substantial portions of the Software. + 1) The above copyright notice and this permission notice shall be included + without modification in all copies or substantial portions of the + Software. -2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF + ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY + IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE OR NONINFRINGEMENT. -3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. + 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT + OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING + NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH + DAMAGES. diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index ad26f427f..e23e2ca4b 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -9,12 +9,10 @@ if (WINDOWS) NAMES python25.exe python23.exe python.exe NO_DEFAULT_PATH # added so that cmake does not find cygwin python PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 0bd623d25..21f263faf 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -96,17 +96,17 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(GRID agni CACHE STRING "Target Grid") set(VIEWER ON CACHE BOOL "Build Second Life viewer.") -set(VIEWER_CHANNEL "Inertia" CACHE STRING "Viewer Channel Name") +set(VIEWER_CHANNEL "Ascent" CACHE STRING "Viewer Channel Name") set(VIEWER_LOGIN_CHANNEL ${VIEWER_CHANNEL} CACHE STRING "Fake login channel for A/B Testing") -set(VIEWER_BRANDING_ID "snowglobe" CACHE STRING "Viewer branding id (currently secondlife|snowglobe)") +set(VIEWER_BRANDING_ID "Ascent" CACHE STRING "Viewer branding id (currently secondlife|snowglobe)") # *TODO: break out proper Branding-secondlife.cmake, Branding-snowglobe.cmake, etc if (${VIEWER_BRANDING_ID} MATCHES "secondlife") set(VIEWER_BRANDING_NAME "Second Life") set(VIEWER_BRANDING_NAME_CAMELCASE "SecondLife") -elseif (${VIEWER_BRANDING_ID} MATCHES "snowglobe") - set(VIEWER_BRANDING_NAME "Snowglobe") - set(VIEWER_BRANDING_NAME_CAMELCASE "Snowglobe") +elseif (${VIEWER_BRANDING_ID} MATCHES "Ascent") + set(VIEWER_BRANDING_NAME "Ascent") + set(VIEWER_BRANDING_NAME_CAMELCASE "Ascent") endif (${VIEWER_BRANDING_ID} MATCHES "secondlife") set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.") diff --git a/indra/fmodfilestructure.zip b/indra/fmodfilestructure.zip new file mode 100644 index 000000000..0edfe5bb8 Binary files /dev/null and b/indra/fmodfilestructure.zip differ diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 37abb27e1..8725b2317 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -251,24 +251,24 @@ BOOL LLVorbisDecodeState::initDecode() return FALSE; } - // - try - { - // - mWAVBuffer.reserve(size_guess); - mWAVBuffer.resize(WAV_HEADER_SIZE); - // - } - catch(std::bad_alloc) - { - llwarns << "bad_alloc" << llendl; - if(mInFilep) - { + // + try + { + // + mWAVBuffer.reserve(size_guess); + mWAVBuffer.resize(WAV_HEADER_SIZE); + // + } + catch(std::bad_alloc) + { + llwarns << "bad_alloc" << llendl; + if(mInFilep) + { delete mInFilep; mInFilep = NULL; } - return FALSE; - } + return FALSE; + } // { @@ -442,9 +442,9 @@ BOOL LLVorbisDecodeState::finishDecode() char pcmout[4096]; /*Flawfinder: ignore*/ fade_length = llmin((S32)128,(S32)(data_length-36)/8); - // - //if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) - if((S32)mWAVBuffer.size() > (WAV_HEADER_SIZE + 2* fade_length)) + // + //if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) + if((S32)mWAVBuffer.size() > (WAV_HEADER_SIZE + 2* fade_length)) // { memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ @@ -464,9 +464,9 @@ BOOL LLVorbisDecodeState::finishDecode() memcpy(&mWAVBuffer[WAV_HEADER_SIZE], pcmout, (2 * fade_length)); /*Flawfinder: ignore*/ } S32 near_end = mWAVBuffer.size() - (2 * fade_length); - // - //if ((S32)mWAVBuffer.size() >= ( near_end + 2* fade_length)) - if ((S32)mWAVBuffer.size() > ( near_end + 2* fade_length)) + // + //if ((S32)mWAVBuffer.size() >= ( near_end + 2* fade_length)) + if ((S32)mWAVBuffer.size() > ( near_end + 2* fade_length)) // { memcpy(pcmout, &mWAVBuffer[near_end], (2 * fade_length)); /*Flawfinder: ignore*/ @@ -566,17 +566,17 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) { if (mCurrentDecodep) { - // rawrning - //BOOL res; - BOOL res = false; + // rawrning + //BOOL res; + BOOL res = false; // // Decode in a loop until we're done or have run out of time. - /* */ try{ /* */ - while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs)) - { - // decodeSection does all of the work above - } + /* */ try{ /* */ + while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs)) + { + // decodeSection does all of the work above + } /* */ }catch(std::bad_alloc){llerrs<<"bad_alloc whilst decoding"< */ if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid()) @@ -692,6 +692,4 @@ BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid) } return FALSE; -} - - +} \ No newline at end of file diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 94348f295..33ec3b6db 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -815,9 +815,9 @@ F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec) void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, - // - //const S32 type, const LLVector3d &pos_global) - const S32 type, const LLVector3d &pos_global, const LLUUID source_object) + // + //const S32 type, const LLVector3d &pos_global) + const S32 type, const LLVector3d &pos_global, const LLUUID source_object) // { // Create a new source (since this can't be associated with an existing source. @@ -831,9 +831,9 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i LLUUID source_id; source_id.generate(); - // - //LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); - LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type, source_object, true); + // + //LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); + LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type, source_object, true); // gAudiop->addAudioSource(asp); if (pos_global.isExactlyZero()) @@ -1261,9 +1261,9 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E // -// -//LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) -LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type, const LLUUID source_id, const bool isTrigger) +// +//LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) +LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type, const LLUUID source_id, const bool isTrigger) // : mID(id), mOwnerID(owner_id), @@ -1277,9 +1277,9 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 mQueueSounds(false), mPlayedOnce(false), mType(type), - // - mSourceID(source_id), - mIsTrigger(isTrigger), + // + mSourceID(source_id), + mIsTrigger(isTrigger), // mChannelp(NULL), mCurrentDatap(NULL), @@ -1299,9 +1299,9 @@ LLAudioSource::~LLAudioSource() mChannelp->setSource(NULL); mChannelp = NULL; } - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) // && mSourceID.notNull()) - logSoundStop(mLogID); + // + if(mType != LLAudioEngine::AUDIO_TYPE_UI) // && mSourceID.notNull()) + logSoundStop(mLogID); // } @@ -1391,9 +1391,9 @@ bool LLAudioSource::setupChannel() bool LLAudioSource::play(const LLUUID &audio_uuid) { - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) - logSoundPlay(mLogID, this, mPositionGlobal, mType, audio_uuid, mOwnerID, mSourceID, mIsTrigger, mLoop); // is mID okay for source id? + // + if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) + logSoundPlay(mLogID, this, mPositionGlobal, mType, audio_uuid, mOwnerID, mSourceID, mIsTrigger, mLoop); // is mID okay for source id? // // Special abuse of play(); don't play a sound, but kill it. if (audio_uuid.isNull()) @@ -1795,67 +1795,66 @@ bool LLAudioData::load() return true; } -// -std::map gSoundHistory; - -// static -void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped) -{ - LLSoundHistoryItem item; - item.mID = id; - item.mAudioSource = audio_source; - item.mPosition = position; - item.mType = type; - item.mAssetID = assetid; - item.mOwnerID = ownerid; - item.mSourceID = sourceid; - item.mPlaying = true; - item.mTimeStarted = LLTimer::getElapsedSeconds(); - item.mTimeStopped = F64_MAX; - item.mIsTrigger = is_trigger; - item.mIsLooped = is_looped; - - item.mReviewed = false; - item.mReviewedCollision = false; - - gSoundHistory[id] = item; -} - -//static -void logSoundStop(LLUUID id) -{ - if(gSoundHistory.find(id) != gSoundHistory.end()) - { - gSoundHistory[id].mPlaying = false; - gSoundHistory[id].mTimeStopped = LLTimer::getElapsedSeconds(); - gSoundHistory[id].mAudioSource = NULL; // just in case - pruneSoundLog(); - } -} - -//static -void pruneSoundLog() -{ - if(++gSoundHistoryPruneCounter >= 64) - { - gSoundHistoryPruneCounter = 0; - while(gSoundHistory.size() > 256) - { - std::map::iterator iter = gSoundHistory.begin(); - std::map::iterator end = gSoundHistory.end(); - U64 lowest_time = (*iter).second.mTimeStopped; - LLUUID lowest_id = (*iter).first; - for( ; iter != end; ++iter) - { - if((*iter).second.mTimeStopped < lowest_time) - { - lowest_time = (*iter).second.mTimeStopped; - lowest_id = (*iter).first; - } - } - gSoundHistory.erase(lowest_id); - } - } -} - -// +// +std::map gSoundHistory; + +// static +void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped) +{ + LLSoundHistoryItem item; + item.mID = id; + item.mAudioSource = audio_source; + item.mPosition = position; + item.mType = type; + item.mAssetID = assetid; + item.mOwnerID = ownerid; + item.mSourceID = sourceid; + item.mPlaying = true; + item.mTimeStarted = LLTimer::getElapsedSeconds(); + item.mTimeStopped = F64_MAX; + item.mIsTrigger = is_trigger; + item.mIsLooped = is_looped; + + item.mReviewed = false; + item.mReviewedCollision = false; + + gSoundHistory[id] = item; +} + +//static +void logSoundStop(LLUUID id) +{ + if(gSoundHistory.find(id) != gSoundHistory.end()) + { + gSoundHistory[id].mPlaying = false; + gSoundHistory[id].mTimeStopped = LLTimer::getElapsedSeconds(); + gSoundHistory[id].mAudioSource = NULL; // just in case + pruneSoundLog(); + } +} + +//static +void pruneSoundLog() +{ + if(++gSoundHistoryPruneCounter >= 64) + { + gSoundHistoryPruneCounter = 0; + while(gSoundHistory.size() > 256) + { + std::map::iterator iter = gSoundHistory.begin(); + std::map::iterator end = gSoundHistory.end(); + U64 lowest_time = (*iter).second.mTimeStopped; + LLUUID lowest_id = (*iter).first; + for( ; iter != end; ++iter) + { + if((*iter).second.mTimeStopped < lowest_time) + { + lowest_time = (*iter).second.mTimeStopped; + lowest_id = (*iter).first; + } + } + gSoundHistory.erase(lowest_id); + } + } +} +// diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 977050fb6..a37366dc2 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -139,10 +139,10 @@ public: // Owner ID is the owner of the object making the request void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, - // - //const LLVector3d &pos_global = LLVector3d::zero); - const LLVector3d &pos_global = LLVector3d::zero, - const LLUUID source_object = LLUUID::null); + // + //const LLVector3d &pos_global = LLVector3d::zero); + const LLVector3d &pos_global = LLVector3d::zero, + const LLUUID source_object = LLUUID::null); // bool preloadSound(const LLUUID &id); @@ -265,9 +265,9 @@ class LLAudioSource public: // owner_id is the id of the agent responsible for making this sound // play, for example, the owner of the object currently playing it - // - //LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); - LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, const LLUUID source_id = LLUUID::null, const bool isTrigger = true); + // + //LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); + LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, const LLUUID source_id = LLUUID::null, const bool isTrigger = true); // virtual ~LLAudioSource(); @@ -308,8 +308,8 @@ public: virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } const LLUUID &getID() const { return mID; } - // - const LLUUID &getLogID() const { return mLogID; } + // + const LLUUID &getLogID() const { return mLogID; } // bool isDone() const; bool isMuted() const { return mSourceMuted; } @@ -344,10 +344,10 @@ protected: S32 mType; LLVector3d mPositionGlobal; LLVector3 mVelocity; - // - LLUUID mLogID; - LLUUID mSourceID; - bool mIsTrigger; + // + LLUUID mLogID; + LLUUID mSourceID; + bool mIsTrigger; // //LLAudioSource *mSyncMasterp; // If we're a slave, the source that we're synced to. @@ -467,32 +467,32 @@ protected: extern LLAudioEngine* gAudiop; -// -typedef struct -{ - LLUUID mID; - LLVector3d mPosition; - S32 mType; - bool mPlaying; - LLUUID mAssetID; - LLUUID mOwnerID; - LLUUID mSourceID; - bool mIsTrigger; - bool mIsLooped; - F64 mTimeStarted; - F64 mTimeStopped; - bool mReviewed; - bool mReviewedCollision; - LLAudioSource* mAudioSource; -} LLSoundHistoryItem; - -extern std::map gSoundHistory; - -extern void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped); -extern void logSoundStop(LLUUID id); -extern void pruneSoundLog(); -extern int gSoundHistoryPruneCounter; - +// +typedef struct +{ + LLUUID mID; + LLVector3d mPosition; + S32 mType; + bool mPlaying; + LLUUID mAssetID; + LLUUID mOwnerID; + LLUUID mSourceID; + bool mIsTrigger; + bool mIsLooped; + F64 mTimeStarted; + F64 mTimeStopped; + bool mReviewed; + bool mReviewedCollision; + LLAudioSource* mAudioSource; +} LLSoundHistoryItem; + +extern std::map gSoundHistory; + +extern void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped); +extern void logSoundStop(LLUUID id); +extern void pruneSoundLog(); +extern int gSoundHistoryPruneCounter; + // #endif diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 6ed1c011a..6e010699c 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -40,7 +40,7 @@ #include "llhandmotion.h" #include "llcriticaldamp.h" - + //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index ad745f9c2..3313f372e 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -526,35 +526,35 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot) // } } -// -std::string LLJoint::exportString(U32 tabs) -{ - std::string out; - for(U32 i = 0; i < tabs; i++) out.append("\t"); - out.append("mName.c_str())); - LLVector3 position = getPosition(); - out.append(llformat("pos=\"<%f, %f, %f>\" ", position.mV[0], position.mV[1], position.mV[2])); - LLQuaternion rotation = getRotation(); - out.append(llformat("rot=\"<%f, %f, %f, %f>\" ", rotation.mQ[0], rotation.mQ[1], rotation.mQ[2], rotation.mQ[3])); - if(mChildren.empty()) - { - out.append("/>\n"); - } - else - { - out.append(">\n"); - int next_tab = tabs + 1; - child_list_t::iterator end = mChildren.end(); - for(child_list_t::iterator iter = mChildren.begin(); iter != end; ++iter) - { - out.append((*iter)->exportString(next_tab)); - } - for(U32 i = 0; i < tabs; i++) out.append("\t"); - out.append("\n"); - } - return out; -} -// - +// +std::string LLJoint::exportString(U32 tabs) +{ + std::string out; + for(U32 i = 0; i < tabs; i++) out.append("\t"); + out.append("mName.c_str())); + LLVector3 position = getPosition(); + out.append(llformat("pos=\"<%f, %f, %f>\" ", position.mV[0], position.mV[1], position.mV[2])); + LLQuaternion rotation = getRotation(); + out.append(llformat("rot=\"<%f, %f, %f, %f>\" ", rotation.mQ[0], rotation.mQ[1], rotation.mQ[2], rotation.mQ[3])); + if(mChildren.empty()) + { + out.append("/>\n"); + } + else + { + out.append(">\n"); + int next_tab = tabs + 1; + child_list_t::iterator end = mChildren.end(); + for(child_list_t::iterator iter = mChildren.begin(); iter != end; ++iter) + { + out.append((*iter)->exportString(next_tab)); + } + for(U32 i = 0; i < tabs; i++) out.append("\t"); + out.append("\n"); + } + return out; +} +// + // End diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 75114a223..b5507e1e4 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -178,10 +178,10 @@ public: S32 getJointNum() const { return mJointNum; } void setJointNum(S32 joint_num) { mJointNum = joint_num; } - - // - std::string exportString(U32 tabs = 0); - // + + // + std::string exportString(U32 tabs = 0); + // }; #endif // LL_LLJOINT_H diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index b28e7387d..bae409af9 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -468,14 +468,14 @@ LLMotion *LLKeyframeMotion::create(const LLUUID &id) //----------------------------------------------------------------------------- LLPointer& LLKeyframeMotion::getJointState(U32 index) { - // - //llassert_always (index < (S32)mJointStates.size()); - if(index >= (S32)mJointStates.size()) - { - llwarns << "LLKeyframeMotion::getJointState: index >= size" << llendl; - index = (S32)mJointStates.size() - 1; - } - // + // + //llassert_always (index < (S32)mJointStates.size()); + if(index >= (S32)mJointStates.size()) + { + llwarns << "LLKeyframeMotion::getJointState: index >= size" << llendl; + index = (S32)mJointStates.size() - 1; + } + // return mJointStates[index]; } @@ -484,11 +484,11 @@ LLPointer& LLKeyframeMotion::getJointState(U32 index) //----------------------------------------------------------------------------- LLJoint* LLKeyframeMotion::getJoint(U32 index) { - // - //llassert_always (index < (S32)mJointStates.size()); - if(index >= (S32)mJointStates.size()) - index = (S32)mJointStates.size() - 1; - // + // + //llassert_always (index < (S32)mJointStates.size()); + if(index >= (S32)mJointStates.size()) + index = (S32)mJointStates.size() - 1; + // LLJoint* joint = mJointStates[index]->getJoint(); llassert_always (joint); return joint; @@ -1383,18 +1383,18 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) } else { - // - int sz = joint_name.size(); - int i = 0; - while (i < sz) - { - if ('\a' == joint_name[i]) - { - joint_name.replace(i, 1, " "); - } - i++; - } - // + // + int sz = joint_name.size(); + int i = 0; + while (i < sz) + { + if ('\a' == joint_name[i]) + { + joint_name.replace(i, 1, " "); + } + i++; + } + // llwarns << "joint not found: " << joint_name << llendl; //return FALSE; } @@ -1673,15 +1673,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) str = (char*)bin_data; constraintp->mSourceConstraintVolume = mCharacter->getCollisionVolumeID(str); - // - if(constraintp->mSourceConstraintVolume == -1) - { - llwarns << "can't get source constraint volume" << llendl; - delete constraintp; - return FALSE; - } - // - + // + if(constraintp->mSourceConstraintVolume == -1) + { + llwarns << "can't get source constraint volume" << llendl; + delete constraintp; + return FALSE; + } + // + if (!dp.unpackVector3(constraintp->mSourceConstraintOffset, "source_offset")) { llwarns << "can't read constraint source offset" << llendl; diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp index 8e6a3edda..8c7cba0a1 100644 --- a/indra/llcharacter/llpose.cpp +++ b/indra/llcharacter/llpose.cpp @@ -158,9 +158,9 @@ void LLPose::setWeight(F32 weight) iter != mJointMap.end(); ++iter) { - // - // there was a crash here - // + // + // there was a crash here + // iter->second->setWeight(weight); } mWeight = weight; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 545a33aee..20007d812 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -38,7 +38,7 @@ const S32 LL_VERSION_MINOR = 4; const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; -const char * const LL_CHANNEL = "Snowglobe Test Build"; +const char * const LL_CHANNEL = "Ascent Test Build"; #if LL_DARWIN const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.snowglobe.viewer"; diff --git a/indra/llimage/aes.cpp b/indra/llimage/aes.cpp index aa8a7dbf8..2dc45ea35 100644 --- a/indra/llimage/aes.cpp +++ b/indra/llimage/aes.cpp @@ -1,1381 +1,1380 @@ - -//Rijndael.cpp - -#include -#include -#include -#include "aes.h" - -const int CRijndael::sm_alog[256] = -{ - 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, - 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, - 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, - 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, - 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, - 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, - 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, - 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, - 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, - 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, - 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, - 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, - 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, - 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, - 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, - 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1 -}; - -const int CRijndael::sm_log[256] = -{ - 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, - 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, - 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, - 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, - 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, - 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, - 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, - 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, - 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, - 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, - 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, - 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, - 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, - 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, - 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, - 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7 -}; - -const char CRijndael::sm_S[256] = -{ - 99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, - -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64, - -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, - 4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, - 9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124, - 83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, - -48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88, - 81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, - -51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, - 96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37, - -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, - -25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, - -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, - 112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, - -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33, - -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22 -}; - -const char CRijndael::sm_Si[256] = -{ - 82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, - 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, - 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, - 8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, - 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, - 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, - -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, - -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, - 58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, - -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, - 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, - -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, - 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, - 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, - -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, - 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125 -}; - -const int CRijndael::sm_T1[256] = -{ - -966564955, -126059388, -294160487, -159679603, - -855539, -697603139, -563122255, -1849309868, - 1613770832, 33620227, -832084055, 1445669757, - -402719207, -1244145822, 1303096294, -327780710, - -1882535355, 528646813, -1983264448, -92439161, - -268764651, -1302767125, -1907931191, -68095989, - 1101901292, -1277897625, 1604494077, 1169141738, - 597466303, 1403299063, -462261610, -1681866661, - 1974974402, -503448292, 1033081774, 1277568618, - 1815492186, 2118074177, -168298750, -2083730353, - 1748251740, 1369810420, -773462732, -101584632, - -495881837, -1411852173, 1647391059, 706024767, - 134480908, -1782069422, 1176707941, -1648114850, - 806885416, 932615841, 168101135, 798661301, - 235341577, 605164086, 461406363, -538779075, - -840176858, 1311188841, 2142417613, -361400929, - 302582043, 495158174, 1479289972, 874125870, - 907746093, -596742478, -1269146898, 1537253627, - -1538108682, 1983593293, -1210657183, 2108928974, - 1378429307, -572267714, 1580150641, 327451799, - -1504488459, -1177431704, 0, -1041371860, - 1075847264, -469959649, 2041688520, -1235526675, - -731223362, -1916023994, 1740553945, 1916352843, - -1807070498, -1739830060, -1336387352, -2049978550, - -1143943061, -974131414, 1336584933, -302253290, - -2042412091, -1706209833, 1714631509, 293963156, - -1975171633, -369493744, 67240454, -25198719, - -1605349136, 2017213508, 631218106, 1269344483, - -1571728909, 1571005438, -2143272768, 93294474, - 1066570413, 563977660, 1882732616, -235539196, - 1673313503, 2008463041, -1344611723, 1109467491, - 537923632, -436207846, -34344178, -1076702611, - -2117218996, 403442708, 638784309, -1007883217, - -1101045791, 899127202, -2008791860, 773265209, - -1815821225, 1437050866, -58818942, 2050833735, - -932944724, -1168286233, 840505643, -428641387, - -1067425632, 427917720, -1638969391, -1545806721, - 1143087718, 1412049534, 999329963, 193497219, - -1941551414, -940642775, 1807268051, 672404540, - -1478566279, -1134666014, 369822493, -1378100362, - -606019525, 1681011286, 1949973070, 336202270, - -1840690725, 201721354, 1210328172, -1201906460, - -1614626211, -1110191250, 1135389935, -1000185178, - 965841320, 831886756, -739974089, -226920053, - -706222286, -1949775805, 1849112409, -630362697, - 26054028, -1311386268, -1672589614, 1235855840, - -663982924, -1403627782, -202050553, -806688219, - -899324497, -193299826, 1202630377, 268961816, - 1874508501, -260540280, 1243948399, 1546530418, - 941366308, 1470539505, 1941222599, -1748580783, - -873928669, -1579295364, -395021156, 1042226977, - -1773450275, 1639824860, 227249030, 260737669, - -529502064, 2084453954, 1907733956, -865704278, - -1874310952, 100860677, -134810111, 470683154, - -1033805405, 1781871967, -1370007559, 1773779408, - 394692241, -1715355304, 974986535, 664706745, - -639508168, -336005101, 731420851, 571543859, - -764843589, -1445340816, 126783113, 865375399, - 765172662, 1008606754, 361203602, -907417312, - -2016489911, -1437248001, 1344809080, -1512054918, - 59542671, 1503764984, 160008576, 437062935, - 1707065306, -672733647, -2076032314, -798463816, - -2109652541, 697932208, 1512910199, 504303377, - 2075177163, -1470868228, 1841019862, 739644986 -}; - -const int CRijndael::sm_T2[256] = -{ - -1513725085, -2064089988, -1712425097, -1913226373, - 234877682, -1110021269, -1310822545, 1418839493, - 1348481072, 50462977, -1446090905, 2102799147, - 434634494, 1656084439, -431117397, -1695779210, - 1167051466, -1658879358, 1082771913, -2013627011, - 368048890, -340633255, -913422521, 201060592, - -331240019, 1739838676, -44064094, -364531793, - -1088185188, -145513308, -1763413390, 1536934080, - -1032472649, 484572669, -1371696237, 1783375398, - 1517041206, 1098792767, 49674231, 1334037708, - 1550332980, -195975771, 886171109, 150598129, - -1813876367, 1940642008, 1398944049, 1059722517, - 201851908, 1385547719, 1699095331, 1587397571, - 674240536, -1590192490, 252314885, -1255171430, - 151914247, 908333586, -1692696448, 1038082786, - 651029483, 1766729511, -847269198, -1612024459, - 454166793, -1642232957, 1951935532, 775166490, - 758520603, -1294176658, -290170278, -77881184, - -157003182, 1299594043, 1639438038, -830622797, - 2068982057, 1054729187, 1901997871, -1760328572, - -173649069, 1757008337, 0, 750906861, - 1614815264, 535035132, -931548751, -306816165, - -1093375382, 1183697867, -647512386, 1265776953, - -560706998, -728216500, -391096232, 1250283471, - 1807470800, 717615087, -447763798, 384695291, - -981056701, -677753523, 1432761139, -1810791035, - -813021883, 283769337, 100925954, -2114027649, - -257929136, 1148730428, -1171939425, -481580888, - -207466159, -27417693, -1065336768, -1979347057, - -1388342638, -1138647651, 1215313976, 82966005, - -547111748, -1049119050, 1974459098, 1665278241, - 807407632, 451280895, 251524083, 1841287890, - 1283575245, 337120268, 891687699, 801369324, - -507617441, -1573546089, -863484860, 959321879, - 1469301956, -229267545, -2097381762, 1199193405, - -1396153244, -407216803, 724703513, -1780059277, - -1598005152, -1743158911, -778154161, 2141445340, - 1715741218, 2119445034, -1422159728, -2096396152, - -896776634, 700968686, -747915080, 1009259540, - 2041044702, -490971554, 487983883, 1991105499, - 1004265696, 1449407026, 1316239930, 504629770, - -611169975, 168560134, 1816667172, -457679780, - 1570751170, 1857934291, -280777556, -1497079198, - -1472622191, -1540254315, 936633572, -1947043463, - 852879335, 1133234376, 1500395319, -1210421907, - -1946055283, 1689376213, -761508274, -532043351, - -1260884884, -89369002, 133428468, 634383082, - -1345690267, -1896580486, -381178194, 403703816, - -714097990, -1997506440, 1867130149, 1918643758, - 607656988, -245913946, -948718412, 1368901318, - 600565992, 2090982877, -1662487436, 557719327, - -577352885, -597574211, -2045932661, -2062579062, - -1864339344, 1115438654, -999180875, -1429445018, - -661632952, 84280067, 33027830, 303828494, - -1547542175, 1600795957, -106014889, -798377543, - -1860729210, 1486471617, 658119965, -1188585826, - 953803233, 334231800, -1288988520, 857870609, - -1143838359, 1890179545, -1995993458, -1489791852, - -1238525029, 574365214, -1844082809, 550103529, - 1233637070, -5614251, 2018519080, 2057691103, - -1895592820, -128343647, -2146858615, 387583245, - -630865985, 836232934, -964410814, -1194301336, - -1014873791, -1339450983, 2002398509, 287182607, - -881086288, -56077228, -697451589, 975967766 -}; - -const int CRijndael::sm_T3[256] = -{ - 1671808611, 2089089148, 2006576759, 2072901243, - -233963534, 1807603307, 1873927791, -984313403, - 810573872, 16974337, 1739181671, 729634347, - -31856642, -681396777, -1410970197, 1989864566, - -901410870, -2103631998, -918517303, 2106063485, - -99225606, 1508618841, 1204391495, -267650064, - -1377025619, -731401260, -1560453214, -1343601233, - -1665195108, -1527295068, 1922491506, -1067738176, - -1211992649, -48438787, -1817297517, 644500518, - 911895606, 1061256767, -150800905, -867204148, - 878471220, -1510714971, -449523227, -251069967, - 1905517169, -663508008, 827548209, 356461077, - 67897348, -950889017, 593839651, -1017209405, - 405286936, -1767819370, 84871685, -1699401830, - 118033927, 305538066, -2137318528, -499261470, - -349778453, 661212711, -1295155278, 1973414517, - 152769033, -2086789757, 745822252, 439235610, - 455947803, 1857215598, 1525593178, -1594139744, - 1391895634, 994932283, -698239018, -1278313037, - 695947817, -482419229, 795958831, -2070473852, - 1408607827, -781665839, 0, -315833875, - 543178784, -65018884, -1312261711, 1542305371, - 1790891114, -884568629, -1093048386, 961245753, - 1256100938, 1289001036, 1491644504, -817199665, - -798245936, -282409489, -1427812438, -82383365, - 1137018435, 1305975373, 861234739, -2053893755, - 1171229253, -116332039, 33948674, 2139225727, - 1357946960, 1011120188, -1615190625, -1461498968, - 1374921297, -1543610973, 1086357568, -1886780017, - -1834139758, -1648615011, 944271416, -184225291, - -1126210628, -1228834890, -629821478, 560153121, - 271589392, -15014401, -217121293, -764559406, - -850624051, 202643468, 322250259, -332413972, - 1608629855, -1750977129, 1154254916, 389623319, - -1000893500, -1477290585, 2122513534, 1028094525, - 1689045092, 1575467613, 422261273, 1939203699, - 1621147744, -2120738431, 1339137615, -595614756, - 577127458, 712922154, -1867826288, -2004677752, - 1187679302, -299251730, -1194103880, 339486740, - -562452514, 1591917662, 186455563, -612979237, - -532948000, 844522546, 978220090, 169743370, - 1239126601, 101321734, 611076132, 1558493276, - -1034051646, -747717165, -1393605716, 1655096418, - -1851246191, -1784401515, -466103324, 2039214713, - -416098841, -935097400, 928607799, 1840765549, - -1920204403, -714821163, 1322425422, -1444918871, - 1823791212, 1459268694, -200805388, -366620694, - 1706019429, 2056189050, -1360443474, 135794696, - -1160417350, 2022240376, 628050469, 779246638, - 472135708, -1494132826, -1261997132, -967731258, - -400307224, -579034659, 1956440180, 522272287, - 1272813131, -1109630531, -1954148981, -1970991222, - 1888542832, 1044544574, -1245417035, 1722469478, - 1222152264, 50660867, -167643146, 236067854, - 1638122081, 895445557, 1475980887, -1177523783, - -2037311610, -1051158079, 489110045, -1632032866, - -516367903, -132912136, -1733088360, 288563729, - 1773916777, -646927911, -1903622258, -1800981612, - -1682559589, 505560094, -2020469369, -383727127, - -834041906, 1442818645, 678973480, -545610273, - -1936784500, -1577559647, -1988097655, 219617805, - -1076206145, -432941082, 1120306242, 1756942440, - 1103331905, -1716508263, 762796589, 252780047, - -1328841808, 1425844308, -1143575109, 372911126 -}; - -const int CRijndael::sm_T4[256] = -{ - 1667474886, 2088535288, 2004326894, 2071694838, - -219017729, 1802223062, 1869591006, -976923503, - 808472672, 16843522, 1734846926, 724270422, - -16901657, -673750347, -1414797747, 1987484396, - -892713585, -2105369313, -909557623, 2105378810, - -84273681, 1499065266, 1195886990, -252703749, - -1381110719, -724277325, -1566376609, -1347425723, - -1667449053, -1532692653, 1920112356, -1061135461, - -1212693899, -33743647, -1819038147, 640051788, - 909531756, 1061110142, -134806795, -859025533, - 875846760, -1515850671, -437963567, -235861767, - 1903268834, -656903253, 825316194, 353713962, - 67374088, -943238507, 589522246, -1010606435, - 404236336, -1768513225, 84217610, -1701137105, - 117901582, 303183396, -2139055333, -488489505, - -336910643, 656894286, -1296904833, 1970642922, - 151591698, -2088526307, 741110872, 437923380, - 454765878, 1852748508, 1515908788, -1600062629, - 1381168804, 993742198, -690593353, -1280061827, - 690584402, -471646499, 791638366, -2071685357, - 1398011302, -774805319, 0, -303223615, - 538992704, -50585629, -1313748871, 1532751286, - 1785380564, -875870579, -1094788761, 960056178, - 1246420628, 1280103576, 1482221744, -808498555, - -791647301, -269538619, -1431640753, -67430675, - 1128514950, 1296947098, 859002214, -2054843375, - 1162203018, -101117719, 33687044, 2139062782, - 1347481760, 1010582648, -1616922075, -1465326773, - 1364325282, -1549533603, 1077985408, -1886418427, - -1835881153, -1650607071, 943212656, -168491791, - -1128472733, -1229536905, -623217233, 555836226, - 269496352, -58651, -202174723, -757961281, - -842183551, 202118168, 320025894, -320065597, - 1600119230, -1751670219, 1145359496, 387397934, - -993765485, -1482165675, 2122220284, 1027426170, - 1684319432, 1566435258, 421079858, 1936954854, - 1616945344, -2122213351, 1330631070, -589529181, - 572679748, 707427924, -1869567173, -2004319477, - 1179044492, -286381625, -1195846805, 336870440, - -555845209, 1583276732, 185277718, -606374227, - -522175525, 842159716, 976899700, 168435220, - 1229577106, 101059084, 606366792, 1549591736, - -1027449441, -741118275, -1397952701, 1650632388, - -1852725191, -1785355215, -454805549, 2038008818, - -404278571, -926399605, 926374254, 1835907034, - -1920103423, -707435343, 1313788572, -1448484791, - 1819063512, 1448540844, -185333773, -353753649, - 1701162954, 2054852340, -1364268729, 134748176, - -1162160785, 2021165296, 623210314, 774795868, - 471606328, -1499008681, -1263220877, -960081513, - -387439669, -572687199, 1953799400, 522133822, - 1263263126, -1111630751, -1953790451, -1970633457, - 1886425312, 1044267644, -1246378895, 1718004428, - 1212733584, 50529542, -151649801, 235803164, - 1633788866, 892690282, 1465383342, -1179004823, - -2038001385, -1044293479, 488449850, -1633765081, - -505333543, -117959701, -1734823125, 286339874, - 1768537042, -640061271, -1903261433, -1802197197, - -1684294099, 505291324, -2021158379, -370597687, - -825341561, 1431699370, 673740880, -539002203, - -1936945405, -1583220647, -1987477495, 218961690, - -1077945755, -421121577, 1111672452, 1751693520, - 1094828930, -1717981143, 757954394, 252645662, - -1330590853, 1414855848, -1145317779, 370555436 -}; - -const int CRijndael::sm_T5[256] = -{ - 1374988112, 2118214995, 437757123, 975658646, - 1001089995, 530400753, -1392879445, 1273168787, - 540080725, -1384747530, -1999866223, -184398811, - 1340463100, -987051049, 641025152, -1251826801, - -558802359, 632953703, 1172967064, 1576976609, - -1020300030, -2125664238, -1924753501, 1809054150, - 59727847, 361929877, -1083344149, -1789765158, - -725712083, 1484005843, 1239443753, -1899378620, - 1975683434, -191989384, -1722270101, 666464733, - -1092530250, -259478249, -920605594, 2110667444, - 1675577880, -451268222, -1756286112, 1649639237, - -1318815776, -1150570876, -25059300, -116905068, - 1883793496, -1891238631, -1797362553, 1383856311, - -1418472669, 1917518562, -484470953, 1716890410, - -1293211641, 800440835, -2033878118, -751368027, - 807962610, 599762354, 33778362, -317291940, - -1966138325, -1485196142, -217582864, 1315562145, - 1708848333, 101039829, -785096161, -995688822, - 875451293, -1561111136, 92987698, -1527321739, - 193195065, 1080094634, 1584504582, -1116860335, - 1042385657, -1763899843, -583137874, 1306967366, - -1856729675, 1908694277, 67556463, 1615861247, - 429456164, -692196969, -1992277044, 1742315127, - -1326955843, 126454664, -417768648, 2043211483, - -1585706425, 2084704233, -125559095, 0, - 159417987, 841739592, 504459436, 1817866830, - -49348613, 260388950, 1034867998, 908933415, - 168810852, 1750902305, -1688513327, 607530554, - 202008497, -1822955761, -1259432238, 463180190, - -2134850225, 1641816226, 1517767529, 470948374, - -493635062, -1063245083, 1008918595, 303765277, - 235474187, -225720403, 766945465, 337553864, - 1475418501, -1351284916, -291906117, -1551933187, - -150919521, 1551037884, 1147550661, 1543208500, - -1958532746, -886847780, -1225917336, -1192955549, - -684598070, 1113818384, 328671808, -2067394272, - -2058738563, -759480840, -1359400431, -953573011, - 496906059, -592301837, 226906860, 2009195472, - 733156972, -1452230247, 294930682, 1206477858, - -1459843900, -1594867942, 1451044056, 573804783, - -2025238841, -650587711, -1932877058, -1730933962, - -1493859889, -1518674392, -625504730, 1068351396, - 742039012, 1350078989, 1784663195, 1417561698, - -158526526, -1864845080, 775550814, -2101104651, - -1621262146, 1775276924, 1876241833, -819653965, - -928212677, 270040487, -392404114, -616842373, - -853116919, 1851332852, -325404927, -2091935064, - -426414491, -1426069890, 566021896, -283776794, - -1159226407, 1248802510, -358676012, 699432150, - 832877231, 708780849, -962227152, 899835584, - 1951317047, -58537306, -527380304, 866637845, - -251357110, 1106041591, 2144161806, 395441711, - 1984812685, 1139781709, -861254316, -459930401, - -1630423581, 1282050075, -1054072904, 1181045119, - -1654724092, 25965917, -91786125, -83148498, - -1285087910, -1831087534, -384805325, 1842759443, - -1697160820, 933301370, 1509430414, -351060855, - -827774994, -1218328267, -518199827, 2051518780, - -1663901863, 1441952575, 404016761, 1942435775, - 1408749034, 1610459739, -549621996, 2017778566, - -894438527, -1184316354, 941896748, -1029488545, - 371049330, -1126030068, 675039627, -15887039, - 967311729, 135050206, -659233636, 1683407248, - 2076935265, -718096784, 1215061108, -793225406 -}; - -const int CRijndael::sm_T6[256] = -{ - 1347548327, 1400783205, -1021700188, -1774573730, - -885281941, -249586363, -1414727080, -1823743229, - 1428173050, -156404115, -1853305738, 636813900, - -61872681, -674944309, -2144979644, -1883938141, - 1239331162, 1730525723, -1740248562, -513933632, - 46346101, 310463728, -1551022441, -966011911, - -419197089, -1793748324, -339776134, -627748263, - 768917123, -749177823, 692707433, 1150208456, - 1786102409, 2029293177, 1805211710, -584599183, - -1229004465, 401639597, 1724457132, -1266823622, - 409198410, -2098914767, 1620529459, 1164071807, - -525245321, -2068091986, 486441376, -1795618773, - 1483753576, 428819965, -2020286868, -1219331080, - 598438867, -495826174, 1474502543, 711349675, - 129166120, 53458370, -1702443653, -1512884472, - -231724921, -1306280027, -1174273174, 1559041666, - 730517276, -1834518092, -252508174, -1588696606, - -848962828, -721025602, 533804130, -1966823682, - -1657524653, -1599933611, 839224033, 1973745387, - 957055980, -1438621457, 106852767, 1371368976, - -113368694, 1033297158, -1361232379, 1179510461, - -1248766835, 91341917, 1862534868, -10465259, - 605657339, -1747534359, -863420349, 2003294622, - -1112479678, -2012771957, 954669403, -612775698, - 1201765386, -377732593, -906460130, 0, - -2096529274, 1211247597, -1407315600, 1315723890, - -67301633, 1443857720, 507358933, 657861945, - 1678381017, 560487590, -778347692, 975451694, - -1324610969, 261314535, -759894378, -1642357871, - 1333838021, -1570644960, 1767536459, 370938394, - 182621114, -440360918, 1128014560, 487725847, - 185469197, -1376613433, -1188186456, -938205527, - -2057834215, 1286567175, -1141990947, -39616672, - -1611202266, -1134791947, -985373125, 878443390, - 1988838185, -590666810, 1756818940, 1673061617, - -891866660, 272786309, 1075025698, 545572369, - 2105887268, -120407235, 296679730, 1841768865, - 1260232239, -203640272, -334657966, -797457949, - 1814803222, -1716948807, -99511224, 575138148, - -995558260, 446754879, -665420500, -282971248, - -947435186, -1042728751, -24327518, 915985419, - -811141759, 681933534, 651868046, -1539330625, - -466863459, 223377554, -1687527476, 1649704518, - -1024029421, -393160520, 1580087799, -175979601, - -1096852096, 2087309459, -1452288723, -1278270190, - 1003007129, -1492117379, 1860738147, 2077965243, - 164439672, -194094824, 32283319, -1467789414, - 1709610350, 2125135846, 136428751, -420538904, - -642062437, -833982666, -722821367, -701910916, - -1355701070, 824852259, 818324884, -1070226842, - 930369212, -1493400886, -1327460144, 355706840, - 1257309336, -146674470, 243256656, 790073846, - -1921626666, 1296297904, 1422699085, -538667516, - -476130891, 457992840, -1195299809, 2135319889, - 77422314, 1560382517, 1945798516, 788204353, - 1521706781, 1385356242, 870912086, 325965383, - -1936009375, 2050466060, -1906706412, -1981082820, - -288446169, 901210569, -304014107, 1014646705, - 1503449823, 1062597235, 2031621326, -1082931401, - -363595827, 1533017514, 350174575, -2038938405, - -2117423117, 1052338372, 741876788, 1606591296, - 1914052035, 213705253, -1960297399, 1107234197, - 1899603969, -569897805, -1663519516, -1872472383, - 1635502980, 1893020342, 1950903388, 1120974935 -}; - -const int CRijndael::sm_T7[256] = -{ - -1487908364, 1699970625, -1530717673, 1586903591, - 1808481195, 1173430173, 1487645946, 59984867, - -95084496, 1844882806, 1989249228, 1277555970, - -671330331, -875051734, 1149249077, -1550863006, - 1514790577, 459744698, 244860394, -1058972162, - 1963115311, -267222708, -1750889146, -104436781, - 1608975247, -1667951214, 2062270317, 1507497298, - -2094148418, 567498868, 1764313568, -935031095, - -1989511742, 2037970062, 1047239000, 1910319033, - 1337376481, -1390940024, -1402549984, 984907214, - 1243112415, 830661914, 861968209, 2135253587, - 2011214180, -1367032981, -1608712575, 731183368, - 1750626376, -48656571, 1820824798, -122203525, - -752637069, 48394827, -1890065633, -1423284651, - 671593195, -1039978571, 2073724613, 145085239, - -2014171096, -1515052097, 1790575107, -2107839210, - 472615631, -1265457287, -219090169, -492745111, - -187865638, -1093335547, 1646252340, -24460122, - 1402811438, 1436590835, -516815478, -344611594, - -331805821, -274055072, -1626972559, 273792366, - -1963377119, 104699613, 95345982, -1119466010, - -1917480620, 1560637892, -730921978, 369057872, - -81520232, -375925059, 1137477952, -1636341799, - 1119727848, -1954019447, 1530455833, -287606328, - 172466556, 266959938, 516552836, 0, - -2038232704, -314035669, 1890328081, 1917742170, - -262898, 945164165, -719438418, 958871085, - -647755249, -1507760036, 1423022939, 775562294, - 1739656202, -418409641, -1764576018, -1851909221, - -984645440, 547512796, 1265195639, 437656594, - -1173691757, 719700128, -532464606, 387781147, - 218828297, -944901493, -1464259146, -1446505442, - 428169201, 122466165, -574886247, 1627235199, - 648017665, -172204942, 1002783846, 2117360635, - 695634755, -958608605, -60246291, -245122844, - -590686415, -2062531997, 574624663, 287343814, - 612205898, 1039717051, 840019705, -1586641111, - 793451934, 821288114, 1391201670, -472877119, - 376187827, -1181111952, 1224348052, 1679968233, - -1933268740, 1058709744, 752375421, -1863376333, - 1321699145, -775825096, -1560376118, 188127444, - -2117097739, -567761542, -1910056265, -1079754835, - -1645990854, -1844621192, -862229921, 1180849278, - 331544205, -1192718120, -144822727, -1342864701, - -2134991011, -1820562992, 766078933, 313773861, - -1724135252, 2108100632, 1668212892, -1149510853, - 2013908262, 418672217, -1224610662, -1700232369, - 1852171925, -427906305, -821550660, -387518699, - -1680229657, 919489135, 164948639, 2094410160, - -1297141340, 590424639, -1808742747, 1723872674, - -1137216434, -895026046, -793714544, -669699161, - -1739919100, -621329940, 1343127501, -164685935, - -695372211, -1337113617, 1297403050, 81781910, - -1243373871, -2011476886, 532201772, 1367295589, - -368796322, 895287692, 1953757831, 1093597963, - 492483431, -766340389, 1446242576, 1192455638, - 1636604631, 209336225, 344873464, 1015671571, - 669961897, -919226527, -437395172, -1321436601, - -547775278, 1933530610, -830924780, 935293895, - -840281097, -1436852227, 1863638845, -611944380, - -209597777, -1002522264, 875313188, 1080017571, - -1015933411, 621591778, 1233856572, -1790836979, - 24197544, -1277294580, -459482956, -1047501738, - -2073986101, -1234119374, 1551124588, 1463996600 -}; - -const int CRijndael::sm_T8[256] = -{ - -190361519, 1097159550, 396673818, 660510266, - -1418998981, -1656360673, -94852180, -486304949, - 821712160, 1986918061, -864644728, 38544885, - -438830001, 718002117, 893681702, 1654886325, - -1319482914, -1172609243, -368142267, -20913827, - 796197571, 1290801793, 1184342925, -738605461, - -1889540349, -1835231979, 1836772287, 1381620373, - -1098699308, 1948373848, -529979063, -909622130, - -1031181707, -1904641804, 1480485785, -1183720153, - -514869570, -2001922064, 548169417, -835013507, - -548792221, 439452389, 1362321559, 1400849762, - 1685577905, 1806599355, -2120213250, 137073913, - 1214797936, 1174215055, -563312748, 2079897426, - 1943217067, 1258480242, 529487843, 1437280870, - -349698126, -1245576401, -981755258, 923313619, - 679998000, -1079659997, 57326082, 377642221, - -820237430, 2041877159, 133361907, 1776460110, - -621490843, 96392454, 878845905, -1493267772, - 777231668, -212492126, -1964953083, -152341084, - -2081670901, 1626319424, 1906247262, 1846563261, - 562755902, -586793578, 1040559837, -423803315, - 1418573201, -1000536719, 114585348, 1343618912, - -1728371687, -1108764714, 1078185097, -643926169, - -398279248, -1987344377, 425408743, -923870343, - 2081048481, 1108339068, -2078357000, 0, - -2138668279, 736970802, 292596766, 1517440620, - 251657213, -2059905521, -1361764803, 758720310, - 265905162, 1554391400, 1532285339, 908999204, - 174567692, 1474760595, -292105548, -1684955621, - -1060810880, -601841055, 2001430874, 303699484, - -1816524062, -1607801408, 585122620, 454499602, - 151849742, -1949848078, -1230456531, 514443284, - -249985705, 1963412655, -1713521682, 2137062819, - 19308535, 1928707164, 1715193156, -75615141, - 1126790795, 600235211, -302225226, -453942344, - 836553431, 1669664834, -1759363053, -971956092, - 1243905413, -1153566510, -114159186, 698445255, - -1641067747, -1305414692, -2041385971, -1042034569, - -1290376149, 1891211689, -1807156719, -379313593, - -57883480, -264299872, 2100090966, 865136418, - 1229899655, 953270745, -895287668, -737462632, - -176042074, 2061379749, -1215420710, -1379949505, - 983426092, 2022837584, 1607244650, 2118541908, - -1928084746, -658970480, 972512814, -1011878526, - 1568718495, -795640727, -718427793, 621982671, - -1399243832, 410887952, -1671205144, 1002142683, - 645401037, 1494807662, -1699282452, 1335535747, - -1787927066, -1671510, -1127282655, 367585007, - -409216582, 1865862730, -1626745622, -1333995991, - -1531793615, 1059270954, -1517014842, -1570324427, - 1320957812, -2100648196, -1865371424, -1479011021, - 77089521, -321194175, -850391425, -1846137065, - 1305906550, -273658557, -1437772596, -1778065436, - -776608866, 1787304780, 740276417, 1699839814, - 1592394909, -1942659839, -2022411270, 188821243, - 1729977011, -606973294, 274084841, -699985043, - -681472870, -1593017801, -132870567, 322734571, - -1457000754, 1640576439, 484830689, 1202797690, - -757114468, -227328171, 349075736, -952647821, - -137500077, -39167137, 1030690015, 1155237496, - -1342996022, 1757691577, 607398968, -1556062270, - 499347990, -500888388, 1011452712, 227885567, - -1476300487, 213114376, -1260086056, 1455525988, - -880516741, 850817237, 1817998408, -1202240816 -}; - -const int CRijndael::sm_U1[256] = -{ - 0, 235474187, 470948374, 303765277, - 941896748, 908933415, 607530554, 708780849, - 1883793496, 2118214995, 1817866830, 1649639237, - 1215061108, 1181045119, 1417561698, 1517767529, - -527380304, -291906117, -58537306, -225720403, - -659233636, -692196969, -995688822, -894438527, - -1864845080, -1630423581, -1932877058, -2101104651, - -1459843900, -1493859889, -1259432238, -1159226407, - -616842373, -718096784, -953573011, -920605594, - -484470953, -317291940, -15887039, -251357110, - -1418472669, -1518674392, -1218328267, -1184316354, - -1822955761, -1654724092, -1891238631, -2125664238, - 1001089995, 899835584, 666464733, 699432150, - 59727847, 226906860, 530400753, 294930682, - 1273168787, 1172967064, 1475418501, 1509430414, - 1942435775, 2110667444, 1876241833, 1641816226, - -1384747530, -1551933187, -1318815776, -1083344149, - -1789765158, -1688513327, -1992277044, -2025238841, - -583137874, -751368027, -1054072904, -819653965, - -451268222, -351060855, -116905068, -150919521, - 1306967366, 1139781709, 1374988112, 1610459739, - 1975683434, 2076935265, 1775276924, 1742315127, - 1034867998, 866637845, 566021896, 800440835, - 92987698, 193195065, 429456164, 395441711, - 1984812685, 2017778566, 1784663195, 1683407248, - 1315562145, 1080094634, 1383856311, 1551037884, - 101039829, 135050206, 437757123, 337553864, - 1042385657, 807962610, 573804783, 742039012, - -1763899843, -1730933962, -1966138325, -2067394272, - -1359400431, -1594867942, -1293211641, -1126030068, - -426414491, -392404114, -91786125, -191989384, - -558802359, -793225406, -1029488545, -861254316, - 1106041591, 1340463100, 1576976609, 1408749034, - 2043211483, 2009195472, 1708848333, 1809054150, - 832877231, 1068351396, 766945465, 599762354, - 159417987, 126454664, 361929877, 463180190, - -1585706425, -1351284916, -1116860335, -1285087910, - -1722270101, -1756286112, -2058738563, -1958532746, - -785096161, -549621996, -853116919, -1020300030, - -384805325, -417768648, -184398811, -83148498, - -1697160820, -1797362553, -2033878118, -1999866223, - -1561111136, -1392879445, -1092530250, -1326955843, - -358676012, -459930401, -158526526, -125559095, - -759480840, -592301837, -827774994, -1063245083, - 2051518780, 1951317047, 1716890410, 1750902305, - 1113818384, 1282050075, 1584504582, 1350078989, - 168810852, 67556463, 371049330, 404016761, - 841739592, 1008918595, 775550814, 540080725, - -325404927, -493635062, -259478249, -25059300, - -725712083, -625504730, -928212677, -962227152, - -1663901863, -1831087534, -2134850225, -1899378620, - -1527321739, -1426069890, -1192955549, -1225917336, - 202008497, 33778362, 270040487, 504459436, - 875451293, 975658646, 675039627, 641025152, - 2084704233, 1917518562, 1615861247, 1851332852, - 1147550661, 1248802510, 1484005843, 1451044056, - 933301370, 967311729, 733156972, 632953703, - 260388950, 25965917, 328671808, 496906059, - 1206477858, 1239443753, 1543208500, 1441952575, - 2144161806, 1908694277, 1675577880, 1842759443, - -684598070, -650587711, -886847780, -987051049, - -283776794, -518199827, -217582864, -49348613, - -1485196142, -1452230247, -1150570876, -1251826801, - -1621262146, -1856729675, -2091935064, -1924753501 -}; - -const int CRijndael::sm_U2[256] = -{ - 0, 185469197, 370938394, 487725847, - 741876788, 657861945, 975451694, 824852259, - 1483753576, 1400783205, 1315723890, 1164071807, - 1950903388, 2135319889, 1649704518, 1767536459, - -1327460144, -1141990947, -1493400886, -1376613433, - -1663519516, -1747534359, -1966823682, -2117423117, - -393160520, -476130891, -24327518, -175979601, - -995558260, -811141759, -759894378, -642062437, - 2077965243, 1893020342, 1841768865, 1724457132, - 1474502543, 1559041666, 1107234197, 1257309336, - 598438867, 681933534, 901210569, 1052338372, - 261314535, 77422314, 428819965, 310463728, - -885281941, -1070226842, -584599183, -701910916, - -419197089, -334657966, -249586363, -99511224, - -1823743229, -1740248562, -2057834215, -1906706412, - -1082931401, -1266823622, -1452288723, -1570644960, - -156404115, -39616672, -525245321, -339776134, - -627748263, -778347692, -863420349, -947435186, - -1361232379, -1512884472, -1195299809, -1278270190, - -2098914767, -1981082820, -1795618773, -1611202266, - 1179510461, 1296297904, 1347548327, 1533017514, - 1786102409, 1635502980, 2087309459, 2003294622, - 507358933, 355706840, 136428751, 53458370, - 839224033, 957055980, 605657339, 790073846, - -1921626666, -2038938405, -1687527476, -1872472383, - -1588696606, -1438621457, -1219331080, -1134791947, - -721025602, -569897805, -1021700188, -938205527, - -113368694, -231724921, -282971248, -466863459, - 1033297158, 915985419, 730517276, 545572369, - 296679730, 446754879, 129166120, 213705253, - 1709610350, 1860738147, 1945798516, 2029293177, - 1239331162, 1120974935, 1606591296, 1422699085, - -146674470, -61872681, -513933632, -363595827, - -612775698, -797457949, -848962828, -966011911, - -1355701070, -1539330625, -1188186456, -1306280027, - -2096529274, -2012771957, -1793748324, -1642357871, - 1201765386, 1286567175, 1371368976, 1521706781, - 1805211710, 1620529459, 2105887268, 1988838185, - 533804130, 350174575, 164439672, 46346101, - 870912086, 954669403, 636813900, 788204353, - -1936009375, -2020286868, -1702443653, -1853305738, - -1599933611, -1414727080, -1229004465, -1112479678, - -722821367, -538667516, -1024029421, -906460130, - -120407235, -203640272, -288446169, -440360918, - 1014646705, 930369212, 711349675, 560487590, - 272786309, 457992840, 106852767, 223377554, - 1678381017, 1862534868, 1914052035, 2031621326, - 1211247597, 1128014560, 1580087799, 1428173050, - 32283319, 182621114, 401639597, 486441376, - 768917123, 651868046, 1003007129, 818324884, - 1503449823, 1385356242, 1333838021, 1150208456, - 1973745387, 2125135846, 1673061617, 1756818940, - -1324610969, -1174273174, -1492117379, -1407315600, - -1657524653, -1774573730, -1960297399, -2144979644, - -377732593, -495826174, -10465259, -194094824, - -985373125, -833982666, -749177823, -665420500, - 2050466060, 1899603969, 1814803222, 1730525723, - 1443857720, 1560382517, 1075025698, 1260232239, - 575138148, 692707433, 878443390, 1062597235, - 243256656, 91341917, 409198410, 325965383, - -891866660, -1042728751, -590666810, -674944309, - -420538904, -304014107, -252508174, -67301633, - -1834518092, -1716948807, -2068091986, -1883938141, - -1096852096, -1248766835, -1467789414, -1551022441, -}; - -const int CRijndael::sm_U3[256] = -{ - 0, 218828297, 437656594, 387781147, - 875313188, 958871085, 775562294, 590424639, - 1750626376, 1699970625, 1917742170, 2135253587, - 1551124588, 1367295589, 1180849278, 1265195639, - -793714544, -574886247, -895026046, -944901493, - -459482956, -375925059, -24460122, -209597777, - -1192718120, -1243373871, -1560376118, -1342864701, - -1933268740, -2117097739, -1764576018, -1680229657, - -1149510853, -1234119374, -1586641111, -1402549984, - -1890065633, -2107839210, -1790836979, -1739919100, - -752637069, -567761542, -919226527, -1002522264, - -418409641, -368796322, -48656571, -267222708, - 1808481195, 1723872674, 1910319033, 2094410160, - 1608975247, 1391201670, 1173430173, 1224348052, - 59984867, 244860394, 428169201, 344873464, - 935293895, 984907214, 766078933, 547512796, - 1844882806, 1627235199, 2011214180, 2062270317, - 1507497298, 1423022939, 1137477952, 1321699145, - 95345982, 145085239, 532201772, 313773861, - 830661914, 1015671571, 731183368, 648017665, - -1119466010, -1337113617, -1487908364, -1436852227, - -1989511742, -2073986101, -1820562992, -1636341799, - -719438418, -669699161, -821550660, -1039978571, - -516815478, -331805821, -81520232, -164685935, - -695372211, -611944380, -862229921, -1047501738, - -492745111, -274055072, -122203525, -172204942, - -1093335547, -1277294580, -1530717673, -1446505442, - -1963377119, -2014171096, -1863376333, -1645990854, - 104699613, 188127444, 472615631, 287343814, - 840019705, 1058709744, 671593195, 621591778, - 1852171925, 1668212892, 1953757831, 2037970062, - 1514790577, 1463996600, 1080017571, 1297403050, - -621329940, -671330331, -1058972162, -840281097, - -287606328, -472877119, -187865638, -104436781, - -1297141340, -1079754835, -1464259146, -1515052097, - -2038232704, -1954019447, -1667951214, -1851909221, - 172466556, 122466165, 273792366, 492483431, - 1047239000, 861968209, 612205898, 695634755, - 1646252340, 1863638845, 2013908262, 1963115311, - 1446242576, 1530455833, 1277555970, 1093597963, - 1636604631, 1820824798, 2073724613, 1989249228, - 1436590835, 1487645946, 1337376481, 1119727848, - 164948639, 81781910, 331544205, 516552836, - 1039717051, 821288114, 669961897, 719700128, - -1321436601, -1137216434, -1423284651, -1507760036, - -2062531997, -2011476886, -1626972559, -1844621192, - -647755249, -730921978, -1015933411, -830924780, - -314035669, -532464606, -144822727, -95084496, - -1224610662, -1173691757, -1390940024, -1608712575, - -2094148418, -1910056265, -1724135252, -1808742747, - -547775278, -766340389, -984645440, -935031095, - -344611594, -427906305, -245122844, -60246291, - 1739656202, 1790575107, 2108100632, 1890328081, - 1402811438, 1586903591, 1233856572, 1149249077, - 266959938, 48394827, 369057872, 418672217, - 1002783846, 919489135, 567498868, 752375421, - 209336225, 24197544, 376187827, 459744698, - 945164165, 895287692, 574624663, 793451934, - 1679968233, 1764313568, 2117360635, 1933530610, - 1343127501, 1560637892, 1243112415, 1192455638, - -590686415, -775825096, -958608605, -875051734, - -387518699, -437395172, -219090169, -262898, - -1265457287, -1181111952, -1367032981, -1550863006, - -2134991011, -1917480620, -1700232369, -1750889146 -}; - -const int CRijndael::sm_U4[256] = -{ - 0, 151849742, 303699484, 454499602, - 607398968, 758720310, 908999204, 1059270954, - 1214797936, 1097159550, 1517440620, 1400849762, - 1817998408, 1699839814, 2118541908, 2001430874, - -1865371424, -1713521682, -2100648196, -1949848078, - -1260086056, -1108764714, -1493267772, -1342996022, - -658970480, -776608866, -895287668, -1011878526, - -57883480, -176042074, -292105548, -409216582, - 1002142683, 850817237, 698445255, 548169417, - 529487843, 377642221, 227885567, 77089521, - 1943217067, 2061379749, 1640576439, 1757691577, - 1474760595, 1592394909, 1174215055, 1290801793, - -1418998981, -1570324427, -1183720153, -1333995991, - -1889540349, -2041385971, -1656360673, -1807156719, - -486304949, -368142267, -249985705, -132870567, - -952647821, -835013507, -718427793, -601841055, - 1986918061, 2137062819, 1685577905, 1836772287, - 1381620373, 1532285339, 1078185097, 1229899655, - 1040559837, 923313619, 740276417, 621982671, - 439452389, 322734571, 137073913, 19308535, - -423803315, -273658557, -190361519, -39167137, - -1031181707, -880516741, -795640727, -643926169, - -1361764803, -1479011021, -1127282655, -1245576401, - -1964953083, -2081670901, -1728371687, -1846137065, - 1305906550, 1155237496, 1607244650, 1455525988, - 1776460110, 1626319424, 2079897426, 1928707164, - 96392454, 213114376, 396673818, 514443284, - 562755902, 679998000, 865136418, 983426092, - -586793578, -737462632, -820237430, -971956092, - -114159186, -264299872, -349698126, -500888388, - -1787927066, -1671205144, -2022411270, -1904641804, - -1319482914, -1202240816, -1556062270, -1437772596, - -321194175, -438830001, -20913827, -137500077, - -923870343, -1042034569, -621490843, -738605461, - -1531793615, -1379949505, -1230456531, -1079659997, - -2138668279, -1987344377, -1835231979, -1684955621, - 2081048481, 1963412655, 1846563261, 1729977011, - 1480485785, 1362321559, 1243905413, 1126790795, - 878845905, 1030690015, 645401037, 796197571, - 274084841, 425408743, 38544885, 188821243, - -681472870, -563312748, -981755258, -864644728, - -212492126, -94852180, -514869570, -398279248, - -1626745622, -1778065436, -1928084746, -2078357000, - -1153566510, -1305414692, -1457000754, -1607801408, - 1202797690, 1320957812, 1437280870, 1554391400, - 1669664834, 1787304780, 1906247262, 2022837584, - 265905162, 114585348, 499347990, 349075736, - 736970802, 585122620, 972512814, 821712160, - -1699282452, -1816524062, -2001922064, -2120213250, - -1098699308, -1215420710, -1399243832, -1517014842, - -757114468, -606973294, -1060810880, -909622130, - -152341084, -1671510, -453942344, -302225226, - 174567692, 57326082, 410887952, 292596766, - 777231668, 660510266, 1011452712, 893681702, - 1108339068, 1258480242, 1343618912, 1494807662, - 1715193156, 1865862730, 1948373848, 2100090966, - -1593017801, -1476300487, -1290376149, -1172609243, - -2059905521, -1942659839, -1759363053, -1641067747, - -379313593, -529979063, -75615141, -227328171, - -850391425, -1000536719, -548792221, -699985043, - 836553431, 953270745, 600235211, 718002117, - 367585007, 484830689, 133361907, 251657213, - 2041877159, 1891211689, 1806599355, 1654886325, - 1568718495, 1418573201, 1335535747, 1184342925 -}; - -const char CRijndael::sm_rcon[30] = -{ - 1, 2, 4, 8, 16, 32, - 64, -128, 27, 54, 108, -40, - -85, 77, -102, 47, 94, -68, - 99, -58, -105, 53, 106, -44, - -77, 125, -6, -17, -59, -111 -}; - -const int CRijndael::sm_shifts[3][4][2] = -{ - { {0, 0}, {1, 3}, {2, 2}, {3, 1} }, - { {0, 0}, {1, 5}, {2, 4}, {3, 3} }, - { {0, 0}, {1, 7}, {3, 5}, {4, 4} } -}; - -//Error Messages -char const* CRijndael::sm_szErrorMsg1 = "Object not Initialized"; -char const* CRijndael::sm_szErrorMsg2 = "Data not multiple of Block Size"; - -//Null chain -char const* CRijndael::sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - -//CONSTRUCTOR -CRijndael::CRijndael() : m_bKeyInit(false) -{ -} - -//DESTRUCTOR -CRijndael::~CRijndael() -{ -} - -//Expand a user-supplied key material into a session key. -// key - The 128/192/256-bit user-key to use. -// chain - initial chain block for CBC and CFB modes. -// keylength - 16, 24 or 32 bytes -// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes). -void CRijndael::MakeKey(char const* key, char const* chain, int keylength, int blockSize) -{ - if(NULL == key) - throw std::string("Empty key"); - if(!(16==keylength || 24==keylength || 32==keylength)) - throw std::string("Incorrect key length"); - if(!(16==blockSize || 24==blockSize || 32==blockSize)) - throw std::string("Incorrect block length"); - m_keylength = keylength; - m_blockSize = blockSize; - //Initialize the chain - memcpy(m_chain0, chain, m_blockSize); - memcpy(m_chain, chain, m_blockSize); - //Calculate Number of Rounds - switch(m_keylength) - { - case 16: - m_iROUNDS = (m_blockSize == 16) ? 10 : (m_blockSize == 24 ? 12 : 14); - break; - - case 24: - m_iROUNDS = (m_blockSize != 32) ? 12 : 14; - break; - - default: // 32 bytes = 256 bits - m_iROUNDS = 14; - } - int BC = m_blockSize / 4; - int i, j; - for(i=0; i<=m_iROUNDS; i++) - { - for(j=0; j> 16) & 0xFF] & 0xFF) << 24 ^ - (sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ - (sm_S[ tt & 0xFF] & 0xFF) << 8 ^ - (sm_S[(tt >> 24) & 0xFF] & 0xFF) ^ - (sm_rcon[rconpointer++] & 0xFF) << 24; - if(KC != 8) - for(i=1, j=0; i> 8) & 0xFF] & 0xFF) << 8 ^ - (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ - (sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24; - for(j = KC/2, i=j+1; i> 24) & 0xFF] ^ - sm_U2[(tt >> 16) & 0xFF] ^ - sm_U3[(tt >> 8) & 0xFF] ^ - sm_U4[tt & 0xFF]; - } - m_bKeyInit = true; -} - -//Convenience method to encrypt exactly one block of plaintext, assuming -//Rijndael's default block size (128-bit). -// in - The plaintext -// result - The ciphertext generated from a plaintext using the key -void CRijndael::DefEncryptBlock(char const* in, char* result) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - int* Ker = m_Ke[0]; - int t0 = ((unsigned char)*(in++) << 24); - t0 |= ((unsigned char)*(in++) << 16); - t0 |= ((unsigned char)*(in++) << 8); - (t0 |= (unsigned char)*(in++)) ^= Ker[0]; - int t1 = ((unsigned char)*(in++) << 24); - t1 |= ((unsigned char)*(in++) << 16); - t1 |= ((unsigned char)*(in++) << 8); - (t1 |= (unsigned char)*(in++)) ^= Ker[1]; - int t2 = ((unsigned char)*(in++) << 24); - t2 |= ((unsigned char)*(in++) << 16); - t2 |= ((unsigned char)*(in++) << 8); - (t2 |= (unsigned char)*(in++)) ^= Ker[2]; - int t3 = ((unsigned char)*(in++) << 24); - t3 |= ((unsigned char)*(in++) << 16); - t3 |= ((unsigned char)*(in++) << 8); - (t3 |= (unsigned char)*(in++)) ^= Ker[3]; - int a0, a1, a2, a3; - //Apply Round Transforms - for (int r = 1; r < m_iROUNDS; r++) - { - Ker = m_Ke[r]; - a0 = (sm_T1[(t0 >> 24) & 0xFF] ^ - sm_T2[(t1 >> 16) & 0xFF] ^ - sm_T3[(t2 >> 8) & 0xFF] ^ - sm_T4[t3 & 0xFF]) ^ Ker[0]; - a1 = (sm_T1[(t1 >> 24) & 0xFF] ^ - sm_T2[(t2 >> 16) & 0xFF] ^ - sm_T3[(t3 >> 8) & 0xFF] ^ - sm_T4[t0 & 0xFF]) ^ Ker[1]; - a2 = (sm_T1[(t2 >> 24) & 0xFF] ^ - sm_T2[(t3 >> 16) & 0xFF] ^ - sm_T3[(t0 >> 8) & 0xFF] ^ - sm_T4[t1 & 0xFF]) ^ Ker[2]; - a3 = (sm_T1[(t3 >> 24) & 0xFF] ^ - sm_T2[(t0 >> 16) & 0xFF] ^ - sm_T3[(t1 >> 8) & 0xFF] ^ - sm_T4[t2 & 0xFF]) ^ Ker[3]; - t0 = a0; - t1 = a1; - t2 = a2; - t3 = a3; - } - //Last Round is special - Ker = m_Ke[m_iROUNDS]; - int tt = Ker[0]; - result[0] = sm_S[(t0 >> 24) & 0xFF] ^ (tt >> 24); - result[1] = sm_S[(t1 >> 16) & 0xFF] ^ (tt >> 16); - result[2] = sm_S[(t2 >> 8) & 0xFF] ^ (tt >> 8); - result[3] = sm_S[t3 & 0xFF] ^ tt; - tt = Ker[1]; - result[4] = sm_S[(t1 >> 24) & 0xFF] ^ (tt >> 24); - result[5] = sm_S[(t2 >> 16) & 0xFF] ^ (tt >> 16); - result[6] = sm_S[(t3 >> 8) & 0xFF] ^ (tt >> 8); - result[7] = sm_S[t0 & 0xFF] ^ tt; - tt = Ker[2]; - result[8] = sm_S[(t2 >> 24) & 0xFF] ^ (tt >> 24); - result[9] = sm_S[(t3 >> 16) & 0xFF] ^ (tt >> 16); - result[10] = sm_S[(t0 >> 8) & 0xFF] ^ (tt >> 8); - result[11] = sm_S[t1 & 0xFF] ^ tt; - tt = Ker[3]; - result[12] = sm_S[(t3 >> 24) & 0xFF] ^ (tt >> 24); - result[13] = sm_S[(t0 >> 16) & 0xFF] ^ (tt >> 16); - result[14] = sm_S[(t1 >> 8) & 0xFF] ^ (tt >> 8); - result[15] = sm_S[t2 & 0xFF] ^ tt; -} - -//Convenience method to decrypt exactly one block of plaintext, assuming -//Rijndael's default block size (128-bit). -// in - The ciphertext. -// result - The plaintext generated from a ciphertext using the session key. -void CRijndael::DefDecryptBlock(char const* in, char* result) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - int* Kdr = m_Kd[0]; - int t0 = ((unsigned char)*(in++) << 24); - t0 = t0 | ((unsigned char)*(in++) << 16); - t0 |= ((unsigned char)*(in++) << 8); - (t0 |= (unsigned char)*(in++)) ^= Kdr[0]; - int t1 = ((unsigned char)*(in++) << 24); - t1 |= ((unsigned char)*(in++) << 16); - t1 |= ((unsigned char)*(in++) << 8); - (t1 |= (unsigned char)*(in++)) ^= Kdr[1]; - int t2 = ((unsigned char)*(in++) << 24); - t2 |= ((unsigned char)*(in++) << 16); - t2 |= ((unsigned char)*(in++) << 8); - (t2 |= (unsigned char)*(in++)) ^= Kdr[2]; - int t3 = ((unsigned char)*(in++) << 24); - t3 |= ((unsigned char)*(in++) << 16); - t3 |= ((unsigned char)*(in++) << 8); - (t3 |= (unsigned char)*(in++)) ^= Kdr[3]; - int a0, a1, a2, a3; - for(int r = 1; r < m_iROUNDS; r++) // apply round transforms - { - Kdr = m_Kd[r]; - a0 = (sm_T5[(t0 >> 24) & 0xFF] ^ - sm_T6[(t3 >> 16) & 0xFF] ^ - sm_T7[(t2 >> 8) & 0xFF] ^ - sm_T8[ t1 & 0xFF] ) ^ Kdr[0]; - a1 = (sm_T5[(t1 >> 24) & 0xFF] ^ - sm_T6[(t0 >> 16) & 0xFF] ^ - sm_T7[(t3 >> 8) & 0xFF] ^ - sm_T8[ t2 & 0xFF] ) ^ Kdr[1]; - a2 = (sm_T5[(t2 >> 24) & 0xFF] ^ - sm_T6[(t1 >> 16) & 0xFF] ^ - sm_T7[(t0 >> 8) & 0xFF] ^ - sm_T8[ t3 & 0xFF] ) ^ Kdr[2]; - a3 = (sm_T5[(t3 >> 24) & 0xFF] ^ - sm_T6[(t2 >> 16) & 0xFF] ^ - sm_T7[(t1 >> 8) & 0xFF] ^ - sm_T8[ t0 & 0xFF] ) ^ Kdr[3]; - t0 = a0; - t1 = a1; - t2 = a2; - t3 = a3; - } - //Last Round is special - Kdr = m_Kd[m_iROUNDS]; - int tt = Kdr[0]; - result[ 0] = sm_Si[(t0 >> 24) & 0xFF] ^ (tt >> 24); - result[ 1] = sm_Si[(t3 >> 16) & 0xFF] ^ (tt >> 16); - result[ 2] = sm_Si[(t2 >> 8) & 0xFF] ^ (tt >> 8); - result[ 3] = sm_Si[ t1 & 0xFF] ^ tt; - tt = Kdr[1]; - result[ 4] = sm_Si[(t1 >> 24) & 0xFF] ^ (tt >> 24); - result[ 5] = sm_Si[(t0 >> 16) & 0xFF] ^ (tt >> 16); - result[ 6] = sm_Si[(t3 >> 8) & 0xFF] ^ (tt >> 8); - result[ 7] = sm_Si[ t2 & 0xFF] ^ tt; - tt = Kdr[2]; - result[ 8] = sm_Si[(t2 >> 24) & 0xFF] ^ (tt >> 24); - result[ 9] = sm_Si[(t1 >> 16) & 0xFF] ^ (tt >> 16); - result[10] = sm_Si[(t0 >> 8) & 0xFF] ^ (tt >> 8); - result[11] = sm_Si[ t3 & 0xFF] ^ tt; - tt = Kdr[3]; - result[12] = sm_Si[(t3 >> 24) & 0xFF] ^ (tt >> 24); - result[13] = sm_Si[(t2 >> 16) & 0xFF] ^ (tt >> 16); - result[14] = sm_Si[(t1 >> 8) & 0xFF] ^ (tt >> 8); - result[15] = sm_Si[ t0 & 0xFF] ^ tt; -} - -//Encrypt exactly one block of plaintext. -// in - The plaintext. -// result - The ciphertext generated from a plaintext using the key. -void CRijndael::EncryptBlock(char const* in, char* result) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - if(DEFAULT_BLOCK_SIZE == m_blockSize) - { - DefEncryptBlock(in, result); - return; - } - int BC = m_blockSize / 4; - int SC = (BC == 4) ? 0 : (BC == 6 ? 1 : 2); - int s1 = sm_shifts[SC][1][0]; - int s2 = sm_shifts[SC][2][0]; - int s3 = sm_shifts[SC][3][0]; - //Temporary Work Arrays - int i; - int tt; - int* pi = t; - for(i=0; i> 24) & 0xFF] ^ - sm_T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^ - sm_T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^ - sm_T4[ t[(i + s3) % BC] & 0xFF] ) ^ m_Ke[r][i]; - memcpy(t, a, 4*BC); - } - int j; - //Last Round is Special - for(i=0,j=0; i> 24) & 0xFF] ^ (tt >> 24); - result[j++] = sm_S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16); - result[j++] = sm_S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8); - result[j++] = sm_S[ t[(i + s3) % BC] & 0xFF] ^ tt; - } -} - -//Decrypt exactly one block of ciphertext. -// in - The ciphertext. -// result - The plaintext generated from a ciphertext using the session key. -void CRijndael::DecryptBlock(char const* in, char* result) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - if(DEFAULT_BLOCK_SIZE == m_blockSize) - { - DefDecryptBlock(in, result); - return; - } - int BC = m_blockSize / 4; - int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); - int s1 = sm_shifts[SC][1][1]; - int s2 = sm_shifts[SC][2][1]; - int s3 = sm_shifts[SC][3][1]; - //Temporary Work Arrays - int i; - int tt; - int* pi = t; - for(i=0; i> 24) & 0xFF] ^ - sm_T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^ - sm_T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^ - sm_T8[ t[(i + s3) % BC] & 0xFF]) ^ m_Kd[r][i]; - memcpy(t, a, 4*BC); - } - int j; - //Last Round is Special - for(i=0,j=0; i> 24) & 0xFF] ^ (tt >> 24); - result[j++] = sm_Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16); - result[j++] = sm_Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8); - result[j++] = sm_Si[ t[(i + s3) % BC] & 0xFF] ^ tt; - } -} - -void CRijndael::Encrypt(char const* in, char* result, size_t n, int iMode) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - //n should be > 0 and multiple of m_blockSize - if(0==n || n%m_blockSize!=0) - throw std::string(sm_szErrorMsg2); - int i; - char const* pin; - char* presult; - if(CBC == iMode) //CBC mode, using the Chain - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - Xor(m_chain, pin); - EncryptBlock(m_chain, presult); - memcpy(m_chain, presult, m_blockSize); - pin += m_blockSize; - presult += m_blockSize; - } - } - else if(CFB == iMode) //CFB mode, using the Chain - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - EncryptBlock(m_chain, presult); - Xor(presult, pin); - memcpy(m_chain, presult, m_blockSize); - pin += m_blockSize; - presult += m_blockSize; - } - } - else //ECB mode, not using the Chain - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - EncryptBlock(pin, presult); - pin += m_blockSize; - presult += m_blockSize; - } - } -} - -void CRijndael::Decrypt(char const* in, char* result, size_t n, int iMode) -{ - if(false==m_bKeyInit) - throw std::string(sm_szErrorMsg1); - //n should be > 0 and multiple of m_blockSize - if(0==n || n%m_blockSize!=0) - throw std::string(sm_szErrorMsg2); - int i; - char const* pin; - char* presult; - if(CBC == iMode) //CBC mode, using the Chain - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - DecryptBlock(pin, presult); - Xor(presult, m_chain); - memcpy(m_chain, pin, m_blockSize); - pin += m_blockSize; - presult += m_blockSize; - } - } - else if(CFB == iMode) //CFB mode, using the Chain, not using Decrypt() - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - EncryptBlock(m_chain, presult); - //memcpy(presult, pin, m_blockSize); - Xor(presult, pin); - memcpy(m_chain, pin, m_blockSize); - pin += m_blockSize; - presult += m_blockSize; - } - } - else //ECB mode, not using the Chain - { - for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) - { - DecryptBlock(pin, presult); - pin += m_blockSize; - presult += m_blockSize; - } - } -} - + +//Rijndael.cpp + +#include +#include +#include +#include "aes.h" + +const int CRijndael::sm_alog[256] = +{ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, + 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, + 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, + 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, + 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, + 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, + 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, + 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, + 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, + 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1 +}; + +const int CRijndael::sm_log[256] = +{ + 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, + 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, + 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, + 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, + 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, + 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, + 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, + 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, + 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, + 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, + 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, + 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, + 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, + 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7 +}; + +const char CRijndael::sm_S[256] = +{ + 99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, + -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64, + -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, + 4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, + 9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124, + 83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, + -48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88, + 81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, + -51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, + 96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37, + -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, + -25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, + -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, + 112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, + -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33, + -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22 +}; + +const char CRijndael::sm_Si[256] = +{ + 82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, + 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, + 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, + 8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, + 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, + 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, + -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, + -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, + 58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, + -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, + 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, + -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, + 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, + 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, + -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, + 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125 +}; + +const int CRijndael::sm_T1[256] = +{ + -966564955, -126059388, -294160487, -159679603, + -855539, -697603139, -563122255, -1849309868, + 1613770832, 33620227, -832084055, 1445669757, + -402719207, -1244145822, 1303096294, -327780710, + -1882535355, 528646813, -1983264448, -92439161, + -268764651, -1302767125, -1907931191, -68095989, + 1101901292, -1277897625, 1604494077, 1169141738, + 597466303, 1403299063, -462261610, -1681866661, + 1974974402, -503448292, 1033081774, 1277568618, + 1815492186, 2118074177, -168298750, -2083730353, + 1748251740, 1369810420, -773462732, -101584632, + -495881837, -1411852173, 1647391059, 706024767, + 134480908, -1782069422, 1176707941, -1648114850, + 806885416, 932615841, 168101135, 798661301, + 235341577, 605164086, 461406363, -538779075, + -840176858, 1311188841, 2142417613, -361400929, + 302582043, 495158174, 1479289972, 874125870, + 907746093, -596742478, -1269146898, 1537253627, + -1538108682, 1983593293, -1210657183, 2108928974, + 1378429307, -572267714, 1580150641, 327451799, + -1504488459, -1177431704, 0, -1041371860, + 1075847264, -469959649, 2041688520, -1235526675, + -731223362, -1916023994, 1740553945, 1916352843, + -1807070498, -1739830060, -1336387352, -2049978550, + -1143943061, -974131414, 1336584933, -302253290, + -2042412091, -1706209833, 1714631509, 293963156, + -1975171633, -369493744, 67240454, -25198719, + -1605349136, 2017213508, 631218106, 1269344483, + -1571728909, 1571005438, -2143272768, 93294474, + 1066570413, 563977660, 1882732616, -235539196, + 1673313503, 2008463041, -1344611723, 1109467491, + 537923632, -436207846, -34344178, -1076702611, + -2117218996, 403442708, 638784309, -1007883217, + -1101045791, 899127202, -2008791860, 773265209, + -1815821225, 1437050866, -58818942, 2050833735, + -932944724, -1168286233, 840505643, -428641387, + -1067425632, 427917720, -1638969391, -1545806721, + 1143087718, 1412049534, 999329963, 193497219, + -1941551414, -940642775, 1807268051, 672404540, + -1478566279, -1134666014, 369822493, -1378100362, + -606019525, 1681011286, 1949973070, 336202270, + -1840690725, 201721354, 1210328172, -1201906460, + -1614626211, -1110191250, 1135389935, -1000185178, + 965841320, 831886756, -739974089, -226920053, + -706222286, -1949775805, 1849112409, -630362697, + 26054028, -1311386268, -1672589614, 1235855840, + -663982924, -1403627782, -202050553, -806688219, + -899324497, -193299826, 1202630377, 268961816, + 1874508501, -260540280, 1243948399, 1546530418, + 941366308, 1470539505, 1941222599, -1748580783, + -873928669, -1579295364, -395021156, 1042226977, + -1773450275, 1639824860, 227249030, 260737669, + -529502064, 2084453954, 1907733956, -865704278, + -1874310952, 100860677, -134810111, 470683154, + -1033805405, 1781871967, -1370007559, 1773779408, + 394692241, -1715355304, 974986535, 664706745, + -639508168, -336005101, 731420851, 571543859, + -764843589, -1445340816, 126783113, 865375399, + 765172662, 1008606754, 361203602, -907417312, + -2016489911, -1437248001, 1344809080, -1512054918, + 59542671, 1503764984, 160008576, 437062935, + 1707065306, -672733647, -2076032314, -798463816, + -2109652541, 697932208, 1512910199, 504303377, + 2075177163, -1470868228, 1841019862, 739644986 +}; + +const int CRijndael::sm_T2[256] = +{ + -1513725085, -2064089988, -1712425097, -1913226373, + 234877682, -1110021269, -1310822545, 1418839493, + 1348481072, 50462977, -1446090905, 2102799147, + 434634494, 1656084439, -431117397, -1695779210, + 1167051466, -1658879358, 1082771913, -2013627011, + 368048890, -340633255, -913422521, 201060592, + -331240019, 1739838676, -44064094, -364531793, + -1088185188, -145513308, -1763413390, 1536934080, + -1032472649, 484572669, -1371696237, 1783375398, + 1517041206, 1098792767, 49674231, 1334037708, + 1550332980, -195975771, 886171109, 150598129, + -1813876367, 1940642008, 1398944049, 1059722517, + 201851908, 1385547719, 1699095331, 1587397571, + 674240536, -1590192490, 252314885, -1255171430, + 151914247, 908333586, -1692696448, 1038082786, + 651029483, 1766729511, -847269198, -1612024459, + 454166793, -1642232957, 1951935532, 775166490, + 758520603, -1294176658, -290170278, -77881184, + -157003182, 1299594043, 1639438038, -830622797, + 2068982057, 1054729187, 1901997871, -1760328572, + -173649069, 1757008337, 0, 750906861, + 1614815264, 535035132, -931548751, -306816165, + -1093375382, 1183697867, -647512386, 1265776953, + -560706998, -728216500, -391096232, 1250283471, + 1807470800, 717615087, -447763798, 384695291, + -981056701, -677753523, 1432761139, -1810791035, + -813021883, 283769337, 100925954, -2114027649, + -257929136, 1148730428, -1171939425, -481580888, + -207466159, -27417693, -1065336768, -1979347057, + -1388342638, -1138647651, 1215313976, 82966005, + -547111748, -1049119050, 1974459098, 1665278241, + 807407632, 451280895, 251524083, 1841287890, + 1283575245, 337120268, 891687699, 801369324, + -507617441, -1573546089, -863484860, 959321879, + 1469301956, -229267545, -2097381762, 1199193405, + -1396153244, -407216803, 724703513, -1780059277, + -1598005152, -1743158911, -778154161, 2141445340, + 1715741218, 2119445034, -1422159728, -2096396152, + -896776634, 700968686, -747915080, 1009259540, + 2041044702, -490971554, 487983883, 1991105499, + 1004265696, 1449407026, 1316239930, 504629770, + -611169975, 168560134, 1816667172, -457679780, + 1570751170, 1857934291, -280777556, -1497079198, + -1472622191, -1540254315, 936633572, -1947043463, + 852879335, 1133234376, 1500395319, -1210421907, + -1946055283, 1689376213, -761508274, -532043351, + -1260884884, -89369002, 133428468, 634383082, + -1345690267, -1896580486, -381178194, 403703816, + -714097990, -1997506440, 1867130149, 1918643758, + 607656988, -245913946, -948718412, 1368901318, + 600565992, 2090982877, -1662487436, 557719327, + -577352885, -597574211, -2045932661, -2062579062, + -1864339344, 1115438654, -999180875, -1429445018, + -661632952, 84280067, 33027830, 303828494, + -1547542175, 1600795957, -106014889, -798377543, + -1860729210, 1486471617, 658119965, -1188585826, + 953803233, 334231800, -1288988520, 857870609, + -1143838359, 1890179545, -1995993458, -1489791852, + -1238525029, 574365214, -1844082809, 550103529, + 1233637070, -5614251, 2018519080, 2057691103, + -1895592820, -128343647, -2146858615, 387583245, + -630865985, 836232934, -964410814, -1194301336, + -1014873791, -1339450983, 2002398509, 287182607, + -881086288, -56077228, -697451589, 975967766 +}; + +const int CRijndael::sm_T3[256] = +{ + 1671808611, 2089089148, 2006576759, 2072901243, + -233963534, 1807603307, 1873927791, -984313403, + 810573872, 16974337, 1739181671, 729634347, + -31856642, -681396777, -1410970197, 1989864566, + -901410870, -2103631998, -918517303, 2106063485, + -99225606, 1508618841, 1204391495, -267650064, + -1377025619, -731401260, -1560453214, -1343601233, + -1665195108, -1527295068, 1922491506, -1067738176, + -1211992649, -48438787, -1817297517, 644500518, + 911895606, 1061256767, -150800905, -867204148, + 878471220, -1510714971, -449523227, -251069967, + 1905517169, -663508008, 827548209, 356461077, + 67897348, -950889017, 593839651, -1017209405, + 405286936, -1767819370, 84871685, -1699401830, + 118033927, 305538066, -2137318528, -499261470, + -349778453, 661212711, -1295155278, 1973414517, + 152769033, -2086789757, 745822252, 439235610, + 455947803, 1857215598, 1525593178, -1594139744, + 1391895634, 994932283, -698239018, -1278313037, + 695947817, -482419229, 795958831, -2070473852, + 1408607827, -781665839, 0, -315833875, + 543178784, -65018884, -1312261711, 1542305371, + 1790891114, -884568629, -1093048386, 961245753, + 1256100938, 1289001036, 1491644504, -817199665, + -798245936, -282409489, -1427812438, -82383365, + 1137018435, 1305975373, 861234739, -2053893755, + 1171229253, -116332039, 33948674, 2139225727, + 1357946960, 1011120188, -1615190625, -1461498968, + 1374921297, -1543610973, 1086357568, -1886780017, + -1834139758, -1648615011, 944271416, -184225291, + -1126210628, -1228834890, -629821478, 560153121, + 271589392, -15014401, -217121293, -764559406, + -850624051, 202643468, 322250259, -332413972, + 1608629855, -1750977129, 1154254916, 389623319, + -1000893500, -1477290585, 2122513534, 1028094525, + 1689045092, 1575467613, 422261273, 1939203699, + 1621147744, -2120738431, 1339137615, -595614756, + 577127458, 712922154, -1867826288, -2004677752, + 1187679302, -299251730, -1194103880, 339486740, + -562452514, 1591917662, 186455563, -612979237, + -532948000, 844522546, 978220090, 169743370, + 1239126601, 101321734, 611076132, 1558493276, + -1034051646, -747717165, -1393605716, 1655096418, + -1851246191, -1784401515, -466103324, 2039214713, + -416098841, -935097400, 928607799, 1840765549, + -1920204403, -714821163, 1322425422, -1444918871, + 1823791212, 1459268694, -200805388, -366620694, + 1706019429, 2056189050, -1360443474, 135794696, + -1160417350, 2022240376, 628050469, 779246638, + 472135708, -1494132826, -1261997132, -967731258, + -400307224, -579034659, 1956440180, 522272287, + 1272813131, -1109630531, -1954148981, -1970991222, + 1888542832, 1044544574, -1245417035, 1722469478, + 1222152264, 50660867, -167643146, 236067854, + 1638122081, 895445557, 1475980887, -1177523783, + -2037311610, -1051158079, 489110045, -1632032866, + -516367903, -132912136, -1733088360, 288563729, + 1773916777, -646927911, -1903622258, -1800981612, + -1682559589, 505560094, -2020469369, -383727127, + -834041906, 1442818645, 678973480, -545610273, + -1936784500, -1577559647, -1988097655, 219617805, + -1076206145, -432941082, 1120306242, 1756942440, + 1103331905, -1716508263, 762796589, 252780047, + -1328841808, 1425844308, -1143575109, 372911126 +}; + +const int CRijndael::sm_T4[256] = +{ + 1667474886, 2088535288, 2004326894, 2071694838, + -219017729, 1802223062, 1869591006, -976923503, + 808472672, 16843522, 1734846926, 724270422, + -16901657, -673750347, -1414797747, 1987484396, + -892713585, -2105369313, -909557623, 2105378810, + -84273681, 1499065266, 1195886990, -252703749, + -1381110719, -724277325, -1566376609, -1347425723, + -1667449053, -1532692653, 1920112356, -1061135461, + -1212693899, -33743647, -1819038147, 640051788, + 909531756, 1061110142, -134806795, -859025533, + 875846760, -1515850671, -437963567, -235861767, + 1903268834, -656903253, 825316194, 353713962, + 67374088, -943238507, 589522246, -1010606435, + 404236336, -1768513225, 84217610, -1701137105, + 117901582, 303183396, -2139055333, -488489505, + -336910643, 656894286, -1296904833, 1970642922, + 151591698, -2088526307, 741110872, 437923380, + 454765878, 1852748508, 1515908788, -1600062629, + 1381168804, 993742198, -690593353, -1280061827, + 690584402, -471646499, 791638366, -2071685357, + 1398011302, -774805319, 0, -303223615, + 538992704, -50585629, -1313748871, 1532751286, + 1785380564, -875870579, -1094788761, 960056178, + 1246420628, 1280103576, 1482221744, -808498555, + -791647301, -269538619, -1431640753, -67430675, + 1128514950, 1296947098, 859002214, -2054843375, + 1162203018, -101117719, 33687044, 2139062782, + 1347481760, 1010582648, -1616922075, -1465326773, + 1364325282, -1549533603, 1077985408, -1886418427, + -1835881153, -1650607071, 943212656, -168491791, + -1128472733, -1229536905, -623217233, 555836226, + 269496352, -58651, -202174723, -757961281, + -842183551, 202118168, 320025894, -320065597, + 1600119230, -1751670219, 1145359496, 387397934, + -993765485, -1482165675, 2122220284, 1027426170, + 1684319432, 1566435258, 421079858, 1936954854, + 1616945344, -2122213351, 1330631070, -589529181, + 572679748, 707427924, -1869567173, -2004319477, + 1179044492, -286381625, -1195846805, 336870440, + -555845209, 1583276732, 185277718, -606374227, + -522175525, 842159716, 976899700, 168435220, + 1229577106, 101059084, 606366792, 1549591736, + -1027449441, -741118275, -1397952701, 1650632388, + -1852725191, -1785355215, -454805549, 2038008818, + -404278571, -926399605, 926374254, 1835907034, + -1920103423, -707435343, 1313788572, -1448484791, + 1819063512, 1448540844, -185333773, -353753649, + 1701162954, 2054852340, -1364268729, 134748176, + -1162160785, 2021165296, 623210314, 774795868, + 471606328, -1499008681, -1263220877, -960081513, + -387439669, -572687199, 1953799400, 522133822, + 1263263126, -1111630751, -1953790451, -1970633457, + 1886425312, 1044267644, -1246378895, 1718004428, + 1212733584, 50529542, -151649801, 235803164, + 1633788866, 892690282, 1465383342, -1179004823, + -2038001385, -1044293479, 488449850, -1633765081, + -505333543, -117959701, -1734823125, 286339874, + 1768537042, -640061271, -1903261433, -1802197197, + -1684294099, 505291324, -2021158379, -370597687, + -825341561, 1431699370, 673740880, -539002203, + -1936945405, -1583220647, -1987477495, 218961690, + -1077945755, -421121577, 1111672452, 1751693520, + 1094828930, -1717981143, 757954394, 252645662, + -1330590853, 1414855848, -1145317779, 370555436 +}; + +const int CRijndael::sm_T5[256] = +{ + 1374988112, 2118214995, 437757123, 975658646, + 1001089995, 530400753, -1392879445, 1273168787, + 540080725, -1384747530, -1999866223, -184398811, + 1340463100, -987051049, 641025152, -1251826801, + -558802359, 632953703, 1172967064, 1576976609, + -1020300030, -2125664238, -1924753501, 1809054150, + 59727847, 361929877, -1083344149, -1789765158, + -725712083, 1484005843, 1239443753, -1899378620, + 1975683434, -191989384, -1722270101, 666464733, + -1092530250, -259478249, -920605594, 2110667444, + 1675577880, -451268222, -1756286112, 1649639237, + -1318815776, -1150570876, -25059300, -116905068, + 1883793496, -1891238631, -1797362553, 1383856311, + -1418472669, 1917518562, -484470953, 1716890410, + -1293211641, 800440835, -2033878118, -751368027, + 807962610, 599762354, 33778362, -317291940, + -1966138325, -1485196142, -217582864, 1315562145, + 1708848333, 101039829, -785096161, -995688822, + 875451293, -1561111136, 92987698, -1527321739, + 193195065, 1080094634, 1584504582, -1116860335, + 1042385657, -1763899843, -583137874, 1306967366, + -1856729675, 1908694277, 67556463, 1615861247, + 429456164, -692196969, -1992277044, 1742315127, + -1326955843, 126454664, -417768648, 2043211483, + -1585706425, 2084704233, -125559095, 0, + 159417987, 841739592, 504459436, 1817866830, + -49348613, 260388950, 1034867998, 908933415, + 168810852, 1750902305, -1688513327, 607530554, + 202008497, -1822955761, -1259432238, 463180190, + -2134850225, 1641816226, 1517767529, 470948374, + -493635062, -1063245083, 1008918595, 303765277, + 235474187, -225720403, 766945465, 337553864, + 1475418501, -1351284916, -291906117, -1551933187, + -150919521, 1551037884, 1147550661, 1543208500, + -1958532746, -886847780, -1225917336, -1192955549, + -684598070, 1113818384, 328671808, -2067394272, + -2058738563, -759480840, -1359400431, -953573011, + 496906059, -592301837, 226906860, 2009195472, + 733156972, -1452230247, 294930682, 1206477858, + -1459843900, -1594867942, 1451044056, 573804783, + -2025238841, -650587711, -1932877058, -1730933962, + -1493859889, -1518674392, -625504730, 1068351396, + 742039012, 1350078989, 1784663195, 1417561698, + -158526526, -1864845080, 775550814, -2101104651, + -1621262146, 1775276924, 1876241833, -819653965, + -928212677, 270040487, -392404114, -616842373, + -853116919, 1851332852, -325404927, -2091935064, + -426414491, -1426069890, 566021896, -283776794, + -1159226407, 1248802510, -358676012, 699432150, + 832877231, 708780849, -962227152, 899835584, + 1951317047, -58537306, -527380304, 866637845, + -251357110, 1106041591, 2144161806, 395441711, + 1984812685, 1139781709, -861254316, -459930401, + -1630423581, 1282050075, -1054072904, 1181045119, + -1654724092, 25965917, -91786125, -83148498, + -1285087910, -1831087534, -384805325, 1842759443, + -1697160820, 933301370, 1509430414, -351060855, + -827774994, -1218328267, -518199827, 2051518780, + -1663901863, 1441952575, 404016761, 1942435775, + 1408749034, 1610459739, -549621996, 2017778566, + -894438527, -1184316354, 941896748, -1029488545, + 371049330, -1126030068, 675039627, -15887039, + 967311729, 135050206, -659233636, 1683407248, + 2076935265, -718096784, 1215061108, -793225406 +}; + +const int CRijndael::sm_T6[256] = +{ + 1347548327, 1400783205, -1021700188, -1774573730, + -885281941, -249586363, -1414727080, -1823743229, + 1428173050, -156404115, -1853305738, 636813900, + -61872681, -674944309, -2144979644, -1883938141, + 1239331162, 1730525723, -1740248562, -513933632, + 46346101, 310463728, -1551022441, -966011911, + -419197089, -1793748324, -339776134, -627748263, + 768917123, -749177823, 692707433, 1150208456, + 1786102409, 2029293177, 1805211710, -584599183, + -1229004465, 401639597, 1724457132, -1266823622, + 409198410, -2098914767, 1620529459, 1164071807, + -525245321, -2068091986, 486441376, -1795618773, + 1483753576, 428819965, -2020286868, -1219331080, + 598438867, -495826174, 1474502543, 711349675, + 129166120, 53458370, -1702443653, -1512884472, + -231724921, -1306280027, -1174273174, 1559041666, + 730517276, -1834518092, -252508174, -1588696606, + -848962828, -721025602, 533804130, -1966823682, + -1657524653, -1599933611, 839224033, 1973745387, + 957055980, -1438621457, 106852767, 1371368976, + -113368694, 1033297158, -1361232379, 1179510461, + -1248766835, 91341917, 1862534868, -10465259, + 605657339, -1747534359, -863420349, 2003294622, + -1112479678, -2012771957, 954669403, -612775698, + 1201765386, -377732593, -906460130, 0, + -2096529274, 1211247597, -1407315600, 1315723890, + -67301633, 1443857720, 507358933, 657861945, + 1678381017, 560487590, -778347692, 975451694, + -1324610969, 261314535, -759894378, -1642357871, + 1333838021, -1570644960, 1767536459, 370938394, + 182621114, -440360918, 1128014560, 487725847, + 185469197, -1376613433, -1188186456, -938205527, + -2057834215, 1286567175, -1141990947, -39616672, + -1611202266, -1134791947, -985373125, 878443390, + 1988838185, -590666810, 1756818940, 1673061617, + -891866660, 272786309, 1075025698, 545572369, + 2105887268, -120407235, 296679730, 1841768865, + 1260232239, -203640272, -334657966, -797457949, + 1814803222, -1716948807, -99511224, 575138148, + -995558260, 446754879, -665420500, -282971248, + -947435186, -1042728751, -24327518, 915985419, + -811141759, 681933534, 651868046, -1539330625, + -466863459, 223377554, -1687527476, 1649704518, + -1024029421, -393160520, 1580087799, -175979601, + -1096852096, 2087309459, -1452288723, -1278270190, + 1003007129, -1492117379, 1860738147, 2077965243, + 164439672, -194094824, 32283319, -1467789414, + 1709610350, 2125135846, 136428751, -420538904, + -642062437, -833982666, -722821367, -701910916, + -1355701070, 824852259, 818324884, -1070226842, + 930369212, -1493400886, -1327460144, 355706840, + 1257309336, -146674470, 243256656, 790073846, + -1921626666, 1296297904, 1422699085, -538667516, + -476130891, 457992840, -1195299809, 2135319889, + 77422314, 1560382517, 1945798516, 788204353, + 1521706781, 1385356242, 870912086, 325965383, + -1936009375, 2050466060, -1906706412, -1981082820, + -288446169, 901210569, -304014107, 1014646705, + 1503449823, 1062597235, 2031621326, -1082931401, + -363595827, 1533017514, 350174575, -2038938405, + -2117423117, 1052338372, 741876788, 1606591296, + 1914052035, 213705253, -1960297399, 1107234197, + 1899603969, -569897805, -1663519516, -1872472383, + 1635502980, 1893020342, 1950903388, 1120974935 +}; + +const int CRijndael::sm_T7[256] = +{ + -1487908364, 1699970625, -1530717673, 1586903591, + 1808481195, 1173430173, 1487645946, 59984867, + -95084496, 1844882806, 1989249228, 1277555970, + -671330331, -875051734, 1149249077, -1550863006, + 1514790577, 459744698, 244860394, -1058972162, + 1963115311, -267222708, -1750889146, -104436781, + 1608975247, -1667951214, 2062270317, 1507497298, + -2094148418, 567498868, 1764313568, -935031095, + -1989511742, 2037970062, 1047239000, 1910319033, + 1337376481, -1390940024, -1402549984, 984907214, + 1243112415, 830661914, 861968209, 2135253587, + 2011214180, -1367032981, -1608712575, 731183368, + 1750626376, -48656571, 1820824798, -122203525, + -752637069, 48394827, -1890065633, -1423284651, + 671593195, -1039978571, 2073724613, 145085239, + -2014171096, -1515052097, 1790575107, -2107839210, + 472615631, -1265457287, -219090169, -492745111, + -187865638, -1093335547, 1646252340, -24460122, + 1402811438, 1436590835, -516815478, -344611594, + -331805821, -274055072, -1626972559, 273792366, + -1963377119, 104699613, 95345982, -1119466010, + -1917480620, 1560637892, -730921978, 369057872, + -81520232, -375925059, 1137477952, -1636341799, + 1119727848, -1954019447, 1530455833, -287606328, + 172466556, 266959938, 516552836, 0, + -2038232704, -314035669, 1890328081, 1917742170, + -262898, 945164165, -719438418, 958871085, + -647755249, -1507760036, 1423022939, 775562294, + 1739656202, -418409641, -1764576018, -1851909221, + -984645440, 547512796, 1265195639, 437656594, + -1173691757, 719700128, -532464606, 387781147, + 218828297, -944901493, -1464259146, -1446505442, + 428169201, 122466165, -574886247, 1627235199, + 648017665, -172204942, 1002783846, 2117360635, + 695634755, -958608605, -60246291, -245122844, + -590686415, -2062531997, 574624663, 287343814, + 612205898, 1039717051, 840019705, -1586641111, + 793451934, 821288114, 1391201670, -472877119, + 376187827, -1181111952, 1224348052, 1679968233, + -1933268740, 1058709744, 752375421, -1863376333, + 1321699145, -775825096, -1560376118, 188127444, + -2117097739, -567761542, -1910056265, -1079754835, + -1645990854, -1844621192, -862229921, 1180849278, + 331544205, -1192718120, -144822727, -1342864701, + -2134991011, -1820562992, 766078933, 313773861, + -1724135252, 2108100632, 1668212892, -1149510853, + 2013908262, 418672217, -1224610662, -1700232369, + 1852171925, -427906305, -821550660, -387518699, + -1680229657, 919489135, 164948639, 2094410160, + -1297141340, 590424639, -1808742747, 1723872674, + -1137216434, -895026046, -793714544, -669699161, + -1739919100, -621329940, 1343127501, -164685935, + -695372211, -1337113617, 1297403050, 81781910, + -1243373871, -2011476886, 532201772, 1367295589, + -368796322, 895287692, 1953757831, 1093597963, + 492483431, -766340389, 1446242576, 1192455638, + 1636604631, 209336225, 344873464, 1015671571, + 669961897, -919226527, -437395172, -1321436601, + -547775278, 1933530610, -830924780, 935293895, + -840281097, -1436852227, 1863638845, -611944380, + -209597777, -1002522264, 875313188, 1080017571, + -1015933411, 621591778, 1233856572, -1790836979, + 24197544, -1277294580, -459482956, -1047501738, + -2073986101, -1234119374, 1551124588, 1463996600 +}; + +const int CRijndael::sm_T8[256] = +{ + -190361519, 1097159550, 396673818, 660510266, + -1418998981, -1656360673, -94852180, -486304949, + 821712160, 1986918061, -864644728, 38544885, + -438830001, 718002117, 893681702, 1654886325, + -1319482914, -1172609243, -368142267, -20913827, + 796197571, 1290801793, 1184342925, -738605461, + -1889540349, -1835231979, 1836772287, 1381620373, + -1098699308, 1948373848, -529979063, -909622130, + -1031181707, -1904641804, 1480485785, -1183720153, + -514869570, -2001922064, 548169417, -835013507, + -548792221, 439452389, 1362321559, 1400849762, + 1685577905, 1806599355, -2120213250, 137073913, + 1214797936, 1174215055, -563312748, 2079897426, + 1943217067, 1258480242, 529487843, 1437280870, + -349698126, -1245576401, -981755258, 923313619, + 679998000, -1079659997, 57326082, 377642221, + -820237430, 2041877159, 133361907, 1776460110, + -621490843, 96392454, 878845905, -1493267772, + 777231668, -212492126, -1964953083, -152341084, + -2081670901, 1626319424, 1906247262, 1846563261, + 562755902, -586793578, 1040559837, -423803315, + 1418573201, -1000536719, 114585348, 1343618912, + -1728371687, -1108764714, 1078185097, -643926169, + -398279248, -1987344377, 425408743, -923870343, + 2081048481, 1108339068, -2078357000, 0, + -2138668279, 736970802, 292596766, 1517440620, + 251657213, -2059905521, -1361764803, 758720310, + 265905162, 1554391400, 1532285339, 908999204, + 174567692, 1474760595, -292105548, -1684955621, + -1060810880, -601841055, 2001430874, 303699484, + -1816524062, -1607801408, 585122620, 454499602, + 151849742, -1949848078, -1230456531, 514443284, + -249985705, 1963412655, -1713521682, 2137062819, + 19308535, 1928707164, 1715193156, -75615141, + 1126790795, 600235211, -302225226, -453942344, + 836553431, 1669664834, -1759363053, -971956092, + 1243905413, -1153566510, -114159186, 698445255, + -1641067747, -1305414692, -2041385971, -1042034569, + -1290376149, 1891211689, -1807156719, -379313593, + -57883480, -264299872, 2100090966, 865136418, + 1229899655, 953270745, -895287668, -737462632, + -176042074, 2061379749, -1215420710, -1379949505, + 983426092, 2022837584, 1607244650, 2118541908, + -1928084746, -658970480, 972512814, -1011878526, + 1568718495, -795640727, -718427793, 621982671, + -1399243832, 410887952, -1671205144, 1002142683, + 645401037, 1494807662, -1699282452, 1335535747, + -1787927066, -1671510, -1127282655, 367585007, + -409216582, 1865862730, -1626745622, -1333995991, + -1531793615, 1059270954, -1517014842, -1570324427, + 1320957812, -2100648196, -1865371424, -1479011021, + 77089521, -321194175, -850391425, -1846137065, + 1305906550, -273658557, -1437772596, -1778065436, + -776608866, 1787304780, 740276417, 1699839814, + 1592394909, -1942659839, -2022411270, 188821243, + 1729977011, -606973294, 274084841, -699985043, + -681472870, -1593017801, -132870567, 322734571, + -1457000754, 1640576439, 484830689, 1202797690, + -757114468, -227328171, 349075736, -952647821, + -137500077, -39167137, 1030690015, 1155237496, + -1342996022, 1757691577, 607398968, -1556062270, + 499347990, -500888388, 1011452712, 227885567, + -1476300487, 213114376, -1260086056, 1455525988, + -880516741, 850817237, 1817998408, -1202240816 +}; + +const int CRijndael::sm_U1[256] = +{ + 0, 235474187, 470948374, 303765277, + 941896748, 908933415, 607530554, 708780849, + 1883793496, 2118214995, 1817866830, 1649639237, + 1215061108, 1181045119, 1417561698, 1517767529, + -527380304, -291906117, -58537306, -225720403, + -659233636, -692196969, -995688822, -894438527, + -1864845080, -1630423581, -1932877058, -2101104651, + -1459843900, -1493859889, -1259432238, -1159226407, + -616842373, -718096784, -953573011, -920605594, + -484470953, -317291940, -15887039, -251357110, + -1418472669, -1518674392, -1218328267, -1184316354, + -1822955761, -1654724092, -1891238631, -2125664238, + 1001089995, 899835584, 666464733, 699432150, + 59727847, 226906860, 530400753, 294930682, + 1273168787, 1172967064, 1475418501, 1509430414, + 1942435775, 2110667444, 1876241833, 1641816226, + -1384747530, -1551933187, -1318815776, -1083344149, + -1789765158, -1688513327, -1992277044, -2025238841, + -583137874, -751368027, -1054072904, -819653965, + -451268222, -351060855, -116905068, -150919521, + 1306967366, 1139781709, 1374988112, 1610459739, + 1975683434, 2076935265, 1775276924, 1742315127, + 1034867998, 866637845, 566021896, 800440835, + 92987698, 193195065, 429456164, 395441711, + 1984812685, 2017778566, 1784663195, 1683407248, + 1315562145, 1080094634, 1383856311, 1551037884, + 101039829, 135050206, 437757123, 337553864, + 1042385657, 807962610, 573804783, 742039012, + -1763899843, -1730933962, -1966138325, -2067394272, + -1359400431, -1594867942, -1293211641, -1126030068, + -426414491, -392404114, -91786125, -191989384, + -558802359, -793225406, -1029488545, -861254316, + 1106041591, 1340463100, 1576976609, 1408749034, + 2043211483, 2009195472, 1708848333, 1809054150, + 832877231, 1068351396, 766945465, 599762354, + 159417987, 126454664, 361929877, 463180190, + -1585706425, -1351284916, -1116860335, -1285087910, + -1722270101, -1756286112, -2058738563, -1958532746, + -785096161, -549621996, -853116919, -1020300030, + -384805325, -417768648, -184398811, -83148498, + -1697160820, -1797362553, -2033878118, -1999866223, + -1561111136, -1392879445, -1092530250, -1326955843, + -358676012, -459930401, -158526526, -125559095, + -759480840, -592301837, -827774994, -1063245083, + 2051518780, 1951317047, 1716890410, 1750902305, + 1113818384, 1282050075, 1584504582, 1350078989, + 168810852, 67556463, 371049330, 404016761, + 841739592, 1008918595, 775550814, 540080725, + -325404927, -493635062, -259478249, -25059300, + -725712083, -625504730, -928212677, -962227152, + -1663901863, -1831087534, -2134850225, -1899378620, + -1527321739, -1426069890, -1192955549, -1225917336, + 202008497, 33778362, 270040487, 504459436, + 875451293, 975658646, 675039627, 641025152, + 2084704233, 1917518562, 1615861247, 1851332852, + 1147550661, 1248802510, 1484005843, 1451044056, + 933301370, 967311729, 733156972, 632953703, + 260388950, 25965917, 328671808, 496906059, + 1206477858, 1239443753, 1543208500, 1441952575, + 2144161806, 1908694277, 1675577880, 1842759443, + -684598070, -650587711, -886847780, -987051049, + -283776794, -518199827, -217582864, -49348613, + -1485196142, -1452230247, -1150570876, -1251826801, + -1621262146, -1856729675, -2091935064, -1924753501 +}; + +const int CRijndael::sm_U2[256] = +{ + 0, 185469197, 370938394, 487725847, + 741876788, 657861945, 975451694, 824852259, + 1483753576, 1400783205, 1315723890, 1164071807, + 1950903388, 2135319889, 1649704518, 1767536459, + -1327460144, -1141990947, -1493400886, -1376613433, + -1663519516, -1747534359, -1966823682, -2117423117, + -393160520, -476130891, -24327518, -175979601, + -995558260, -811141759, -759894378, -642062437, + 2077965243, 1893020342, 1841768865, 1724457132, + 1474502543, 1559041666, 1107234197, 1257309336, + 598438867, 681933534, 901210569, 1052338372, + 261314535, 77422314, 428819965, 310463728, + -885281941, -1070226842, -584599183, -701910916, + -419197089, -334657966, -249586363, -99511224, + -1823743229, -1740248562, -2057834215, -1906706412, + -1082931401, -1266823622, -1452288723, -1570644960, + -156404115, -39616672, -525245321, -339776134, + -627748263, -778347692, -863420349, -947435186, + -1361232379, -1512884472, -1195299809, -1278270190, + -2098914767, -1981082820, -1795618773, -1611202266, + 1179510461, 1296297904, 1347548327, 1533017514, + 1786102409, 1635502980, 2087309459, 2003294622, + 507358933, 355706840, 136428751, 53458370, + 839224033, 957055980, 605657339, 790073846, + -1921626666, -2038938405, -1687527476, -1872472383, + -1588696606, -1438621457, -1219331080, -1134791947, + -721025602, -569897805, -1021700188, -938205527, + -113368694, -231724921, -282971248, -466863459, + 1033297158, 915985419, 730517276, 545572369, + 296679730, 446754879, 129166120, 213705253, + 1709610350, 1860738147, 1945798516, 2029293177, + 1239331162, 1120974935, 1606591296, 1422699085, + -146674470, -61872681, -513933632, -363595827, + -612775698, -797457949, -848962828, -966011911, + -1355701070, -1539330625, -1188186456, -1306280027, + -2096529274, -2012771957, -1793748324, -1642357871, + 1201765386, 1286567175, 1371368976, 1521706781, + 1805211710, 1620529459, 2105887268, 1988838185, + 533804130, 350174575, 164439672, 46346101, + 870912086, 954669403, 636813900, 788204353, + -1936009375, -2020286868, -1702443653, -1853305738, + -1599933611, -1414727080, -1229004465, -1112479678, + -722821367, -538667516, -1024029421, -906460130, + -120407235, -203640272, -288446169, -440360918, + 1014646705, 930369212, 711349675, 560487590, + 272786309, 457992840, 106852767, 223377554, + 1678381017, 1862534868, 1914052035, 2031621326, + 1211247597, 1128014560, 1580087799, 1428173050, + 32283319, 182621114, 401639597, 486441376, + 768917123, 651868046, 1003007129, 818324884, + 1503449823, 1385356242, 1333838021, 1150208456, + 1973745387, 2125135846, 1673061617, 1756818940, + -1324610969, -1174273174, -1492117379, -1407315600, + -1657524653, -1774573730, -1960297399, -2144979644, + -377732593, -495826174, -10465259, -194094824, + -985373125, -833982666, -749177823, -665420500, + 2050466060, 1899603969, 1814803222, 1730525723, + 1443857720, 1560382517, 1075025698, 1260232239, + 575138148, 692707433, 878443390, 1062597235, + 243256656, 91341917, 409198410, 325965383, + -891866660, -1042728751, -590666810, -674944309, + -420538904, -304014107, -252508174, -67301633, + -1834518092, -1716948807, -2068091986, -1883938141, + -1096852096, -1248766835, -1467789414, -1551022441, +}; + +const int CRijndael::sm_U3[256] = +{ + 0, 218828297, 437656594, 387781147, + 875313188, 958871085, 775562294, 590424639, + 1750626376, 1699970625, 1917742170, 2135253587, + 1551124588, 1367295589, 1180849278, 1265195639, + -793714544, -574886247, -895026046, -944901493, + -459482956, -375925059, -24460122, -209597777, + -1192718120, -1243373871, -1560376118, -1342864701, + -1933268740, -2117097739, -1764576018, -1680229657, + -1149510853, -1234119374, -1586641111, -1402549984, + -1890065633, -2107839210, -1790836979, -1739919100, + -752637069, -567761542, -919226527, -1002522264, + -418409641, -368796322, -48656571, -267222708, + 1808481195, 1723872674, 1910319033, 2094410160, + 1608975247, 1391201670, 1173430173, 1224348052, + 59984867, 244860394, 428169201, 344873464, + 935293895, 984907214, 766078933, 547512796, + 1844882806, 1627235199, 2011214180, 2062270317, + 1507497298, 1423022939, 1137477952, 1321699145, + 95345982, 145085239, 532201772, 313773861, + 830661914, 1015671571, 731183368, 648017665, + -1119466010, -1337113617, -1487908364, -1436852227, + -1989511742, -2073986101, -1820562992, -1636341799, + -719438418, -669699161, -821550660, -1039978571, + -516815478, -331805821, -81520232, -164685935, + -695372211, -611944380, -862229921, -1047501738, + -492745111, -274055072, -122203525, -172204942, + -1093335547, -1277294580, -1530717673, -1446505442, + -1963377119, -2014171096, -1863376333, -1645990854, + 104699613, 188127444, 472615631, 287343814, + 840019705, 1058709744, 671593195, 621591778, + 1852171925, 1668212892, 1953757831, 2037970062, + 1514790577, 1463996600, 1080017571, 1297403050, + -621329940, -671330331, -1058972162, -840281097, + -287606328, -472877119, -187865638, -104436781, + -1297141340, -1079754835, -1464259146, -1515052097, + -2038232704, -1954019447, -1667951214, -1851909221, + 172466556, 122466165, 273792366, 492483431, + 1047239000, 861968209, 612205898, 695634755, + 1646252340, 1863638845, 2013908262, 1963115311, + 1446242576, 1530455833, 1277555970, 1093597963, + 1636604631, 1820824798, 2073724613, 1989249228, + 1436590835, 1487645946, 1337376481, 1119727848, + 164948639, 81781910, 331544205, 516552836, + 1039717051, 821288114, 669961897, 719700128, + -1321436601, -1137216434, -1423284651, -1507760036, + -2062531997, -2011476886, -1626972559, -1844621192, + -647755249, -730921978, -1015933411, -830924780, + -314035669, -532464606, -144822727, -95084496, + -1224610662, -1173691757, -1390940024, -1608712575, + -2094148418, -1910056265, -1724135252, -1808742747, + -547775278, -766340389, -984645440, -935031095, + -344611594, -427906305, -245122844, -60246291, + 1739656202, 1790575107, 2108100632, 1890328081, + 1402811438, 1586903591, 1233856572, 1149249077, + 266959938, 48394827, 369057872, 418672217, + 1002783846, 919489135, 567498868, 752375421, + 209336225, 24197544, 376187827, 459744698, + 945164165, 895287692, 574624663, 793451934, + 1679968233, 1764313568, 2117360635, 1933530610, + 1343127501, 1560637892, 1243112415, 1192455638, + -590686415, -775825096, -958608605, -875051734, + -387518699, -437395172, -219090169, -262898, + -1265457287, -1181111952, -1367032981, -1550863006, + -2134991011, -1917480620, -1700232369, -1750889146 +}; + +const int CRijndael::sm_U4[256] = +{ + 0, 151849742, 303699484, 454499602, + 607398968, 758720310, 908999204, 1059270954, + 1214797936, 1097159550, 1517440620, 1400849762, + 1817998408, 1699839814, 2118541908, 2001430874, + -1865371424, -1713521682, -2100648196, -1949848078, + -1260086056, -1108764714, -1493267772, -1342996022, + -658970480, -776608866, -895287668, -1011878526, + -57883480, -176042074, -292105548, -409216582, + 1002142683, 850817237, 698445255, 548169417, + 529487843, 377642221, 227885567, 77089521, + 1943217067, 2061379749, 1640576439, 1757691577, + 1474760595, 1592394909, 1174215055, 1290801793, + -1418998981, -1570324427, -1183720153, -1333995991, + -1889540349, -2041385971, -1656360673, -1807156719, + -486304949, -368142267, -249985705, -132870567, + -952647821, -835013507, -718427793, -601841055, + 1986918061, 2137062819, 1685577905, 1836772287, + 1381620373, 1532285339, 1078185097, 1229899655, + 1040559837, 923313619, 740276417, 621982671, + 439452389, 322734571, 137073913, 19308535, + -423803315, -273658557, -190361519, -39167137, + -1031181707, -880516741, -795640727, -643926169, + -1361764803, -1479011021, -1127282655, -1245576401, + -1964953083, -2081670901, -1728371687, -1846137065, + 1305906550, 1155237496, 1607244650, 1455525988, + 1776460110, 1626319424, 2079897426, 1928707164, + 96392454, 213114376, 396673818, 514443284, + 562755902, 679998000, 865136418, 983426092, + -586793578, -737462632, -820237430, -971956092, + -114159186, -264299872, -349698126, -500888388, + -1787927066, -1671205144, -2022411270, -1904641804, + -1319482914, -1202240816, -1556062270, -1437772596, + -321194175, -438830001, -20913827, -137500077, + -923870343, -1042034569, -621490843, -738605461, + -1531793615, -1379949505, -1230456531, -1079659997, + -2138668279, -1987344377, -1835231979, -1684955621, + 2081048481, 1963412655, 1846563261, 1729977011, + 1480485785, 1362321559, 1243905413, 1126790795, + 878845905, 1030690015, 645401037, 796197571, + 274084841, 425408743, 38544885, 188821243, + -681472870, -563312748, -981755258, -864644728, + -212492126, -94852180, -514869570, -398279248, + -1626745622, -1778065436, -1928084746, -2078357000, + -1153566510, -1305414692, -1457000754, -1607801408, + 1202797690, 1320957812, 1437280870, 1554391400, + 1669664834, 1787304780, 1906247262, 2022837584, + 265905162, 114585348, 499347990, 349075736, + 736970802, 585122620, 972512814, 821712160, + -1699282452, -1816524062, -2001922064, -2120213250, + -1098699308, -1215420710, -1399243832, -1517014842, + -757114468, -606973294, -1060810880, -909622130, + -152341084, -1671510, -453942344, -302225226, + 174567692, 57326082, 410887952, 292596766, + 777231668, 660510266, 1011452712, 893681702, + 1108339068, 1258480242, 1343618912, 1494807662, + 1715193156, 1865862730, 1948373848, 2100090966, + -1593017801, -1476300487, -1290376149, -1172609243, + -2059905521, -1942659839, -1759363053, -1641067747, + -379313593, -529979063, -75615141, -227328171, + -850391425, -1000536719, -548792221, -699985043, + 836553431, 953270745, 600235211, 718002117, + 367585007, 484830689, 133361907, 251657213, + 2041877159, 1891211689, 1806599355, 1654886325, + 1568718495, 1418573201, 1335535747, 1184342925 +}; + +const char CRijndael::sm_rcon[30] = +{ + 1, 2, 4, 8, 16, 32, + 64, -128, 27, 54, 108, -40, + -85, 77, -102, 47, 94, -68, + 99, -58, -105, 53, 106, -44, + -77, 125, -6, -17, -59, -111 +}; + +const int CRijndael::sm_shifts[3][4][2] = +{ + { {0, 0}, {1, 3}, {2, 2}, {3, 1} }, + { {0, 0}, {1, 5}, {2, 4}, {3, 3} }, + { {0, 0}, {1, 7}, {3, 5}, {4, 4} } +}; + +//Error Messages +char const* CRijndael::sm_szErrorMsg1 = "Object not Initialized"; +char const* CRijndael::sm_szErrorMsg2 = "Data not multiple of Block Size"; + +//Null chain +char const* CRijndael::sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + +//CONSTRUCTOR +CRijndael::CRijndael() : m_bKeyInit(false) +{ +} + +//DESTRUCTOR +CRijndael::~CRijndael() +{ +} + +//Expand a user-supplied key material into a session key. +// key - The 128/192/256-bit user-key to use. +// chain - initial chain block for CBC and CFB modes. +// keylength - 16, 24 or 32 bytes +// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes). +void CRijndael::MakeKey(char const* key, char const* chain, int keylength, int blockSize) +{ + if(NULL == key) + throw std::string("Empty key"); + if(!(16==keylength || 24==keylength || 32==keylength)) + throw std::string("Incorrect key length"); + if(!(16==blockSize || 24==blockSize || 32==blockSize)) + throw std::string("Incorrect block length"); + m_keylength = keylength; + m_blockSize = blockSize; + //Initialize the chain + memcpy(m_chain0, chain, m_blockSize); + memcpy(m_chain, chain, m_blockSize); + //Calculate Number of Rounds + switch(m_keylength) + { + case 16: + m_iROUNDS = (m_blockSize == 16) ? 10 : (m_blockSize == 24 ? 12 : 14); + break; + + case 24: + m_iROUNDS = (m_blockSize != 32) ? 12 : 14; + break; + + default: // 32 bytes = 256 bits + m_iROUNDS = 14; + } + int BC = m_blockSize / 4; + int i, j; + for(i=0; i<=m_iROUNDS; i++) + { + for(j=0; j> 16) & 0xFF] & 0xFF) << 24 ^ + (sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ + (sm_S[ tt & 0xFF] & 0xFF) << 8 ^ + (sm_S[(tt >> 24) & 0xFF] & 0xFF) ^ + (sm_rcon[rconpointer++] & 0xFF) << 24; + if(KC != 8) + for(i=1, j=0; i> 8) & 0xFF] & 0xFF) << 8 ^ + (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ + (sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24; + for(j = KC/2, i=j+1; i> 24) & 0xFF] ^ + sm_U2[(tt >> 16) & 0xFF] ^ + sm_U3[(tt >> 8) & 0xFF] ^ + sm_U4[tt & 0xFF]; + } + m_bKeyInit = true; +} + +//Convenience method to encrypt exactly one block of plaintext, assuming +//Rijndael's default block size (128-bit). +// in - The plaintext +// result - The ciphertext generated from a plaintext using the key +void CRijndael::DefEncryptBlock(char const* in, char* result) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + int* Ker = m_Ke[0]; + int t0 = ((unsigned char)*(in++) << 24); + t0 |= ((unsigned char)*(in++) << 16); + t0 |= ((unsigned char)*(in++) << 8); + (t0 |= (unsigned char)*(in++)) ^= Ker[0]; + int t1 = ((unsigned char)*(in++) << 24); + t1 |= ((unsigned char)*(in++) << 16); + t1 |= ((unsigned char)*(in++) << 8); + (t1 |= (unsigned char)*(in++)) ^= Ker[1]; + int t2 = ((unsigned char)*(in++) << 24); + t2 |= ((unsigned char)*(in++) << 16); + t2 |= ((unsigned char)*(in++) << 8); + (t2 |= (unsigned char)*(in++)) ^= Ker[2]; + int t3 = ((unsigned char)*(in++) << 24); + t3 |= ((unsigned char)*(in++) << 16); + t3 |= ((unsigned char)*(in++) << 8); + (t3 |= (unsigned char)*(in++)) ^= Ker[3]; + int a0, a1, a2, a3; + //Apply Round Transforms + for (int r = 1; r < m_iROUNDS; r++) + { + Ker = m_Ke[r]; + a0 = (sm_T1[(t0 >> 24) & 0xFF] ^ + sm_T2[(t1 >> 16) & 0xFF] ^ + sm_T3[(t2 >> 8) & 0xFF] ^ + sm_T4[t3 & 0xFF]) ^ Ker[0]; + a1 = (sm_T1[(t1 >> 24) & 0xFF] ^ + sm_T2[(t2 >> 16) & 0xFF] ^ + sm_T3[(t3 >> 8) & 0xFF] ^ + sm_T4[t0 & 0xFF]) ^ Ker[1]; + a2 = (sm_T1[(t2 >> 24) & 0xFF] ^ + sm_T2[(t3 >> 16) & 0xFF] ^ + sm_T3[(t0 >> 8) & 0xFF] ^ + sm_T4[t1 & 0xFF]) ^ Ker[2]; + a3 = (sm_T1[(t3 >> 24) & 0xFF] ^ + sm_T2[(t0 >> 16) & 0xFF] ^ + sm_T3[(t1 >> 8) & 0xFF] ^ + sm_T4[t2 & 0xFF]) ^ Ker[3]; + t0 = a0; + t1 = a1; + t2 = a2; + t3 = a3; + } + //Last Round is special + Ker = m_Ke[m_iROUNDS]; + int tt = Ker[0]; + result[0] = sm_S[(t0 >> 24) & 0xFF] ^ (tt >> 24); + result[1] = sm_S[(t1 >> 16) & 0xFF] ^ (tt >> 16); + result[2] = sm_S[(t2 >> 8) & 0xFF] ^ (tt >> 8); + result[3] = sm_S[t3 & 0xFF] ^ tt; + tt = Ker[1]; + result[4] = sm_S[(t1 >> 24) & 0xFF] ^ (tt >> 24); + result[5] = sm_S[(t2 >> 16) & 0xFF] ^ (tt >> 16); + result[6] = sm_S[(t3 >> 8) & 0xFF] ^ (tt >> 8); + result[7] = sm_S[t0 & 0xFF] ^ tt; + tt = Ker[2]; + result[8] = sm_S[(t2 >> 24) & 0xFF] ^ (tt >> 24); + result[9] = sm_S[(t3 >> 16) & 0xFF] ^ (tt >> 16); + result[10] = sm_S[(t0 >> 8) & 0xFF] ^ (tt >> 8); + result[11] = sm_S[t1 & 0xFF] ^ tt; + tt = Ker[3]; + result[12] = sm_S[(t3 >> 24) & 0xFF] ^ (tt >> 24); + result[13] = sm_S[(t0 >> 16) & 0xFF] ^ (tt >> 16); + result[14] = sm_S[(t1 >> 8) & 0xFF] ^ (tt >> 8); + result[15] = sm_S[t2 & 0xFF] ^ tt; +} + +//Convenience method to decrypt exactly one block of plaintext, assuming +//Rijndael's default block size (128-bit). +// in - The ciphertext. +// result - The plaintext generated from a ciphertext using the session key. +void CRijndael::DefDecryptBlock(char const* in, char* result) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + int* Kdr = m_Kd[0]; + int t0 = ((unsigned char)*(in++) << 24); + t0 = t0 | ((unsigned char)*(in++) << 16); + t0 |= ((unsigned char)*(in++) << 8); + (t0 |= (unsigned char)*(in++)) ^= Kdr[0]; + int t1 = ((unsigned char)*(in++) << 24); + t1 |= ((unsigned char)*(in++) << 16); + t1 |= ((unsigned char)*(in++) << 8); + (t1 |= (unsigned char)*(in++)) ^= Kdr[1]; + int t2 = ((unsigned char)*(in++) << 24); + t2 |= ((unsigned char)*(in++) << 16); + t2 |= ((unsigned char)*(in++) << 8); + (t2 |= (unsigned char)*(in++)) ^= Kdr[2]; + int t3 = ((unsigned char)*(in++) << 24); + t3 |= ((unsigned char)*(in++) << 16); + t3 |= ((unsigned char)*(in++) << 8); + (t3 |= (unsigned char)*(in++)) ^= Kdr[3]; + int a0, a1, a2, a3; + for(int r = 1; r < m_iROUNDS; r++) // apply round transforms + { + Kdr = m_Kd[r]; + a0 = (sm_T5[(t0 >> 24) & 0xFF] ^ + sm_T6[(t3 >> 16) & 0xFF] ^ + sm_T7[(t2 >> 8) & 0xFF] ^ + sm_T8[ t1 & 0xFF] ) ^ Kdr[0]; + a1 = (sm_T5[(t1 >> 24) & 0xFF] ^ + sm_T6[(t0 >> 16) & 0xFF] ^ + sm_T7[(t3 >> 8) & 0xFF] ^ + sm_T8[ t2 & 0xFF] ) ^ Kdr[1]; + a2 = (sm_T5[(t2 >> 24) & 0xFF] ^ + sm_T6[(t1 >> 16) & 0xFF] ^ + sm_T7[(t0 >> 8) & 0xFF] ^ + sm_T8[ t3 & 0xFF] ) ^ Kdr[2]; + a3 = (sm_T5[(t3 >> 24) & 0xFF] ^ + sm_T6[(t2 >> 16) & 0xFF] ^ + sm_T7[(t1 >> 8) & 0xFF] ^ + sm_T8[ t0 & 0xFF] ) ^ Kdr[3]; + t0 = a0; + t1 = a1; + t2 = a2; + t3 = a3; + } + //Last Round is special + Kdr = m_Kd[m_iROUNDS]; + int tt = Kdr[0]; + result[ 0] = sm_Si[(t0 >> 24) & 0xFF] ^ (tt >> 24); + result[ 1] = sm_Si[(t3 >> 16) & 0xFF] ^ (tt >> 16); + result[ 2] = sm_Si[(t2 >> 8) & 0xFF] ^ (tt >> 8); + result[ 3] = sm_Si[ t1 & 0xFF] ^ tt; + tt = Kdr[1]; + result[ 4] = sm_Si[(t1 >> 24) & 0xFF] ^ (tt >> 24); + result[ 5] = sm_Si[(t0 >> 16) & 0xFF] ^ (tt >> 16); + result[ 6] = sm_Si[(t3 >> 8) & 0xFF] ^ (tt >> 8); + result[ 7] = sm_Si[ t2 & 0xFF] ^ tt; + tt = Kdr[2]; + result[ 8] = sm_Si[(t2 >> 24) & 0xFF] ^ (tt >> 24); + result[ 9] = sm_Si[(t1 >> 16) & 0xFF] ^ (tt >> 16); + result[10] = sm_Si[(t0 >> 8) & 0xFF] ^ (tt >> 8); + result[11] = sm_Si[ t3 & 0xFF] ^ tt; + tt = Kdr[3]; + result[12] = sm_Si[(t3 >> 24) & 0xFF] ^ (tt >> 24); + result[13] = sm_Si[(t2 >> 16) & 0xFF] ^ (tt >> 16); + result[14] = sm_Si[(t1 >> 8) & 0xFF] ^ (tt >> 8); + result[15] = sm_Si[ t0 & 0xFF] ^ tt; +} + +//Encrypt exactly one block of plaintext. +// in - The plaintext. +// result - The ciphertext generated from a plaintext using the key. +void CRijndael::EncryptBlock(char const* in, char* result) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + if(DEFAULT_BLOCK_SIZE == m_blockSize) + { + DefEncryptBlock(in, result); + return; + } + int BC = m_blockSize / 4; + int SC = (BC == 4) ? 0 : (BC == 6 ? 1 : 2); + int s1 = sm_shifts[SC][1][0]; + int s2 = sm_shifts[SC][2][0]; + int s3 = sm_shifts[SC][3][0]; + //Temporary Work Arrays + int i; + int tt; + int* pi = t; + for(i=0; i> 24) & 0xFF] ^ + sm_T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^ + sm_T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^ + sm_T4[ t[(i + s3) % BC] & 0xFF] ) ^ m_Ke[r][i]; + memcpy(t, a, 4*BC); + } + int j; + //Last Round is Special + for(i=0,j=0; i> 24) & 0xFF] ^ (tt >> 24); + result[j++] = sm_S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16); + result[j++] = sm_S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8); + result[j++] = sm_S[ t[(i + s3) % BC] & 0xFF] ^ tt; + } +} + +//Decrypt exactly one block of ciphertext. +// in - The ciphertext. +// result - The plaintext generated from a ciphertext using the session key. +void CRijndael::DecryptBlock(char const* in, char* result) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + if(DEFAULT_BLOCK_SIZE == m_blockSize) + { + DefDecryptBlock(in, result); + return; + } + int BC = m_blockSize / 4; + int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); + int s1 = sm_shifts[SC][1][1]; + int s2 = sm_shifts[SC][2][1]; + int s3 = sm_shifts[SC][3][1]; + //Temporary Work Arrays + int i; + int tt; + int* pi = t; + for(i=0; i> 24) & 0xFF] ^ + sm_T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^ + sm_T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^ + sm_T8[ t[(i + s3) % BC] & 0xFF]) ^ m_Kd[r][i]; + memcpy(t, a, 4*BC); + } + int j; + //Last Round is Special + for(i=0,j=0; i> 24) & 0xFF] ^ (tt >> 24); + result[j++] = sm_Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16); + result[j++] = sm_Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8); + result[j++] = sm_Si[ t[(i + s3) % BC] & 0xFF] ^ tt; + } +} + +void CRijndael::Encrypt(char const* in, char* result, size_t n, int iMode) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + //n should be > 0 and multiple of m_blockSize + if(0==n || n%m_blockSize!=0) + throw std::string(sm_szErrorMsg2); + int i; + char const* pin; + char* presult; + if(CBC == iMode) //CBC mode, using the Chain + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + Xor(m_chain, pin); + EncryptBlock(m_chain, presult); + memcpy(m_chain, presult, m_blockSize); + pin += m_blockSize; + presult += m_blockSize; + } + } + else if(CFB == iMode) //CFB mode, using the Chain + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + EncryptBlock(m_chain, presult); + Xor(presult, pin); + memcpy(m_chain, presult, m_blockSize); + pin += m_blockSize; + presult += m_blockSize; + } + } + else //ECB mode, not using the Chain + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + EncryptBlock(pin, presult); + pin += m_blockSize; + presult += m_blockSize; + } + } +} + +void CRijndael::Decrypt(char const* in, char* result, size_t n, int iMode) +{ + if(false==m_bKeyInit) + throw std::string(sm_szErrorMsg1); + //n should be > 0 and multiple of m_blockSize + if(0==n || n%m_blockSize!=0) + throw std::string(sm_szErrorMsg2); + int i; + char const* pin; + char* presult; + if(CBC == iMode) //CBC mode, using the Chain + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + DecryptBlock(pin, presult); + Xor(presult, m_chain); + memcpy(m_chain, pin, m_blockSize); + pin += m_blockSize; + presult += m_blockSize; + } + } + else if(CFB == iMode) //CFB mode, using the Chain, not using Decrypt() + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + EncryptBlock(m_chain, presult); + //memcpy(presult, pin, m_blockSize); + Xor(presult, pin); + memcpy(m_chain, pin, m_blockSize); + pin += m_blockSize; + presult += m_blockSize; + } + } + else //ECB mode, not using the Chain + { + for(i=0,pin=in,presult=result; i<(int)n/m_blockSize; i++) + { + DecryptBlock(pin, presult); + pin += m_blockSize; + presult += m_blockSize; + } + } +} diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 79d854d6e..76e2f1dee 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -11,6 +11,8 @@ include_directories( set(llmath_SOURCE_FILES llbboxlocal.cpp + llcalc.cpp + llcalcparser.cpp llcamera.cpp llcoordframe.cpp llline.cpp @@ -40,6 +42,8 @@ set(llmath_HEADER_FILES camera.h coordframe.h llbboxlocal.h + llcalc.h + llcalcparser.h llcamera.h llcoord.h llcoordframe.h diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp new file mode 100644 index 000000000..f399463a4 --- /dev/null +++ b/indra/llmath/llcalc.cpp @@ -0,0 +1,150 @@ +/* + * LLCalc.cpp + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalc.h" + +#include "llcalcparser.h" +#include "llmath.h" + + +// Variable names for use in the build floater +const char* LLCalc::X_POS = "PX"; +const char* LLCalc::Y_POS = "PY"; +const char* LLCalc::Z_POS = "PZ"; +const char* LLCalc::X_SCALE = "SX"; +const char* LLCalc::Y_SCALE = "SY"; +const char* LLCalc::Z_SCALE = "SZ"; +const char* LLCalc::X_ROT = "RX"; +const char* LLCalc::Y_ROT = "RY"; +const char* LLCalc::Z_ROT = "RZ"; +const char* LLCalc::HOLLOW = "HLW"; +const char* LLCalc::CUT_BEGIN = "CB"; +const char* LLCalc::CUT_END = "CE"; +const char* LLCalc::PATH_BEGIN = "PB"; +const char* LLCalc::PATH_END = "PE"; +const char* LLCalc::TWIST_BEGIN = "TB"; +const char* LLCalc::TWIST_END = "TE"; +const char* LLCalc::X_SHEAR = "SHX"; +const char* LLCalc::Y_SHEAR = "SHY"; +const char* LLCalc::X_TAPER = "TPX"; +const char* LLCalc::Y_TAPER = "TPY"; +const char* LLCalc::RADIUS_OFFSET = "ROF"; +const char* LLCalc::REVOLUTIONS = "REV"; +const char* LLCalc::SKEW = "SKW"; +const char* LLCalc::X_HOLE = "HLX"; +const char* LLCalc::Y_HOLE = "HLY"; +const char* LLCalc::TEX_U_SCALE = "TSU"; +const char* LLCalc::TEX_V_SCALE = "TSV"; +const char* LLCalc::TEX_U_OFFSET = "TOU"; +const char* LLCalc::TEX_V_OFFSET = "TOV"; +const char* LLCalc::TEX_ROTATION = "TROT"; +const char* LLCalc::TEX_TRANSPARENCY = "TRNS"; +const char* LLCalc::TEX_GLOW = "GLOW"; + + +LLCalc* LLCalc::sInstance = NULL; + +LLCalc::LLCalc() : mLastErrorPos(0) +{ +// mUserVariables = new calc_map_t; + mVariables = new calc_map_t; + mConstants = new calc_map_t; + + // Init table of constants + (*mConstants)["PI"] = F_PI; + (*mConstants)["TWO_PI"] = F_TWO_PI; + (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; + (*mConstants)["SQRT2"] = F_SQRT2; + (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; + (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; + (*mConstants)["GRAVITY"] = GRAVITY; +} + +LLCalc::~LLCalc() +{ + delete mConstants; + delete mVariables; +// delete mUserVariables; +} + +//static +void LLCalc::cleanUp() +{ + delete sInstance; + sInstance = NULL; +} + +//static +LLCalc* LLCalc::getInstance() +{ + if (!sInstance) sInstance = new LLCalc(); + return sInstance; +} + +void LLCalc::setVar(const std::string& name, const F32& value) +{ + (*mVariables)[name] = value; +} + +void LLCalc::clearVar(const std::string& name) +{ + mVariables->erase(name); +} + +void LLCalc::clearAllVariables() +{ + mVariables->clear(); +} + +/* +void LLCalc::updateVariables(LLSD& vars) +{ + LLSD::map_iterator cIt = vars.beginMap(); + for(; cIt != vars.endMap(); cIt++) + { + setVar(cIt->first, (F32)(LLSD::Real)cIt->second); + } +} +*/ + +bool LLCalc::evalString(const std::string& expression, F32& result) +{ + std::string expr_upper = expression; + LLStringUtil::toUpper(expr_upper); + + LLCalcParser calc(result, mConstants, mVariables); + + mLastErrorPos = 0; + std::string::iterator start = expr_upper.begin(); + parse_info info; + + try + { + info = parse(start, expr_upper.end(), calc, space_p); + lldebugs << "Math expression: " << expression << " = " << result << llendl; + } + catch(parser_error &e) + { + mLastErrorPos = e.where - expr_upper.begin(); + + llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl; + return false; + } + + if (!info.full) + { + mLastErrorPos = info.stop - expr_upper.begin(); + llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl; + return false; + } + + return true; +} diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h new file mode 100644 index 000000000..23c83f623 --- /dev/null +++ b/indra/llmath/llcalc.h @@ -0,0 +1,83 @@ +/* + * LLCalc.h + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALC_H +#define LL_CALC_H + +#include +#include + +class LLCalc +{ +public: + LLCalc(); + ~LLCalc(); + + // Variable name constants + static const char* X_POS; + static const char* Y_POS; + static const char* Z_POS; + static const char* X_SCALE; + static const char* Y_SCALE; + static const char* Z_SCALE; + static const char* X_ROT; + static const char* Y_ROT; + static const char* Z_ROT; + static const char* HOLLOW; + static const char* CUT_BEGIN; + static const char* CUT_END; + static const char* PATH_BEGIN; + static const char* PATH_END; + static const char* TWIST_BEGIN; + static const char* TWIST_END; + static const char* X_SHEAR; + static const char* Y_SHEAR; + static const char* X_TAPER; + static const char* Y_TAPER; + static const char* RADIUS_OFFSET; + static const char* REVOLUTIONS; + static const char* SKEW; + static const char* X_HOLE; + static const char* Y_HOLE; + static const char* TEX_U_SCALE; + static const char* TEX_V_SCALE; + static const char* TEX_U_OFFSET; + static const char* TEX_V_OFFSET; + static const char* TEX_ROTATION; + static const char* TEX_TRANSPARENCY; + static const char* TEX_GLOW; + + void setVar(const std::string& name, const F32& value); + void clearVar(const std::string& name); + void clearAllVariables(); +// void updateVariables(LLSD& vars); + + bool evalString(const std::string& expression, F32& result); + std::string::size_type getLastErrorPos() { return mLastErrorPos; } + + static LLCalc* getInstance(); + static void cleanUp(); + + typedef std::map calc_map_t; + +private: + std::string::size_type mLastErrorPos; + + calc_map_t* mConstants; + calc_map_t* mVariables; + + // *TODO: Add support for storing user defined variables, and stored functions. + // Will need UI work, and a means to save them between sessions. +// calc_map_t* mUserVariables; + + // "There shall be only one" + static LLCalc* sInstance; +}; + +#endif // LL_CALC_H diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp new file mode 100644 index 000000000..fd55376fa --- /dev/null +++ b/indra/llmath/llcalcparser.cpp @@ -0,0 +1,46 @@ +/* + * LLCalcParser.cpp + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalcparser.h" +using namespace boost::spirit::classic; + +F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const +{ + LLCalc::calc_map_t::iterator iter; + + std::string name(start, end); + + if (mConstants) + { + iter = mConstants->find(name); + if (iter != mConstants->end()) + { + return (*iter).second; + } + } + else + { + // This should never happen! + throw_(end, std::string("Missing constants table")); + } + + if (mVariables) + { + iter = mVariables->find(name); + if (iter != mVariables->end()) + { + return (*iter).second; + } + } + + throw_(end, std::string("Unknown symbol " + name)); + return 0.f; +} diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h new file mode 100644 index 000000000..a759a3571 --- /dev/null +++ b/indra/llmath/llcalcparser.h @@ -0,0 +1,169 @@ +/* + * LLCalcParser.h + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALCPARSER_H +#define LL_CALCPARSER_H + +#include +#include +#include +#include +#include +#include +using namespace boost::spirit::classic; + +#include "llcalc.h" +#include "llmath.h" + +struct LLCalcParser : grammar +{ + LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : + mResult(result), mConstants(constants), mVariables(vars) {}; + + struct value_closure : closure + { + member1 value; + }; + + template + struct definition + { + // Rule declarations + rule statement, identifier; + rule expression, term, + power, + unary_expr, + factor, + unary_func, + binary_func, + group; + + // start() should return the starting symbol + rule const& start() const { return statement; } + + definition(LLCalcParser const& self) + { + using namespace phoenix; + + assertion assert_domain("Domain error"); +// assertion assert_symbol("Unknown symbol"); + assertion assert_syntax("Syntax error"); + + identifier = + lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] + ; + + group = + '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) + ; + + unary_func = + ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) | + (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) | + (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) | + (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) | + (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) | + (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) | + (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | + (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | + (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | + (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + binary_func = + ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | + (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | + (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + // *TODO: Localisation of the decimal point? + // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate + // for the current locale. However to do that here could clash with using + // the comma as a separator when passing arguments to functions. + factor = + (ureal_p[factor.value = arg1] | + group[factor.value = arg1] | + unary_func[factor.value = arg1] | + binary_func[factor.value = arg1] | + // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, + // would be "neater" to handle symbol lookup from here with an assertive parser. +// constants_p[factor.value = arg1]| + identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)] + ) >> + // Detect and throw math errors. + assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value))) + ; + + unary_expr = + !ch_p('+') >> factor[unary_expr.value = arg1] | + '-' >> factor[unary_expr.value = -arg1] + ; + + power = + unary_expr[power.value = arg1] >> + *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)])) + ; + + term = + power[term.value = arg1] >> + *(('*' >> assert_syntax(power[term.value *= arg1])) | + ('/' >> assert_syntax(power[term.value /= arg1])) + ) + ; + + expression = + assert_syntax(term[expression.value = arg1]) >> + *(('+' >> assert_syntax(term[expression.value += arg1])) | + ('-' >> assert_syntax(term[expression.value -= arg1])) + ) + ; + + statement = + !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) + ; + } + }; + +private: + // Member functions for semantic actions + F32 lookup(const std::string::iterator&, const std::string::iterator&) const; + F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } + F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } + + bool checkNaN(const F32& a) const { return !llisnan(a); } + + //FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz + F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } + F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } + F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } + F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); } + F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); } + F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); } + F32 _sqrt(const F32& a) const { return sqrt(a); } + F32 _log(const F32& a) const { return log(a); } + F32 _exp(const F32& a) const { return exp(a); } + F32 _fabs(const F32& a) const { return fabs(a) * RAD_TO_DEG; } + + F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + + + + LLCalc::calc_map_t* mConstants; + LLCalc::calc_map_t* mVariables; +// LLCalc::calc_map_t* mUserVariables; + + F32& mResult; +}; + +#endif // LL_CALCPARSER_H diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 970162329..dc628e79d 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -599,32 +599,32 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb impl.mReplyQueue.push_back(PendingReply(id, callback, user_data)); } } -// -BOOL LLCacheName::getIfThere(const LLUUID& id, std::string& fullname, BOOL& is_group) -{ - if(id.isNull()) - { - fullname = ""; - return FALSE; - } - - LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id ); - if (entry) - { - if (entry->mIsGroup) - { - fullname = entry->mGroupName; - } - else - { - fullname = entry->mFirstName + " " + entry->mLastName; - } - is_group = entry->mIsGroup; - return TRUE; - } - fullname = ""; - return FALSE; -} +// +BOOL LLCacheName::getIfThere(const LLUUID& id, std::string& fullname, BOOL& is_group) +{ + if(id.isNull()) + { + fullname = ""; + return FALSE; + } + + LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id ); + if (entry) + { + if (entry->mIsGroup) + { + fullname = entry->mGroupName; + } + else + { + fullname = entry->mFirstName + " " + entry->mLastName; + } + is_group = entry->mIsGroup; + return TRUE; + } + fullname = ""; + return FALSE; +} // void LLCacheName::processPending() { diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 9524a88ba..773c23ef2 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -91,8 +91,8 @@ public: // available. There is no garuntee the callback will ever be called. void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); - // - BOOL getIfThere(const LLUUID& id, std::string& fullname, BOOL& is_group); + // + BOOL getIfThere(const LLUUID& id, std::string& fullname, BOOL& is_group); // // LEGACY diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index c3841347f..3ea94c52b 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -550,76 +550,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak S32 receive_size = 0; do { - // - // Expire old canary entries - F64 now = LLTimer::getElapsedSeconds(); - std::map::iterator canary_entry_iter; - std::map::iterator canary_entry_end = mCanaryEntries.end(); - for( canary_entry_iter = mCanaryEntries.begin(); - canary_entry_iter != mCanaryEntries.end(); ) - { - if( ((*canary_entry_iter).second.time + 30.0f) < now) - { - llinfos << "Expiring ban on " << (*canary_entry_iter).second.name << " message, " << (*canary_entry_iter).second.points << " points" << llendl; - mCanaryEntries.erase(canary_entry_iter++); - } - else - { - canary_entry_iter++; - } - } - if(!faked_message && mSpoofProtectionLevel > 1) - { - // Canaries receive - std::vector::iterator canary_iter = mCanaries.begin(); - std::vector::iterator canary_end = mCanaries.end(); - for( ; canary_iter != canary_end; ++canary_iter) - { - U8* canary_buffer = (*canary_iter)->mBuffer; - S32 len = receive_packet((*canary_iter)->mSocket, (char*)canary_buffer); - if(len) - { - //llinfos << "canary received " << len << " bytes on port " << (*canary_iter)->mPort << llendl; - zeroCodeExpand(&canary_buffer, &len); - if(len < 7) continue; // too short to be an slmsg - LLNetCanary::entry entry; - entry.message = 0; - if(canary_buffer[6] != 0xFF) // High XX - entry.message = canary_buffer[6]; - else if((len >= 8) && (canary_buffer[7] != 0xFF)) // Medium FFXX - entry.message = (255 << 8) | canary_buffer[7]; - else if((len >= 10) && (canary_buffer[7] == 0xFF)) // Low FFFFXXXX - { - U16 message_id_U16 = 0; - memcpy(&message_id_U16, &canary_buffer[8], 2); - message_id_U16 = ntohs(message_id_U16); - entry.message = 0xFFFF0000 | message_id_U16; - } - else continue; // not an slmsg - - if(mCanaryEntries.find(entry.message) == mCanaryEntries.end()) - { - // brand new entry - LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers, entry.message); - entry.name = temp ? temp->mName : "Invalid"; - entry.points = 1; - entry.time = now; - mCanaryEntries[entry.message] = entry; - if(mSpoofProtectionLevel == 2) - llinfos << "Temporarily banning a " << entry.name << " message" << llendl; - } - else - { - // strike two, three... - mCanaryEntries[entry.message].points++; - mCanaryEntries[entry.message].time = now; - if((mSpoofProtectionLevel > 2) && (mCanaryEntries[entry.message].points == 2)) - llinfos << "Temporarily banning a " << mCanaryEntries[entry.message].name << " message" << llendl; - } - } - } - } - // clearReceiveState(); BOOL recv_reliable = FALSE; @@ -646,12 +576,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak // If you want to dump all received packets into SecondLife.log, uncomment this //dumpPacketToLog(); - // - if(mTrueReceiveSize && receive_size > (S32) LL_MINIMUM_VALID_PACKET_SIZE && !faked_message) - { - LLMessageLog::log(mLastSender, LLHost(16777343, mPort), buffer, mTrueReceiveSize); - } - // if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE) @@ -695,61 +619,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak // process the message as normal mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size); mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1]))); - // - BOOL spoofed_packet = FALSE; - if(!faked_message && mSpoofProtectionLevel > 0) - { - S32 len = receive_size; - U32 message = 0; - if(buffer[6] != 0xFF) // High XX - message = buffer[6]; - else if((len >= 8) && (buffer[7] != 0xFF)) // Medium FFXX - message = (255 << 8) | buffer[7]; - else if((len >= 10) && (buffer[7] == 0xFF)) // Low FFFFXXXX - { - U16 message_id_U16 = 0; - memcpy(&message_id_U16, &buffer[8], 2); - message_id_U16 = ntohs(message_id_U16); - message = 0xFFFF0000 | message_id_U16; - } - if(!mCurrentRecvPacketID) - { - LL_WARNS("Messaging") << "CODE DONKEY_A" << llendl; - if(mSpoofDroppedCallback) - { - LLNetCanary::entry entry; - LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers, message); - entry.name = temp ? temp->mName : "Invalid"; - entry.message = message; - entry.time = now; - entry.points = 1; - mSpoofDroppedCallback(entry); - } - spoofed_packet = TRUE; - valid_packet = FALSE; - } - else if((mSpoofProtectionLevel > 1) && (receive_size >= 7)) - { - if(mCanaryEntries.find(message) != mCanaryEntries.end()) - { - if( - (mSpoofProtectionLevel == 2) || - (mCanaryEntries[message].points > 1) - ) - { - LL_WARNS("Messaging") << "Dropped probably spoofed " << mCanaryEntries[message].name << " packet, " << mCanaryEntries[message].points << " points" << llendl; - if(mSpoofDroppedCallback) - { - mSpoofDroppedCallback(mCanaryEntries[message]); - } - spoofed_packet = TRUE; - valid_packet = FALSE; - break; - } - } - } - } // mSpoofProtectionLevel - // + host = getSender(); const bool resetPacketId = true; @@ -832,9 +702,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak // But we don't want to acknowledge UseCircuitCode until the circuit is // available, which is why the acknowledgement test is done above. JC bool trusted = cdp && cdp->getTrusted(); - // - if(!spoofed_packet) - // + valid_packet = mTemplateMessageReader->validateMessage( buffer, receive_size, @@ -2850,9 +2718,6 @@ void end_messaging_system(bool print_summary) LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile if (gMessageSystem) { - // - gMessageSystem->stopSpoofProtection(); - // gMessageSystem->stopLogging(); if (print_summary) @@ -4216,154 +4081,10 @@ const LLHost& LLMessageSystem::getSender() const LLHTTPRegistration > gHTTPRegistrationTrustedMessageWildcard("/trusted-message/"); // -void LLMessageSystem::startSpoofProtection(U32 level) -{ - if(!mPort) - { - llwarns << "listen port is 0!!!" << llendl; - } - - mSpoofProtectionLevel = level; - mCanaries.clear(); - mCanaryEntries.clear(); - // Make canaries - std::string canary_info(""); - - if(mSpoofProtectionLevel > 2) // 3 or greater - { - // FULL CANARY POWER - int rPort = 768 + ll_rand(32); - if(mPort < rPort) rPort = mPort - 16; - if(rPort < 1) rPort = 1; - while(rPort < 65536) - { - if(rPort != mPort) - { - LLNetCanary* canary = new LLNetCanary(rPort); - if(canary->mGood) - { - mCanaries.push_back(canary); - canary_info.append(llformat(" %d", canary->mPort)); - } - else - delete canary; - } - int dist = llabs(mPort - rPort); - if(dist > 4096) - rPort += ll_rand(2048) + 2048; - else if(dist > 2048) - rPort += ll_rand(1024) + 1024; - else if(dist > 1024) - rPort += ll_rand(512) + 512; - else if(dist > 512) - rPort += ll_rand(256) + 256; - else if(dist > 128) - rPort += ll_rand(64) + 64; - else if(dist > 16) - rPort += ll_rand(8) + 8; - else - rPort += 4; - } - } - else if(mSpoofProtectionLevel == 2) - { - // Minimal canaries - for(int o = -32; o <= 32; o += 8) - { - int rPort = mPort + o; - if(rPort != mPort) - { - LLNetCanary* canary = new LLNetCanary(rPort); - if(canary->mGood) - { - mCanaries.push_back(canary); - canary_info.append(llformat(" %d", canary->mPort)); - } - else - delete canary; - } - } - } - - if(mCanaries.size()) - { - llinfos << "level " << mSpoofProtectionLevel << ", " << mCanaries.size() << " canaries: " << canary_info << llendl; - } - else - { - llinfos << "level " << mSpoofProtectionLevel << ", no canaries" << llendl; - } -} - -void LLMessageSystem::stopSpoofProtection() -{ - llinfos << "cleaning up" << llendl; - // Shut down canaries - std::vector::iterator canary_iter = mCanaries.begin(); - std::vector::iterator canary_end = mCanaries.end(); - for( ; canary_iter != canary_end; ++canary_iter) - { - LLNetCanary* canary = (*canary_iter); - delete canary; - } - mCanaries.clear(); - // Empty canary entries - mCanaryEntries.clear(); -} - -void LLMessageSystem::setSpoofDroppedCallback(void (*callback)(LLNetCanary::entry)) -{ - mSpoofDroppedCallback = callback; -} // Copypasta from LLTemplateMessageReader BOOL LLMessageSystem::decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template ) { - const U8* header = buffer + LL_PACKET_ID_SIZE; - if (buffer_size <= 0) return FALSE; - U32 num = 0; - if (header[0] != 255) - { - // high frequency message - num = header[0]; - } - else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255)) - { - // medium frequency message - num = (255 << 8) | header[1]; - } - else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255)) - { - // low frequency message - U16 message_id_U16 = 0; - // I think this check busts the message system. - // it appears that if there is a NULL in the message #, it won't copy it.... - // what was the goal? - //if(header[2]) - memcpy(&message_id_U16, &header[2], 2); - - // dependant on endian-ness: - // U32 temp = (255 << 24) | (255 << 16) | header[2]; - - // independant of endian-ness: - message_id_U16 = ntohs(message_id_U16); - num = 0xFFFF0000 | message_id_U16; - } - else // bogus packet received (too short) - { - return(FALSE); - } - - LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num); - if (temp) - { - *msg_template = temp; - } - else - { - return(FALSE); - } - return(TRUE); } // - U32 mSpoofProtectionLevel; - std::vector mCanaries; - std::map mCanaryEntries; - void (*mSpoofDroppedCallback)(LLNetCanary::entry); - // bool mBlockUntrustedInterface; LLHost mUntrustedInterface; @@ -622,12 +616,6 @@ public: // Change this message to be UDP black listed. void banUdpMessage(const std::string& name); - // - void startSpoofProtection(U32 level); - void stopSpoofProtection(); - void setSpoofDroppedCallback(void (*callback)(LLNetCanary::entry)); - // - private: // A list of the circuits that need to be sent DenyTrustedCircuit messages. typedef std::set host_set_t; diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp index e3c25dd0a..39ee1b04d 100644 --- a/indra/llprimitive/llmaterialtable.cpp +++ b/indra/llprimitive/llmaterialtable.cpp @@ -1,518 +1,518 @@ -/** - * @file llmaterialtable.cpp - * @brief Table of material names and IDs for viewer - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llmaterialtable.h" -#include "llstl.h" -#include "material_codes.h" -#include "sound_ids.h" -#include "imageids.h" - -LLMaterialTable LLMaterialTable::basic(1); - -/* - Old Havok 1 constants - -// these are the approximately correct friction values for various materials -// however Havok1's friction dynamics are not very correct, so the effective -// friction coefficients that result from these numbers are approximately -// 25-50% too low, more incorrect for the lower values. -F32 const LLMaterialTable::FRICTION_MIN = 0.2f; -F32 const LLMaterialTable::FRICTION_GLASS = 0.2f; // borosilicate glass -F32 const LLMaterialTable::FRICTION_LIGHT = 0.2f; // -F32 const LLMaterialTable::FRICTION_METAL = 0.3f; // steel -F32 const LLMaterialTable::FRICTION_PLASTIC = 0.4f; // HDPE -F32 const LLMaterialTable::FRICTION_WOOD = 0.6f; // southern pine -F32 const LLMaterialTable::FRICTION_FLESH = 0.60f; // saltwater -F32 const LLMaterialTable::FRICTION_LAND = 0.78f; // dirt -F32 const LLMaterialTable::FRICTION_STONE = 0.8f; // concrete -F32 const LLMaterialTable::FRICTION_RUBBER = 0.9f; // -F32 const LLMaterialTable::FRICTION_MAX = 0.95f; // -*/ - -// #if LL_CURRENT_HAVOK_VERSION == LL_HAVOK_VERSION_460 -// Havok4 has more correct friction dynamics, however here we have to use -// the "incorrect" equivalents for the legacy Havok1 behavior -F32 const LLMaterialTable::FRICTION_MIN = 0.15f; -F32 const LLMaterialTable::FRICTION_GLASS = 0.13f; // borosilicate glass -F32 const LLMaterialTable::FRICTION_LIGHT = 0.14f; // -F32 const LLMaterialTable::FRICTION_METAL = 0.22f; // steel -F32 const LLMaterialTable::FRICTION_PLASTIC = 0.3f; // HDPE -F32 const LLMaterialTable::FRICTION_WOOD = 0.44f; // southern pine -F32 const LLMaterialTable::FRICTION_FLESH = 0.46f; // saltwater -F32 const LLMaterialTable::FRICTION_LAND = 0.58f; // dirt -F32 const LLMaterialTable::FRICTION_STONE = 0.6f; // concrete -F32 const LLMaterialTable::FRICTION_RUBBER = 0.67f; // -F32 const LLMaterialTable::FRICTION_MAX = 0.71f; // -// #endif - -F32 const LLMaterialTable::RESTITUTION_MIN = 0.02f; -F32 const LLMaterialTable::RESTITUTION_LAND = LLMaterialTable::RESTITUTION_MIN; -F32 const LLMaterialTable::RESTITUTION_FLESH = 0.2f; // saltwater -F32 const LLMaterialTable::RESTITUTION_STONE = 0.4f; // concrete -F32 const LLMaterialTable::RESTITUTION_METAL = 0.4f; // steel -F32 const LLMaterialTable::RESTITUTION_WOOD = 0.5f; // southern pine -F32 const LLMaterialTable::RESTITUTION_GLASS = 0.7f; // borosilicate glass -F32 const LLMaterialTable::RESTITUTION_PLASTIC = 0.7f; // HDPE -F32 const LLMaterialTable::RESTITUTION_LIGHT = 0.7f; // -F32 const LLMaterialTable::RESTITUTION_RUBBER = 0.9f; // -F32 const LLMaterialTable::RESTITUTION_MAX = 0.95f; - -F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f; -F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f; - -LLMaterialTable::LLMaterialTable() -{ -} - -LLMaterialTable::LLMaterialTable(U8 isBasic) -{ - initBasicTable(); -} - -LLMaterialTable::~LLMaterialTable() -{ - if (mCollisionSoundMatrix) - { - delete [] mCollisionSoundMatrix; - mCollisionSoundMatrix = NULL; - } - - if (mSlidingSoundMatrix) - { - delete [] mSlidingSoundMatrix; - mSlidingSoundMatrix = NULL; - } - - if (mRollingSoundMatrix) - { - delete [] mRollingSoundMatrix; - mRollingSoundMatrix = NULL; - } - - for_each(mMaterialInfoList.begin(), mMaterialInfoList.end(), DeletePointer()); - mMaterialInfoList.clear(); -} - -void LLMaterialTable::initBasicTable() -{ - // *TODO: Translate - add(LL_MCODE_STONE,std::string("Stone"), LL_DEFAULT_STONE_UUID); - add(LL_MCODE_METAL,std::string("Metal"), LL_DEFAULT_METAL_UUID); - add(LL_MCODE_GLASS,std::string("Glass"), LL_DEFAULT_GLASS_UUID); - add(LL_MCODE_WOOD,std::string("Wood"), LL_DEFAULT_WOOD_UUID); - add(LL_MCODE_FLESH,std::string("Flesh"), LL_DEFAULT_FLESH_UUID); - add(LL_MCODE_PLASTIC,std::string("Plastic"), LL_DEFAULT_PLASTIC_UUID); - add(LL_MCODE_RUBBER,std::string("Rubber"), LL_DEFAULT_RUBBER_UUID); - add(LL_MCODE_LIGHT,std::string("Light"), LL_DEFAULT_LIGHT_UUID); - - // specify densities for these materials. . . - // these were taken from http://www.mcelwee.net/html/densities_of_various_materials.html - - addDensity(LL_MCODE_STONE,30.f); - addDensity(LL_MCODE_METAL,50.f); - addDensity(LL_MCODE_GLASS,20.f); - addDensity(LL_MCODE_WOOD,10.f); - addDensity(LL_MCODE_FLESH,10.f); - addDensity(LL_MCODE_PLASTIC,5.f); - addDensity(LL_MCODE_RUBBER,0.5f); // - addDensity(LL_MCODE_LIGHT,20.f); // - - // add damage and energy values - addDamageAndEnergy(LL_MCODE_STONE, 1.f, 1.f, 1.f); // concrete - addDamageAndEnergy(LL_MCODE_METAL, 1.f, 1.f, 1.f); // steel - addDamageAndEnergy(LL_MCODE_GLASS, 1.f, 1.f, 1.f); // borosilicate glass - addDamageAndEnergy(LL_MCODE_WOOD, 1.f, 1.f, 1.f); // southern pine - addDamageAndEnergy(LL_MCODE_FLESH, 1.f, 1.f, 1.f); // saltwater - addDamageAndEnergy(LL_MCODE_PLASTIC, 1.f, 1.f, 1.f); // HDPE - addDamageAndEnergy(LL_MCODE_RUBBER, 1.f, 1.f, 1.f); // - addDamageAndEnergy(LL_MCODE_LIGHT, 1.f, 1.f, 1.f); // - - addFriction(LL_MCODE_STONE,0.8f); // concrete - addFriction(LL_MCODE_METAL,0.3f); // steel - addFriction(LL_MCODE_GLASS,0.2f); // borosilicate glass - addFriction(LL_MCODE_WOOD,0.6f); // southern pine - addFriction(LL_MCODE_FLESH,0.9f); // saltwater - addFriction(LL_MCODE_PLASTIC,0.4f); // HDPE - addFriction(LL_MCODE_RUBBER,0.9f); // - addFriction(LL_MCODE_LIGHT,0.2f); // - - addRestitution(LL_MCODE_STONE,0.4f); // concrete - addRestitution(LL_MCODE_METAL,0.4f); // steel - addRestitution(LL_MCODE_GLASS,0.7f); // borosilicate glass - addRestitution(LL_MCODE_WOOD,0.5f); // southern pine - addRestitution(LL_MCODE_FLESH,0.3f); // saltwater - addRestitution(LL_MCODE_PLASTIC,0.7f); // HDPE - addRestitution(LL_MCODE_RUBBER,0.9f); // - addRestitution(LL_MCODE_LIGHT,0.7f); // - - addShatterSound(LL_MCODE_STONE,LLUUID("ea296329-0f09-4993-af1b-e6784bab1dc9")); - addShatterSound(LL_MCODE_METAL,LLUUID("d1375446-1c4d-470b-9135-30132433b678")); - addShatterSound(LL_MCODE_GLASS,LLUUID("85cda060-b393-48e6-81c8-2cfdfb275351")); - addShatterSound(LL_MCODE_WOOD,LLUUID("6f00669f-15e0-4793-a63e-c03f62fee43a")); - addShatterSound(LL_MCODE_FLESH,LLUUID("2d8c6f51-149e-4e23-8413-93a379b42b67")); - addShatterSound(LL_MCODE_PLASTIC,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); - addShatterSound(LL_MCODE_RUBBER,LLUUID("212b6d1e-8d9c-4986-b3aa-f3c6df8d987d")); - addShatterSound(LL_MCODE_LIGHT,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); - - // CollisionSounds - mCollisionSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; - if (mCollisionSoundMatrix) - { - addCollisionSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_STONE_STONE); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_STONE_METAL); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_STONE_GLASS); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_STONE_WOOD); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_STONE_FLESH); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_STONE_PLASTIC); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_STONE_RUBBER); - addCollisionSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_STONE_PLASTIC); - - addCollisionSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_METAL_METAL); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_METAL_GLASS); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_METAL_WOOD); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_METAL_FLESH); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_METAL_PLASTIC); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_METAL_PLASTIC); - addCollisionSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_METAL_RUBBER); - - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_GLASS_GLASS); - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_GLASS_WOOD); - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_GLASS_FLESH); - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_GLASS_PLASTIC); - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_GLASS_RUBBER); - addCollisionSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_GLASS_PLASTIC); - - addCollisionSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_WOOD_WOOD); - addCollisionSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_WOOD_FLESH); - addCollisionSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_WOOD_PLASTIC); - addCollisionSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_WOOD_RUBBER); - addCollisionSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_WOOD_PLASTIC); - - addCollisionSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_FLESH_FLESH); - addCollisionSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_FLESH_PLASTIC); - addCollisionSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_FLESH_RUBBER); - addCollisionSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_FLESH_PLASTIC); - - addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_RUBBER_RUBBER); - addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_RUBBER_PLASTIC); - addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_RUBBER_PLASTIC); - - addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_PLASTIC_PLASTIC); - addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); - - addCollisionSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); - } - - // Sliding Sounds - mSlidingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; - if (mSlidingSoundMatrix) - { - addSlidingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_SLIDE_STONE_STONE); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_SLIDE_STONE_WOOD); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_SLIDE_STONE_PLASTIC); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_RUBBER); - addSlidingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_SLIDE_STONE_PLASTIC); - - addSlidingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_METAL_METAL); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_SLIDE_METAL_GLASS); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_SLIDE_METAL_WOOD); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_METAL_FLESH); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_METAL_RUBBER); - addSlidingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addSlidingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_SLIDE_WOOD_WOOD); - addSlidingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_SLIDE_WOOD_FLESH); - addSlidingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_SLIDE_WOOD_PLASTIC); - addSlidingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_SLIDE_WOOD_PLASTIC); - - addSlidingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_FLESH_FLESH); - addSlidingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_RUBBER_PLASTIC); - addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_RUBBER_PLASTIC); - - addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addSlidingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - } - - // Rolling Sounds - mRollingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; - if (mRollingSoundMatrix) - { - addRollingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_ROLL_STONE_STONE); - addRollingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_ROLL_STONE_WOOD); - addRollingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_ROLL_STONE_PLASTIC); - addRollingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_ROLL_STONE_PLASTIC); - - addRollingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_ROLL_METAL_GLASS); - addRollingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_ROLL_METAL_WOOD); - addRollingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_ROLL_METAL_WOOD); - addRollingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_ROLL_METAL_WOOD); - - addRollingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_ROLL_GLASS_WOOD); - addRollingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addRollingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_ROLL_WOOD_WOOD); - addRollingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_ROLL_WOOD_FLESH); - addRollingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_ROLL_WOOD_PLASTIC); - addRollingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_ROLL_WOOD_PLASTIC); - - addRollingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_ROLL_FLESH_PLASTIC); - addRollingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_ROLL_FLESH_PLASTIC); - - addRollingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); - addRollingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); - - addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_ROLL_PLASTIC_PLASTIC); - addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); - - addRollingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); - } -} - -BOOL LLMaterialTable::add(U8 mcode, const std::string& name, const LLUUID &uuid) -{ - LLMaterialInfo *infop; - - infop = new LLMaterialInfo(mcode,name,uuid); - if (!infop) return FALSE; - - // Add at the end so the order in menus matches the order in this - // file. JNC 11.30.01 - mMaterialInfoList.push_back(infop); - - return TRUE; -} - -BOOL LLMaterialTable::addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid) -{ - if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; - if (mcode != mcode2) - { - mCollisionSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; - } - } - return TRUE; -} - -BOOL LLMaterialTable::addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) -{ - if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; - if (mcode != mcode2) - { - mSlidingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; - } - } - return TRUE; -} - -BOOL LLMaterialTable::addRollingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) -{ - if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; - if (mcode != mcode2) - { - mRollingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; - } - } - return TRUE; -} - -BOOL LLMaterialTable::addShatterSound(U8 mcode, const LLUUID &uuid) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - infop->mShatterSoundID = uuid; - return TRUE; - } - } - - return FALSE; -} - -BOOL LLMaterialTable::addDensity(U8 mcode, const F32 &density) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - infop->mDensity = density; - return TRUE; - } - } - - return FALSE; -} - -BOOL LLMaterialTable::addRestitution(U8 mcode, const F32 &restitution) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - infop->mRestitution = restitution; - return TRUE; - } - } - - return FALSE; -} - -BOOL LLMaterialTable::addFriction(U8 mcode, const F32 &friction) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - infop->mFriction = friction; - return TRUE; - } - } - - return FALSE; -} - -BOOL LLMaterialTable::addDamageAndEnergy(U8 mcode, const F32 &hp_mod, const F32 &damage_mod, const F32 &ep_mod) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - infop->mHPModifier = hp_mod; - infop->mDamageModifier = damage_mod; - infop->mEPModifier = ep_mod; - return TRUE; - } - } - - return FALSE; -} - -LLUUID LLMaterialTable::getDefaultTextureID(const std::string& name) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (name == infop->mName) - { - return infop->mDefaultTextureID; - } - } - - return LLUUID::null; -} - - -LLUUID LLMaterialTable::getDefaultTextureID(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mDefaultTextureID; - } - } - - return LLUUID::null; -} - - -U8 LLMaterialTable::getMCode(const std::string& name) -{ - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (name == infop->mName) - { - return infop->mMCode; - } - } - +/** + * @file llmaterialtable.cpp + * @brief Table of material names and IDs for viewer + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llmaterialtable.h" +#include "llstl.h" +#include "material_codes.h" +#include "sound_ids.h" +#include "imageids.h" + +LLMaterialTable LLMaterialTable::basic(1); + +/* + Old Havok 1 constants + +// these are the approximately correct friction values for various materials +// however Havok1's friction dynamics are not very correct, so the effective +// friction coefficients that result from these numbers are approximately +// 25-50% too low, more incorrect for the lower values. +F32 const LLMaterialTable::FRICTION_MIN = 0.2f; +F32 const LLMaterialTable::FRICTION_GLASS = 0.2f; // borosilicate glass +F32 const LLMaterialTable::FRICTION_LIGHT = 0.2f; // +F32 const LLMaterialTable::FRICTION_METAL = 0.3f; // steel +F32 const LLMaterialTable::FRICTION_PLASTIC = 0.4f; // HDPE +F32 const LLMaterialTable::FRICTION_WOOD = 0.6f; // southern pine +F32 const LLMaterialTable::FRICTION_FLESH = 0.60f; // saltwater +F32 const LLMaterialTable::FRICTION_LAND = 0.78f; // dirt +F32 const LLMaterialTable::FRICTION_STONE = 0.8f; // concrete +F32 const LLMaterialTable::FRICTION_RUBBER = 0.9f; // +F32 const LLMaterialTable::FRICTION_MAX = 0.95f; // +*/ + +// #if LL_CURRENT_HAVOK_VERSION == LL_HAVOK_VERSION_460 +// Havok4 has more correct friction dynamics, however here we have to use +// the "incorrect" equivalents for the legacy Havok1 behavior +F32 const LLMaterialTable::FRICTION_MIN = 0.15f; +F32 const LLMaterialTable::FRICTION_GLASS = 0.13f; // borosilicate glass +F32 const LLMaterialTable::FRICTION_LIGHT = 0.14f; // +F32 const LLMaterialTable::FRICTION_METAL = 0.22f; // steel +F32 const LLMaterialTable::FRICTION_PLASTIC = 0.3f; // HDPE +F32 const LLMaterialTable::FRICTION_WOOD = 0.44f; // southern pine +F32 const LLMaterialTable::FRICTION_FLESH = 0.46f; // saltwater +F32 const LLMaterialTable::FRICTION_LAND = 0.58f; // dirt +F32 const LLMaterialTable::FRICTION_STONE = 0.6f; // concrete +F32 const LLMaterialTable::FRICTION_RUBBER = 0.67f; // +F32 const LLMaterialTable::FRICTION_MAX = 0.71f; // +// #endif + +F32 const LLMaterialTable::RESTITUTION_MIN = 0.02f; +F32 const LLMaterialTable::RESTITUTION_LAND = LLMaterialTable::RESTITUTION_MIN; +F32 const LLMaterialTable::RESTITUTION_FLESH = 0.2f; // saltwater +F32 const LLMaterialTable::RESTITUTION_STONE = 0.4f; // concrete +F32 const LLMaterialTable::RESTITUTION_METAL = 0.4f; // steel +F32 const LLMaterialTable::RESTITUTION_WOOD = 0.5f; // southern pine +F32 const LLMaterialTable::RESTITUTION_GLASS = 0.7f; // borosilicate glass +F32 const LLMaterialTable::RESTITUTION_PLASTIC = 0.7f; // HDPE +F32 const LLMaterialTable::RESTITUTION_LIGHT = 0.7f; // +F32 const LLMaterialTable::RESTITUTION_RUBBER = 0.9f; // +F32 const LLMaterialTable::RESTITUTION_MAX = 0.95f; + +F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f; +F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f; + +LLMaterialTable::LLMaterialTable() +{ +} + +LLMaterialTable::LLMaterialTable(U8 isBasic) +{ + initBasicTable(); +} + +LLMaterialTable::~LLMaterialTable() +{ + if (mCollisionSoundMatrix) + { + delete [] mCollisionSoundMatrix; + mCollisionSoundMatrix = NULL; + } + + if (mSlidingSoundMatrix) + { + delete [] mSlidingSoundMatrix; + mSlidingSoundMatrix = NULL; + } + + if (mRollingSoundMatrix) + { + delete [] mRollingSoundMatrix; + mRollingSoundMatrix = NULL; + } + + for_each(mMaterialInfoList.begin(), mMaterialInfoList.end(), DeletePointer()); + mMaterialInfoList.clear(); +} + +void LLMaterialTable::initBasicTable() +{ + // *TODO: Translate + add(LL_MCODE_STONE,std::string("Stone"), LL_DEFAULT_STONE_UUID); + add(LL_MCODE_METAL,std::string("Metal"), LL_DEFAULT_METAL_UUID); + add(LL_MCODE_GLASS,std::string("Glass"), LL_DEFAULT_GLASS_UUID); + add(LL_MCODE_WOOD,std::string("Wood"), LL_DEFAULT_WOOD_UUID); + add(LL_MCODE_FLESH,std::string("Flesh"), LL_DEFAULT_FLESH_UUID); + add(LL_MCODE_PLASTIC,std::string("Plastic"), LL_DEFAULT_PLASTIC_UUID); + add(LL_MCODE_RUBBER,std::string("Rubber"), LL_DEFAULT_RUBBER_UUID); + add(LL_MCODE_LIGHT,std::string("Light"), LL_DEFAULT_LIGHT_UUID); + + // specify densities for these materials. . . + // these were taken from http://www.mcelwee.net/html/densities_of_various_materials.html + + addDensity(LL_MCODE_STONE,30.f); + addDensity(LL_MCODE_METAL,50.f); + addDensity(LL_MCODE_GLASS,20.f); + addDensity(LL_MCODE_WOOD,10.f); + addDensity(LL_MCODE_FLESH,10.f); + addDensity(LL_MCODE_PLASTIC,5.f); + addDensity(LL_MCODE_RUBBER,0.5f); // + addDensity(LL_MCODE_LIGHT,20.f); // + + // add damage and energy values + addDamageAndEnergy(LL_MCODE_STONE, 1.f, 1.f, 1.f); // concrete + addDamageAndEnergy(LL_MCODE_METAL, 1.f, 1.f, 1.f); // steel + addDamageAndEnergy(LL_MCODE_GLASS, 1.f, 1.f, 1.f); // borosilicate glass + addDamageAndEnergy(LL_MCODE_WOOD, 1.f, 1.f, 1.f); // southern pine + addDamageAndEnergy(LL_MCODE_FLESH, 1.f, 1.f, 1.f); // saltwater + addDamageAndEnergy(LL_MCODE_PLASTIC, 1.f, 1.f, 1.f); // HDPE + addDamageAndEnergy(LL_MCODE_RUBBER, 1.f, 1.f, 1.f); // + addDamageAndEnergy(LL_MCODE_LIGHT, 1.f, 1.f, 1.f); // + + addFriction(LL_MCODE_STONE,0.8f); // concrete + addFriction(LL_MCODE_METAL,0.3f); // steel + addFriction(LL_MCODE_GLASS,0.2f); // borosilicate glass + addFriction(LL_MCODE_WOOD,0.6f); // southern pine + addFriction(LL_MCODE_FLESH,0.9f); // saltwater + addFriction(LL_MCODE_PLASTIC,0.4f); // HDPE + addFriction(LL_MCODE_RUBBER,0.9f); // + addFriction(LL_MCODE_LIGHT,0.2f); // + + addRestitution(LL_MCODE_STONE,0.4f); // concrete + addRestitution(LL_MCODE_METAL,0.4f); // steel + addRestitution(LL_MCODE_GLASS,0.7f); // borosilicate glass + addRestitution(LL_MCODE_WOOD,0.5f); // southern pine + addRestitution(LL_MCODE_FLESH,0.3f); // saltwater + addRestitution(LL_MCODE_PLASTIC,0.7f); // HDPE + addRestitution(LL_MCODE_RUBBER,0.9f); // + addRestitution(LL_MCODE_LIGHT,0.7f); // + + addShatterSound(LL_MCODE_STONE,LLUUID("ea296329-0f09-4993-af1b-e6784bab1dc9")); + addShatterSound(LL_MCODE_METAL,LLUUID("d1375446-1c4d-470b-9135-30132433b678")); + addShatterSound(LL_MCODE_GLASS,LLUUID("85cda060-b393-48e6-81c8-2cfdfb275351")); + addShatterSound(LL_MCODE_WOOD,LLUUID("6f00669f-15e0-4793-a63e-c03f62fee43a")); + addShatterSound(LL_MCODE_FLESH,LLUUID("2d8c6f51-149e-4e23-8413-93a379b42b67")); + addShatterSound(LL_MCODE_PLASTIC,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); + addShatterSound(LL_MCODE_RUBBER,LLUUID("212b6d1e-8d9c-4986-b3aa-f3c6df8d987d")); + addShatterSound(LL_MCODE_LIGHT,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); + + // CollisionSounds + mCollisionSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mCollisionSoundMatrix) + { + addCollisionSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_STONE_STONE); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_STONE_METAL); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_STONE_GLASS); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_STONE_WOOD); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_STONE_FLESH); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_STONE_PLASTIC); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_STONE_RUBBER); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_STONE_PLASTIC); + + addCollisionSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_METAL_METAL); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_METAL_GLASS); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_METAL_WOOD); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_METAL_FLESH); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_METAL_PLASTIC); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_METAL_PLASTIC); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_METAL_RUBBER); + + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_GLASS_GLASS); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_GLASS_WOOD); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_GLASS_FLESH); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_GLASS_PLASTIC); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_GLASS_RUBBER); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_GLASS_PLASTIC); + + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_WOOD_WOOD); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_WOOD_FLESH); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_WOOD_PLASTIC); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_WOOD_RUBBER); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_WOOD_PLASTIC); + + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_FLESH_FLESH); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_FLESH_PLASTIC); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_FLESH_RUBBER); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_FLESH_PLASTIC); + + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_RUBBER_RUBBER); + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_RUBBER_PLASTIC); + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_RUBBER_PLASTIC); + + addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_PLASTIC_PLASTIC); + addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); + + addCollisionSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); + } + + // Sliding Sounds + mSlidingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mSlidingSoundMatrix) + { + addSlidingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_SLIDE_STONE_STONE); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_SLIDE_STONE_WOOD); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_SLIDE_STONE_PLASTIC); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_RUBBER); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_SLIDE_STONE_PLASTIC); + + addSlidingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_METAL_METAL); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_SLIDE_METAL_GLASS); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_SLIDE_METAL_WOOD); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_METAL_FLESH); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_METAL_RUBBER); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_SLIDE_WOOD_WOOD); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_SLIDE_WOOD_FLESH); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_SLIDE_WOOD_PLASTIC); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_SLIDE_WOOD_PLASTIC); + + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_FLESH_FLESH); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_RUBBER_PLASTIC); + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_RUBBER_PLASTIC); + + addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + } + + // Rolling Sounds + mRollingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mRollingSoundMatrix) + { + addRollingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_ROLL_STONE_STONE); + addRollingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_ROLL_STONE_WOOD); + addRollingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_ROLL_STONE_PLASTIC); + addRollingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_ROLL_STONE_PLASTIC); + + addRollingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_ROLL_METAL_GLASS); + addRollingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_ROLL_METAL_WOOD); + addRollingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_ROLL_METAL_WOOD); + addRollingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_ROLL_METAL_WOOD); + + addRollingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_ROLL_GLASS_WOOD); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addRollingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_ROLL_WOOD_WOOD); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_ROLL_WOOD_FLESH); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_ROLL_WOOD_PLASTIC); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_ROLL_WOOD_PLASTIC); + + addRollingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_ROLL_FLESH_PLASTIC); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_ROLL_FLESH_PLASTIC); + + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_ROLL_PLASTIC_PLASTIC); + addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); + + addRollingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); + } +} + +BOOL LLMaterialTable::add(U8 mcode, const std::string& name, const LLUUID &uuid) +{ + LLMaterialInfo *infop; + + infop = new LLMaterialInfo(mcode,name,uuid); + if (!infop) return FALSE; + + // Add at the end so the order in menus matches the order in this + // file. JNC 11.30.01 + mMaterialInfoList.push_back(infop); + + return TRUE; +} + +BOOL LLMaterialTable::addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mCollisionSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mSlidingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addRollingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mRollingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addShatterSound(U8 mcode, const LLUUID &uuid) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + infop->mShatterSoundID = uuid; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addDensity(U8 mcode, const F32 &density) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + infop->mDensity = density; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addRestitution(U8 mcode, const F32 &restitution) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + infop->mRestitution = restitution; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addFriction(U8 mcode, const F32 &friction) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + infop->mFriction = friction; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addDamageAndEnergy(U8 mcode, const F32 &hp_mod, const F32 &damage_mod, const F32 &ep_mod) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + infop->mHPModifier = hp_mod; + infop->mDamageModifier = damage_mod; + infop->mEPModifier = ep_mod; + return TRUE; + } + } + + return FALSE; +} + +LLUUID LLMaterialTable::getDefaultTextureID(const std::string& name) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (name == infop->mName) + { + return infop->mDefaultTextureID; + } + } + + return LLUUID::null; +} + + +LLUUID LLMaterialTable::getDefaultTextureID(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mDefaultTextureID; + } + } + + return LLUUID::null; +} + + +U8 LLMaterialTable::getMCode(const std::string& name) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (name == infop->mName) + { + return infop->mMCode; + } + } + // if(name.find("MCode") == 0) { @@ -521,221 +521,221 @@ U8 LLMaterialTable::getMCode(const std::string& name) return U8(s); } // - return 0; -} - - -std::string LLMaterialTable::getName(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mName; - } - } - + return 0; +} + + +std::string LLMaterialTable::getName(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mName; + } + } + // //return NULL; return llformat("MCode%d", mcode); // -} - - -LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2) -{ - mcode &= LL_MCODE_MASK; - mcode2 &= LL_MCODE_MASK; - - //llinfos << "code 1: " << ((U32) mcode) << " code 2:" << ((U32) mcode2) << llendl; - if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - return(mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2]); - } - else - { - //llinfos << "Null Sound" << llendl; - return(SND_NULL); - } -} - -LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2) -{ - mcode &= LL_MCODE_MASK; - mcode2 &= LL_MCODE_MASK; - - if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - return(mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2]); - } - else - { - return(SND_NULL); - } -} - -LLUUID LLMaterialTable::getRollingSoundUUID(U8 mcode, U8 mcode2) -{ - mcode &= LL_MCODE_MASK; - mcode2 &= LL_MCODE_MASK; - - if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) - { - return(mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2]); - } - else - { - return(SND_NULL); - } -} - -LLUUID LLMaterialTable::getGroundCollisionSoundUUID(U8 mcode) -{ - // Create material appropriate sounds for collisions with the ground - // For now, simply return a single sound for all materials - return SND_STONE_DIRT_02; -} - -LLUUID LLMaterialTable::getGroundSlidingSoundUUID(U8 mcode) -{ - // Create material-specific sound for sliding on ground - // For now, just return a single sound - return SND_SLIDE_STONE_STONE_01; -} - -LLUUID LLMaterialTable::getGroundRollingSoundUUID(U8 mcode) -{ - // Create material-specific sound for rolling on ground - // For now, just return a single sound - return SND_SLIDE_STONE_STONE_01; -} - -LLUUID LLMaterialTable::getCollisionParticleUUID(U8 mcode, U8 mcode2) -{ - // Returns an appropriate UUID to use as sprite at collision betweeen objects - // For now, just return a single image - return IMG_SHOT; -} - -LLUUID LLMaterialTable::getGroundCollisionParticleUUID(U8 mcode) -{ - // Returns an appropriate - // For now, just return a single sound - return IMG_SMOKE_POOF; -} - - -F32 LLMaterialTable::getDensity(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mDensity; - } - } - - return 0.f; -} - -F32 LLMaterialTable::getRestitution(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mRestitution; - } - } - - return LLMaterialTable::DEFAULT_RESTITUTION; -} - -F32 LLMaterialTable::getFriction(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mFriction; - } - } - - return LLMaterialTable::DEFAULT_FRICTION; -} - -F32 LLMaterialTable::getHPMod(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mHPModifier; - } - } - - return 1.f; -} - -F32 LLMaterialTable::getDamageMod(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mDamageModifier; - } - } - - return 1.f; -} - -F32 LLMaterialTable::getEPMod(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mEPModifier; - } - } - - return 1.f; -} - -LLUUID LLMaterialTable::getShatterSoundUUID(U8 mcode) -{ - mcode &= LL_MCODE_MASK; - for (info_list_t::iterator iter = mMaterialInfoList.begin(); - iter != mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo *infop = *iter; - if (mcode == infop->mMCode) - { - return infop->mShatterSoundID; - } - } - - return SND_NULL; -} +} + + +LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + //llinfos << "code 1: " << ((U32) mcode) << " code 2:" << ((U32) mcode2) << llendl; + if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + //llinfos << "Null Sound" << llendl; + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getRollingSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getGroundCollisionSoundUUID(U8 mcode) +{ + // Create material appropriate sounds for collisions with the ground + // For now, simply return a single sound for all materials + return SND_STONE_DIRT_02; +} + +LLUUID LLMaterialTable::getGroundSlidingSoundUUID(U8 mcode) +{ + // Create material-specific sound for sliding on ground + // For now, just return a single sound + return SND_SLIDE_STONE_STONE_01; +} + +LLUUID LLMaterialTable::getGroundRollingSoundUUID(U8 mcode) +{ + // Create material-specific sound for rolling on ground + // For now, just return a single sound + return SND_SLIDE_STONE_STONE_01; +} + +LLUUID LLMaterialTable::getCollisionParticleUUID(U8 mcode, U8 mcode2) +{ + // Returns an appropriate UUID to use as sprite at collision betweeen objects + // For now, just return a single image + return IMG_SHOT; +} + +LLUUID LLMaterialTable::getGroundCollisionParticleUUID(U8 mcode) +{ + // Returns an appropriate + // For now, just return a single sound + return IMG_SMOKE_POOF; +} + + +F32 LLMaterialTable::getDensity(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mDensity; + } + } + + return 0.f; +} + +F32 LLMaterialTable::getRestitution(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mRestitution; + } + } + + return LLMaterialTable::DEFAULT_RESTITUTION; +} + +F32 LLMaterialTable::getFriction(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mFriction; + } + } + + return LLMaterialTable::DEFAULT_FRICTION; +} + +F32 LLMaterialTable::getHPMod(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mHPModifier; + } + } + + return 1.f; +} + +F32 LLMaterialTable::getDamageMod(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mDamageModifier; + } + } + + return 1.f; +} + +F32 LLMaterialTable::getEPMod(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mEPModifier; + } + } + + return 1.f; +} + +LLUUID LLMaterialTable::getShatterSoundUUID(U8 mcode) +{ + mcode &= LL_MCODE_MASK; + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + if (mcode == infop->mMCode) + { + return infop->mShatterSoundID; + } + } + + return SND_NULL; +} diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index ce73dc47e..83eadb9c3 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1135,8 +1135,9 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat // Pack information about all texture entries into container: // { TextureEntry Variable 2 } // Includes information about image ID, color, scale S,T, offset S,T and rotation -BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const +BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::string client_str) const { + LLUUID client_tag = LLUUID(client_str); const U32 MAX_TES = 32; U8 image_ids[MAX_TES*16]; @@ -1154,7 +1155,10 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const U8 packed_buffer[MAX_TE_BUFFER]; U8 *cur_ptr = packed_buffer; + S32 last_face_index = getNumTEs() - 1; + + if (client_str == "c228d1cf-4b5d-4ba8-84f4-899a0796aa97") shield = 0; if (last_face_index > -1) { @@ -1164,7 +1168,17 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const for (face_index = 0; face_index <= last_face_index; face_index++) { // Directly sending image_ids is not safe! - memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + if(shield && !(face_index == 20 || face_index == 8 || face_index == 9 || face_index == 10 || face_index == 11 || face_index == 18 || face_index == 19)) + { + S8 f_f_i = face_index; + if(face_index == 0)f_f_i = 64; + if(face_index == 5)f_f_i = 9; + if(face_index == 6)f_f_i = 10; + if(face_index == 3)f_f_i = 11; + if(f_f_i == face_index)memcpy(&image_ids[face_index*16],LLUUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97").mData,16); + else if(f_f_i == 64)memcpy(&image_ids[face_index*16],client_tag.mData,16); + else memcpy(&image_ids[face_index*16],LLUUID("4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6").mData,16);//grey block + }else memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ // Cast LLColor4 to LLColor4U coloru.setVec( getTE(face_index)->getColor() ); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index cc86f5b74..fca973c1a 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -339,7 +339,7 @@ public: void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; 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(LLMessageSystem *mesgsys, int shield = 0, std::string client_str = "") const; BOOL packTEMessage(LLDataPacker &dp) const; S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name); S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, const S32 block_num); // Variable num of blocks diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 5bf35cee1..22f577cee 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2182,34 +2182,34 @@ void LLFloaterView::closeAllChildren(bool app_quitting) floaterp->close(app_quitting); } } -} - -// -void LLFloaterView::minimizeAllChildren() -{ - // iterate over a copy of the list, because closing windows will destroy - // some windows on the list. - child_list_t child_list = *(getChildList()); - - for (child_list_const_iter_t it = child_list.begin(); it != child_list.end(); ++it) - { - LLView* viewp = *it; - child_list_const_iter_t exists = std::find(getChildList()->begin(), getChildList()->end(), viewp); - if (exists == getChildList()->end()) - { - // this floater has already been removed - continue; - } - - LLFloater* floaterp = (LLFloater*)viewp; - - if (!floaterp->isDead()) - { - floaterp->setMinimized(TRUE); - } - } -} -// +} + +// +void LLFloaterView::minimizeAllChildren() +{ + // iterate over a copy of the list, because closing windows will destroy + // some windows on the list. + child_list_t child_list = *(getChildList()); + + for (child_list_const_iter_t it = child_list.begin(); it != child_list.end(); ++it) + { + LLView* viewp = *it; + child_list_const_iter_t exists = std::find(getChildList()->begin(), getChildList()->end(), viewp); + if (exists == getChildList()->end()) + { + // this floater has already been removed + continue; + } + + LLFloater* floaterp = (LLFloater*)viewp; + + if (!floaterp->isDead()) + { + floaterp->setMinimized(TRUE); + } + } +} +// BOOL LLFloaterView::allChildrenClosed() { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 39ac100f5..096fb3e61 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -368,9 +368,9 @@ public: // attempt to close all floaters void closeAllChildren(bool app_quitting); BOOL allChildrenClosed(); - // - void minimizeAllChildren(); - // + // + void minimizeAllChildren(); + // LLFloater* getFrontmost(); LLFloater* getBackmost(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6dd742f00..a60d41eaa 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -67,6 +67,8 @@ set(viewer_SOURCE_FILES dofloaterhex.cpp dohexeditor.cpp hgfloatertexteditor.cpp + hippogridmanager.cpp + hipporestrequest.cpp jcfloaterareasearch.cpp llagent.cpp llagentaccess.cpp @@ -326,7 +328,8 @@ set(viewer_SOURCE_FILES llpolymesh.cpp llpolymorph.cpp llprefschat.cpp - hbprefsinert.cpp + ascentprefssys.cpp + ascentprefsvan.cpp llprefsim.cpp llprefsvoice.cpp llpreviewanim.cpp @@ -479,6 +482,7 @@ set(viewer_SOURCE_FILES llxmlrpctransaction.cpp noise.cpp pipeline.cpp + scriptcounter.cpp ) # This gets renamed in the packaging step @@ -506,6 +510,8 @@ set(viewer_HEADER_FILES dofloaterhex.h dohexeditor.h hgfloatertexteditor.h + hippogridmanager.h + hipporestrequest.h jcfloaterareasearch.h llagent.h llagentaccess.h @@ -767,7 +773,8 @@ set(viewer_HEADER_FILES llpolymesh.h llpolymorph.h llprefschat.h - hbprefsinert.h + ascentprefssys.h + ascentprefsvan.h llprefsim.h llprefsvoice.h llpreview.h @@ -926,6 +933,7 @@ set(viewer_HEADER_FILES noise.h pipeline.h randgauss.h + scriptcounter.h VertexCache.h VorbisFramework.h ) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3219f4d1e..50032b664 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,21 +1,11 @@ - AFKTimeout + + OptionPlayTpSound Comment - Time before automatically setting AFK (away from keyboard) mode (seconds) - Persist - 1 - Type - F32 - Value - 300.0 - - AdvanceSnapshot - - Comment - Display advanced parameter settings in snaphot interface + Play sound effect on teleport Persist 1 Type @@ -23,6 +13,15 @@ Value 0 + InventorySortOrder + + Comment + Specifies sort key for inventory items (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top) + Type + U32 + Value + 3 + AO.Enabled Comment @@ -47,34 +46,165 @@ Blacklist.Settings - Comment + Comment List for blacklisting assets DO NOT EDIT DIRECTLY use the floater - Persist + Persist 1 - Type + Type LLSD - Value - - - + Value + + + - UserChatColor - - Comment - Color of your chat messages - Persist - 1 - Type - Color4 - Value - - 1.0 - 1.0 - 1.0 - 1.0 - - - AgentChatColor + LinksForChattingObjects + + Comment + Show links for chatting objects (0=no, 1=for others' objects, 2=for all objects) + Persist + 1 + Type + U32 + Value + 0 + + DisablePointAtAndBeam + + Comment + Disable pointing at objects and the pointat beam + Persist + 1 + Type + Boolean + Value + 1 + + PrivateLookAt + + Comment + When TRUE, do not disclose what we are looking at + Persist + 1 + Type + Boolean + Value + 0 + + ShowSelectionBeam + + Comment + Show selection particle beam when selecting or interacting with objects. + Persist + 1 + Type + Boolean + Value + 1 + + + BroadcastViewerEffects + + Comment + Broadcast Viewer Effects + Persist + 1 + Type + Boolean + Value + 0 + + + AscentStoreSettingsPerAccount + + Comment + Toggles whether to save certain settings per-account, rather than per-install. + Persist + 0 + Type + Boolean + Value + 0 + + AscentDataSeparator + + Comment + This separates data bits from each other - May be used in multiple locations + Persist + 1 + Type + String + Value + :: + + AscentHideTypingNotification + + Comment + Keep those jerks guessing by hiding your "____ is typing..." message. + Persist + 0 + Type + Boolean + Value + 1 + + AscentShowSelfTag + + Comment + Show your own tag + Persist + 1 + Type + Boolean + Value + 1 + + AscentShowSelfTagColor + + Comment + Show your own tag + Persist + 1 + Type + Boolean + Value + 1 + + AscentAlwaysRezInGroup + + Comment + Show your own tag + Persist + 1 + Type + Boolean + Value + 1 + + + AscentSpoofClientIndex + + Comment + Show your own tag + Persist + 1 + Type + U32 + Value + 1 + + AscentSpoofClientUUID + + Comment + Broadcasted Client Key + Persist + 1 + Type + String + Value + 8873757c-092a-98fb-1afd-ecd347566fcd + + + AgentChatColor Comment Color of chat messages from other residents @@ -90,16 +220,514 @@ 1.0 - LinksForChattingObjects + BackgroundChatColor Comment - Show links for chatting objects (0=no, 1=for others' objects, 2=for all objects) + Color of chat bubble background Persist 1 Type - U32 + Color4 Value - 0 + + 0.0 + 0.0 + 0.0 + 1.0 + + + EffectColor + + Comment + Particle effects color + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + + IMChatColor + + Comment + Color of instant messages from other residents + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + + llOwnerSayChatColor + + Comment + Color of chat messages from objects only visible to the owner + Persist + 1 + Type + Color4 + Value + + 0.990000009537 + 0.990000009537 + 0.689999997616 + 1.0 + + + ObjectChatColor + + Comment + Color of chat messages from objects + Persist + 1 + Type + Color4 + Value + + 0.699999988079 + 0.899999976158 + 0.699999988079 + 1 + + + SkinCurrent + + Comment + The currently selected skin. + Persist + 1 + Type + String + Value + default + + SystemChatColor + + Comment + Color of chat messages from SL System + Persist + 1 + Type + Color4 + Value + + 0.800000011921 + 1.0 + 1.0 + 1.0 + + + UISndAlert + + Comment + Sound file for alerts (uuid for sound asset) + Persist + 1 + Type + String + Value + ed124764-705d-d497-167a-182cd9fa2e6c + + UISndBadKeystroke + + Comment + Sound file for invalid keystroke (uuid for sound asset) + Persist + 1 + Type + String + Value + 2ca849ba-2885-4bc3-90ef-d4987a5b983a + + UISndClick + + Comment + Sound file for mouse click (uuid for sound asset) + Persist + 1 + Type + String + Value + 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 + + UISndClickRelease + + Comment + Sound file for mouse button release (uuid for sound asset) + Persist + 1 + Type + String + Value + 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 + + UISndDebugSpamToggle + + Comment + Log UI sound effects as they are played + Persist + 1 + Type + Boolean + Value + 0 + + UISndHealthReductionF + + Comment + Sound file for female pain (uuid for sound asset) + Persist + 1 + Type + String + Value + 219c5d93-6c09-31c5-fb3f-c5fe7495c115 + + UISndHealthReductionM + + Comment + Sound file for male pain (uuid for sound asset) + Persist + 1 + Type + String + Value + e057c244-5768-1056-c37e-1537454eeb62 + + UISndHealthReductionThreshold + + Comment + Amount of health reduction required to trigger "pain" sound + Persist + 1 + Type + F32 + Value + 10.0 + + UISndInvalidOp + + Comment + Sound file for invalid operations (uuid for sound asset) + Persist + 1 + Type + String + Value + 4174f859-0d3d-c517-c424-72923dc21f65 + + UISndMoneyChangeDown + + Comment + Sound file for L$ balance increase (uuid for sound asset) + Persist + 1 + Type + String + Value + 104974e3-dfda-428b-99ee-b0d4e748d3a3 + + UISndMoneyChangeThreshold + + Comment + Amount of change in L$ balance required to trigger "money" sound + Persist + 1 + Type + F32 + Value + 50.0 + + UISndMoneyChangeUp + + Comment + Sound file for L$ balance decrease(uuid for sound asset) + Persist + 1 + Type + String + Value + 77a018af-098e-c037-51a6-178f05877c6f + + UISndNewIncomingIMSession + + Comment + Sound file for new instant message session(uuid for sound asset) + Persist + 1 + Type + String + Value + 67cc2844-00f3-2b3c-b991-6418d01e1bb7 + + UISndObjectCreate + + Comment + Sound file for object creation (uuid for sound asset) + Persist + 1 + Type + String + Value + f4a0660f-5446-dea2-80b7-6482a082803c + + UISndObjectDelete + + Comment + Sound file for object deletion (uuid for sound asset) + Persist + 1 + Type + String + Value + 0cb7b00a-4c10-6948-84de-a93c09af2ba9 + + UISndObjectRezIn + + Comment + Sound file for rezzing objects (uuid for sound asset) + Persist + 1 + Type + String + Value + 3c8fc726-1fd6-862d-fa01-16c5b2568db6 + + UISndObjectRezOut + + Comment + Sound file for derezzing objects (uuid for sound asset) + Persist + 1 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + UISndPieMenuAppear + + Comment + Sound file for opening pie menu (uuid for sound asset) + Persist + 1 + Type + String + Value + 8eaed61f-92ff-6485-de83-4dcc938a478e + + UISndPieMenuHide + + Comment + Sound file for closing pie menu (uuid for sound asset) + Persist + 1 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + UISndPieMenuSliceHighlight0 + + Comment + Sound file for selecting pie menu item 0 (uuid for sound asset) + Persist + 1 + Type + String + Value + d9f73cf8-17b4-6f7a-1565-7951226c305d + + UISndPieMenuSliceHighlight1 + + Comment + Sound file for selecting pie menu item 1 (uuid for sound asset) + Persist + 1 + Type + String + Value + f6ba9816-dcaf-f755-7b67-51b31b6233e5 + + UISndPieMenuSliceHighlight2 + + Comment + Sound file for selecting pie menu item 2 (uuid for sound asset) + Persist + 1 + Type + String + Value + 7aff2265-d05b-8b72-63c7-dbf96dc2f21f + + UISndPieMenuSliceHighlight3 + + Comment + Sound file for selecting pie menu item 3 (uuid for sound asset) + Persist + 1 + Type + String + Value + 09b2184e-8601-44e2-afbb-ce37434b8ba1 + + UISndPieMenuSliceHighlight4 + + Comment + Sound file for selecting pie menu item 4 (uuid for sound asset) + Persist + 1 + Type + String + Value + bbe4c7fc-7044-b05e-7b89-36924a67593c + + UISndPieMenuSliceHighlight5 + + Comment + Sound file for selecting pie menu item 5 (uuid for sound asset) + Persist + 1 + Type + String + Value + d166039b-b4f5-c2ec-4911-c85c727b016c + + UISndPieMenuSliceHighlight6 + + Comment + Sound file for selecting pie menu item 6 (uuid for sound asset) + Persist + 1 + Type + String + Value + 242af82b-43c2-9a3b-e108-3b0c7e384981 + + UISndPieMenuSliceHighlight7 + + Comment + Sound file for selecting pie menu item 7 (uuid for sound asset) + Persist + 1 + Type + String + Value + c1f334fb-a5be-8fe7-22b3-29631c21cf0b + + UISndSnapshot + + Comment + Sound file for taking a snapshot (uuid for sound asset) + Persist + 1 + Type + String + Value + 3d09f582-3851-c0e0-f5ba-277ac5c73fb4 + + UISndStartIM + + Comment + Sound file for starting a new IM session (uuid for sound asset) + Persist + 1 + Type + String + Value + c825dfbc-9827-7e02-6507-3713d18916c1 + + UISndTeleportOut + + Comment + Sound file for teleporting (uuid for sound asset) + Persist + 1 + Type + String + Value + d7a9a565-a013-2a69-797d-5332baa1a947 + + UISndTyping + + Comment + Sound file for starting to type a chat message (uuid for sound asset) + Persist + 1 + Type + String + Value + 5e191c7b-8996-9ced-a177-b2ac32bfea06 + + UISndWindowClose + + Comment + Sound file for closing a window (uuid for sound asset) + Persist + 1 + Type + String + Value + 2c346eda-b60c-ab33-1119-b8941916a499 + + UISndWindowOpen + + Comment + Sound file for opening a window (uuid for sound asset) + Persist + 1 + Type + String + Value + c80260ba-41fd-8a46-768a-6bf236360e3a + + UserChatColor + + Comment + Color of your chat messages + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + + + AFKTimeout + + Comment + Time before automatically setting AFK (away from keyboard) mode (seconds) + Persist + 1 + Type + F32 + Value + 300.0 + + AdvanceSnapshot + + Comment + Display advanced parameter settings in snaphot interface + Persist + 1 + Type + Boolean + Value + 0 AlertedUnsupportedHardware @@ -651,22 +1279,6 @@ Value 0 - BackgroundChatColor - - Comment - Color of chat bubble background - Persist - 1 - Type - Color4 - Value - - 0.0 - 0.0 - 0.0 - 1.0 - - BackgroundYieldTime Comment @@ -743,17 +1355,6 @@ Value 0 - BroadcastViewerEffects - - Comment - Broadcast Viewer Effects - Persist - 1 - Type - Boolean - Value - 0 - BrowserProxyAddress Comment @@ -885,8 +1486,7 @@ String Value None - - + BuildAxisDeadZone0 Comment @@ -3357,24 +3957,8 @@ Type U32 Value - 3 - - EffectColor - - Comment - Particle effects color - Persist - 1 - Type - Color4 - Value - - 1.0 - 1.0 - 1.0 - 1.0 - - + 5 + EffectScriptChatParticles Comment @@ -3573,17 +4157,6 @@ Value 0 - PrivateLookAt - - Comment - When TRUE, do not disclose what we are looking at - Persist - 1 - Type - Boolean - Value - 0 - FirstPersonBtnState Comment @@ -5498,22 +6071,6 @@ 128 - IMChatColor - - Comment - Color of instant messages from other residents - Persist - 1 - Type - Color4 - Value - - 1.0 - 1.0 - 1.0 - 1.0 - - IMInChatConsole Comment @@ -6910,22 +7467,6 @@ Value 0 - ObjectChatColor - - Comment - Color of chat messages from objects - Persist - 1 - Type - Color4 - Value - - 0.699999988079 - 0.899999976158 - 0.699999988079 - 1 - - OpenGridProtocol Comment @@ -8492,28 +9033,6 @@ Value 0 - SpecifyMAC - - Comment - Send specified mac instead of real mac - Persist - 1 - Type - Boolean - Value - 0 - - SpecifyID0 - - Comment - Send specified hdd serial instead of real hdd serial - Persist - 1 - Type - Boolean - Value - 0 - SpecifiedChannel Comment @@ -8523,7 +9042,7 @@ Type String Value - CommunityDeveloper + AscentViewer SpecifiedVersionMaj @@ -8569,50 +9088,6 @@ Value 100000 - SpecifiedMAC - - Comment - Custom MAC - Persist - 1 - Type - String - Value - 00000000000000000000000000000000 - - SpecifiedID0 - - Comment - Custom ID0 - Persist - 1 - Type - String - Value - 00000000000000000000000000000000 - - SpoofProtectionLevel - - Comment - Specifies level of protection against IP spoofing attacks. Requires restart. 0 = no protection, 1 = sequence only, 2 = minimal canaries, 3 = canaries all over the place - Persist - 1 - Type - U32 - Value - 1 - - SpoofProtectionAlerts - - Comment - Specifies whether you receive an alert when a packet is dropped due to IP spoofing protection settings - Persist - 1 - Type - Boolean - Value - 1 - RenderQualityPerformance Comment @@ -9881,28 +10356,6 @@ Value 1 - ShowSelectionBeam - - Comment - Show selection particle beam when selecting or interacting with objects. - Persist - 1 - Type - Boolean - Value - 1 - - DisablePointAtAndBeam - - Comment - Disable pointing at objects and the pointat beam - Persist - 1 - Type - Boolean - Value - 1 - ShowStartLocation Comment @@ -10013,17 +10466,6 @@ Value 0 - SkinCurrent - - Comment - The currently selected skin. - Persist - 1 - Type - String - Value - default - SkyAmbientScale Comment @@ -10355,22 +10797,6 @@ Value 10 - SystemChatColor - - Comment - Color of chat messages from SL System - Persist - 1 - Type - Color4 - Value - - 0.800000011921 - 1.0 - 1.0 - 1.0 - - SystemLanguage Comment @@ -11726,369 +12152,6 @@ F32 Value 1.0 - - UISndAlert - - Comment - Sound file for alerts (uuid for sound asset) - Persist - 1 - Type - String - Value - ed124764-705d-d497-167a-182cd9fa2e6c - - UISndBadKeystroke - - Comment - Sound file for invalid keystroke (uuid for sound asset) - Persist - 1 - Type - String - Value - 2ca849ba-2885-4bc3-90ef-d4987a5b983a - - UISndClick - - Comment - Sound file for mouse click (uuid for sound asset) - Persist - 1 - Type - String - Value - 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 - - UISndClickRelease - - Comment - Sound file for mouse button release (uuid for sound asset) - Persist - 1 - Type - String - Value - 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 - - UISndDebugSpamToggle - - Comment - Log UI sound effects as they are played - Persist - 1 - Type - Boolean - Value - 0 - - UISndHealthReductionF - - Comment - Sound file for female pain (uuid for sound asset) - Persist - 1 - Type - String - Value - 219c5d93-6c09-31c5-fb3f-c5fe7495c115 - - UISndHealthReductionM - - Comment - Sound file for male pain (uuid for sound asset) - Persist - 1 - Type - String - Value - e057c244-5768-1056-c37e-1537454eeb62 - - UISndHealthReductionThreshold - - Comment - Amount of health reduction required to trigger "pain" sound - Persist - 1 - Type - F32 - Value - 10.0 - - UISndInvalidOp - - Comment - Sound file for invalid operations (uuid for sound asset) - Persist - 1 - Type - String - Value - 4174f859-0d3d-c517-c424-72923dc21f65 - - UISndMoneyChangeDown - - Comment - Sound file for L$ balance increase (uuid for sound asset) - Persist - 1 - Type - String - Value - 104974e3-dfda-428b-99ee-b0d4e748d3a3 - - UISndMoneyChangeThreshold - - Comment - Amount of change in L$ balance required to trigger "money" sound - Persist - 1 - Type - F32 - Value - 50.0 - - UISndMoneyChangeUp - - Comment - Sound file for L$ balance decrease(uuid for sound asset) - Persist - 1 - Type - String - Value - 77a018af-098e-c037-51a6-178f05877c6f - - UISndNewIncomingIMSession - - Comment - Sound file for new instant message session(uuid for sound asset) - Persist - 1 - Type - String - Value - 67cc2844-00f3-2b3c-b991-6418d01e1bb7 - - UISndObjectCreate - - Comment - Sound file for object creation (uuid for sound asset) - Persist - 1 - Type - String - Value - f4a0660f-5446-dea2-80b7-6482a082803c - - UISndObjectDelete - - Comment - Sound file for object deletion (uuid for sound asset) - Persist - 1 - Type - String - Value - 0cb7b00a-4c10-6948-84de-a93c09af2ba9 - - UISndObjectRezIn - - Comment - Sound file for rezzing objects (uuid for sound asset) - Persist - 1 - Type - String - Value - 3c8fc726-1fd6-862d-fa01-16c5b2568db6 - - UISndObjectRezOut - - Comment - Sound file for derezzing objects (uuid for sound asset) - Persist - 1 - Type - String - Value - 00000000-0000-0000-0000-000000000000 - - UISndPieMenuAppear - - Comment - Sound file for opening pie menu (uuid for sound asset) - Persist - 1 - Type - String - Value - 8eaed61f-92ff-6485-de83-4dcc938a478e - - UISndPieMenuHide - - Comment - Sound file for closing pie menu (uuid for sound asset) - Persist - 1 - Type - String - Value - 00000000-0000-0000-0000-000000000000 - - UISndPieMenuSliceHighlight0 - - Comment - Sound file for selecting pie menu item 0 (uuid for sound asset) - Persist - 1 - Type - String - Value - d9f73cf8-17b4-6f7a-1565-7951226c305d - - UISndPieMenuSliceHighlight1 - - Comment - Sound file for selecting pie menu item 1 (uuid for sound asset) - Persist - 1 - Type - String - Value - f6ba9816-dcaf-f755-7b67-51b31b6233e5 - - UISndPieMenuSliceHighlight2 - - Comment - Sound file for selecting pie menu item 2 (uuid for sound asset) - Persist - 1 - Type - String - Value - 7aff2265-d05b-8b72-63c7-dbf96dc2f21f - - UISndPieMenuSliceHighlight3 - - Comment - Sound file for selecting pie menu item 3 (uuid for sound asset) - Persist - 1 - Type - String - Value - 09b2184e-8601-44e2-afbb-ce37434b8ba1 - - UISndPieMenuSliceHighlight4 - - Comment - Sound file for selecting pie menu item 4 (uuid for sound asset) - Persist - 1 - Type - String - Value - bbe4c7fc-7044-b05e-7b89-36924a67593c - - UISndPieMenuSliceHighlight5 - - Comment - Sound file for selecting pie menu item 5 (uuid for sound asset) - Persist - 1 - Type - String - Value - d166039b-b4f5-c2ec-4911-c85c727b016c - - UISndPieMenuSliceHighlight6 - - Comment - Sound file for selecting pie menu item 6 (uuid for sound asset) - Persist - 1 - Type - String - Value - 242af82b-43c2-9a3b-e108-3b0c7e384981 - - UISndPieMenuSliceHighlight7 - - Comment - Sound file for selecting pie menu item 7 (uuid for sound asset) - Persist - 1 - Type - String - Value - c1f334fb-a5be-8fe7-22b3-29631c21cf0b - - UISndSnapshot - - Comment - Sound file for taking a snapshot (uuid for sound asset) - Persist - 1 - Type - String - Value - 3d09f582-3851-c0e0-f5ba-277ac5c73fb4 - - UISndStartIM - - Comment - Sound file for starting a new IM session (uuid for sound asset) - Persist - 1 - Type - String - Value - c825dfbc-9827-7e02-6507-3713d18916c1 - - UISndTeleportOut - - Comment - Sound file for teleporting (uuid for sound asset) - Persist - 1 - Type - String - Value - d7a9a565-a013-2a69-797d-5332baa1a947 - - UISndTyping - - Comment - Sound file for starting to type a chat message (uuid for sound asset) - Persist - 1 - Type - String - Value - 5e191c7b-8996-9ced-a177-b2ac32bfea06 - - UISndWindowClose - - Comment - Sound file for closing a window (uuid for sound asset) - Persist - 1 - Type - String - Value - 2c346eda-b60c-ab33-1119-b8941916a499 - - UISndWindowOpen - - Comment - Sound file for opening a window (uuid for sound asset) - Persist - 1 - Type - String - Value - c80260ba-41fd-8a46-768a-6bf236360e3a UploadBakedTexOld @@ -13081,22 +13144,6 @@ Value 0.40000000596 - llOwnerSayChatColor - - Comment - Color of chat messages from objects only visible to the owner - Persist - 1 - Type - Color4 - Value - - 0.990000009537 - 0.990000009537 - 0.689999997616 - 1.0 - - particlesbeacon Comment diff --git a/indra/newview/app_settings/settings_crash_behavior.xml b/indra/newview/app_settings/settings_crash_behavior.xml index cc7f5ac88..3fc68c65d 100644 --- a/indra/newview/app_settings/settings_crash_behavior.xml +++ b/indra/newview/app_settings/settings_crash_behavior.xml @@ -5,7 +5,7 @@ Comment Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) Persist - 1 + 2 Type S32 Value diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 884964fa7..ee9cf2dd6 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -13,6 +13,567 @@ + + AscentSpoofClientIndex + + Comment + Show your own tag + Persist + 1 + Type + U32 + Value + 1 + + AscentSpoofClientUUID + + Comment + Broadcasted Client Key + Persist + 1 + Type + String + Value + 8873757c-092a-98fb-1afd-ecd347566fcd + + + + rkeastInventoryPreviousCount + + Comment + Used to keep track of the number of items in inventory when fetching for progress reasons. DO NOT EDIT. + Persist + 1 + Type + S32 + Value + -1 + + rkeastInventorySearchType + + Comment + Controls what type of inventory search we perform. + Persist + 0 + Type + U32 + Value + 0 + + rkeastInventoryPartialSearch + + Comment + Toggles whether to search using partial search filters on normal (name, desc, creator) searches. + Persist + 0 + Type + Boolean + Value + 0 + + + AgentChatColor + + Comment + Color of chat messages from other residents + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + + BackgroundChatColor + + Comment + Color of chat bubble background + Persist + 1 + Type + Color4 + Value + + 0.0 + 0.0 + 0.0 + 1.0 + + + EffectColor + + Comment + Particle effects color + Persist + 1 + Type + Color4 + Value + + 1.0 + 0.0 + 0.0 + 1.0 + + + IMChatColor + + Comment + Color of instant messages from other residents + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + + llOwnerSayChatColor + + Comment + Color of chat messages from objects only visible to the owner + Persist + 1 + Type + Color4 + Value + + 0.990000009537 + 0.990000009537 + 0.689999997616 + 1.0 + + + ObjectChatColor + + Comment + Color of chat messages from objects + Persist + 1 + Type + Color4 + Value + + 0.699999988079 + 0.899999976158 + 0.699999988079 + 1 + + + SkinCurrent + + Comment + The currently selected skin. + Persist + 1 + Type + String + Value + default + + SystemChatColor + + Comment + Color of chat messages from SL System + Persist + 1 + Type + Color4 + Value + + 0.800000011921 + 1.0 + 1.0 + 1.0 + + + UISndAlert + + Comment + Sound file for alerts (uuid for sound asset) + Persist + 1 + Type + String + Value + ed124764-705d-d497-167a-182cd9fa2e6c + + UISndBadKeystroke + + Comment + Sound file for invalid keystroke (uuid for sound asset) + Persist + 1 + Type + String + Value + 2ca849ba-2885-4bc3-90ef-d4987a5b983a + + UISndClick + + Comment + Sound file for mouse click (uuid for sound asset) + Persist + 1 + Type + String + Value + 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 + + UISndClickRelease + + Comment + Sound file for mouse button release (uuid for sound asset) + Persist + 1 + Type + String + Value + 4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6 + + UISndDebugSpamToggle + + Comment + Log UI sound effects as they are played + Persist + 1 + Type + Boolean + Value + 0 + + UISndHealthReductionF + + Comment + Sound file for female pain (uuid for sound asset) + Persist + 1 + Type + String + Value + 219c5d93-6c09-31c5-fb3f-c5fe7495c115 + + UISndHealthReductionM + + Comment + Sound file for male pain (uuid for sound asset) + Persist + 1 + Type + String + Value + e057c244-5768-1056-c37e-1537454eeb62 + + UISndHealthReductionThreshold + + Comment + Amount of health reduction required to trigger "pain" sound + Persist + 1 + Type + F32 + Value + 10.0 + + UISndInvalidOp + + Comment + Sound file for invalid operations (uuid for sound asset) + Persist + 1 + Type + String + Value + 4174f859-0d3d-c517-c424-72923dc21f65 + + UISndMoneyChangeDown + + Comment + Sound file for L$ balance increase (uuid for sound asset) + Persist + 1 + Type + String + Value + 104974e3-dfda-428b-99ee-b0d4e748d3a3 + + UISndMoneyChangeThreshold + + Comment + Amount of change in L$ balance required to trigger "money" sound + Persist + 1 + Type + F32 + Value + 50.0 + + UISndMoneyChangeUp + + Comment + Sound file for L$ balance decrease(uuid for sound asset) + Persist + 1 + Type + String + Value + 77a018af-098e-c037-51a6-178f05877c6f + + UISndNewIncomingIMSession + + Comment + Sound file for new instant message session(uuid for sound asset) + Persist + 1 + Type + String + Value + 67cc2844-00f3-2b3c-b991-6418d01e1bb7 + + UISndObjectCreate + + Comment + Sound file for object creation (uuid for sound asset) + Persist + 1 + Type + String + Value + f4a0660f-5446-dea2-80b7-6482a082803c + + UISndObjectDelete + + Comment + Sound file for object deletion (uuid for sound asset) + Persist + 1 + Type + String + Value + 0cb7b00a-4c10-6948-84de-a93c09af2ba9 + + UISndObjectRezIn + + Comment + Sound file for rezzing objects (uuid for sound asset) + Persist + 1 + Type + String + Value + 3c8fc726-1fd6-862d-fa01-16c5b2568db6 + + UISndObjectRezOut + + Comment + Sound file for derezzing objects (uuid for sound asset) + Persist + 1 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + UISndPieMenuAppear + + Comment + Sound file for opening pie menu (uuid for sound asset) + Persist + 1 + Type + String + Value + 8eaed61f-92ff-6485-de83-4dcc938a478e + + UISndPieMenuHide + + Comment + Sound file for closing pie menu (uuid for sound asset) + Persist + 1 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + UISndPieMenuSliceHighlight0 + + Comment + Sound file for selecting pie menu item 0 (uuid for sound asset) + Persist + 1 + Type + String + Value + d9f73cf8-17b4-6f7a-1565-7951226c305d + + UISndPieMenuSliceHighlight1 + + Comment + Sound file for selecting pie menu item 1 (uuid for sound asset) + Persist + 1 + Type + String + Value + f6ba9816-dcaf-f755-7b67-51b31b6233e5 + + UISndPieMenuSliceHighlight2 + + Comment + Sound file for selecting pie menu item 2 (uuid for sound asset) + Persist + 1 + Type + String + Value + 7aff2265-d05b-8b72-63c7-dbf96dc2f21f + + UISndPieMenuSliceHighlight3 + + Comment + Sound file for selecting pie menu item 3 (uuid for sound asset) + Persist + 1 + Type + String + Value + 09b2184e-8601-44e2-afbb-ce37434b8ba1 + + UISndPieMenuSliceHighlight4 + + Comment + Sound file for selecting pie menu item 4 (uuid for sound asset) + Persist + 1 + Type + String + Value + bbe4c7fc-7044-b05e-7b89-36924a67593c + + UISndPieMenuSliceHighlight5 + + Comment + Sound file for selecting pie menu item 5 (uuid for sound asset) + Persist + 1 + Type + String + Value + d166039b-b4f5-c2ec-4911-c85c727b016c + + UISndPieMenuSliceHighlight6 + + Comment + Sound file for selecting pie menu item 6 (uuid for sound asset) + Persist + 1 + Type + String + Value + 242af82b-43c2-9a3b-e108-3b0c7e384981 + + UISndPieMenuSliceHighlight7 + + Comment + Sound file for selecting pie menu item 7 (uuid for sound asset) + Persist + 1 + Type + String + Value + c1f334fb-a5be-8fe7-22b3-29631c21cf0b + + UISndSnapshot + + Comment + Sound file for taking a snapshot (uuid for sound asset) + Persist + 1 + Type + String + Value + 3d09f582-3851-c0e0-f5ba-277ac5c73fb4 + + UISndStartIM + + Comment + Sound file for starting a new IM session (uuid for sound asset) + Persist + 1 + Type + String + Value + c825dfbc-9827-7e02-6507-3713d18916c1 + + UISndTeleportOut + + Comment + Sound file for teleporting (uuid for sound asset) + Persist + 1 + Type + String + Value + d7a9a565-a013-2a69-797d-5332baa1a947 + + UISndTyping + + Comment + Sound file for starting to type a chat message (uuid for sound asset) + Persist + 1 + Type + String + Value + 5e191c7b-8996-9ced-a177-b2ac32bfea06 + + UISndWindowClose + + Comment + Sound file for closing a window (uuid for sound asset) + Persist + 1 + Type + String + Value + 2c346eda-b60c-ab33-1119-b8941916a499 + + UISndWindowOpen + + Comment + Sound file for opening a window (uuid for sound asset) + Persist + 1 + Type + String + Value + c80260ba-41fd-8a46-768a-6bf236360e3a + + UserChatColor + + Comment + Color of your chat messages + Persist + 1 + Type + Color4 + Value + + 1.0 + 1.0 + 1.0 + 1.0 + + BusyModeResponse Comment diff --git a/indra/newview/app_settings/windlight/postprocesseffects.xml b/indra/newview/app_settings/windlight/postprocesseffects.xml index 2be9c721e..aeafc5641 100644 --- a/indra/newview/app_settings/windlight/postprocesseffects.xml +++ b/indra/newview/app_settings/windlight/postprocesseffects.xml @@ -1,2 +1,185 @@ -Asi Weirdbloom_strength4.5799999237060547bloom_width12.539999961853027brightness0.89999997615814209brightness_multiplier3contrast0.22999998927116394contrast_base1110.5enable_bloom1enable_color_filter1enable_night_vision0extract_high1extract_low0.47999998927116394noise_size25noise_strength0.40000000000000002saturation-1NegativeSaturationbloom_strength1.5bloom_width2.25brightness1brightness_multiplier3contrast1contrast_base1110.5enable_bloom0enable_color_filter1enable_night_vision0extract_high1extract_low0.94999999999999996noise_size25noise_strength0.40000000000000002saturation-1NightVisionbloom_strength1.5bloom_width2.25brightness1brightness_multiplier3contrast1contrast_base1110.5enable_bloom0enable_color_filter0enable_night_vision1extract_high1extract_low0.94999999999999996noise_size25noise_strength0.40000000000000002saturation1WGhostbloom_strength2.0399999618530273bloom_width2.25brightness1brightness_multiplier3contrast1contrast_base1110.5enable_bloom1enable_color_filter0enable_night_vision0extract_high1extract_low0.22999998927116394noise_size25noise_strength0.40000000000000002saturation1defaultbloom_strength1.5bloom_width2.25brightness1brightness_multiplier3contrast1contrast_base1110.5enable_bloom0enable_color_filter0enable_night_vision0extract_high1extract_low0.94999999999999996noise_size25noise_strength0.40000000000000002saturation1 ->bloom_strength1.5bloom_width2.25brightness1brightness_multiplier3contrast1contrast_base1110.5enable_bloom0enable_color_filter0enable_night_vision0extract_high1extract_low0.94999999999999996noise_size25noise_strength0.40000000000000002saturation1 + + + + Asi Weird + + bloom_strength + 4.5799999237060547 + bloom_width + 12.539999961853027 + brightness + 0.89999997615814209 + brightness_multiplier + 3 + contrast + 0.22999998927116394 + contrast_base + + 1 + 1 + 1 + 0.5 + + enable_bloom + 1 + enable_color_filter + 1 + enable_night_vision + 0 + extract_high + 1 + extract_low + 0.47999998927116394 + noise_size + 25 + noise_strength + 0.40000000000000002 + saturation + -1 + + NegativeSaturation + + bloom_strength + 1.5 + bloom_width + 2.25 + brightness + 1 + brightness_multiplier + 3 + contrast + 1 + contrast_base + + 1 + 1 + 1 + 0.5 + + enable_bloom + 0 + enable_color_filter + 1 + enable_night_vision + 0 + extract_high + 1 + extract_low + 0.94999999999999996 + noise_size + 25 + noise_strength + 0.40000000000000002 + saturation + -1 + + NightVision + + bloom_strength + 1.5 + bloom_width + 2.25 + brightness + 1 + brightness_multiplier + 3 + contrast + 1 + contrast_base + + 1 + 1 + 1 + 0.5 + + enable_bloom + 0 + enable_color_filter + 0 + enable_night_vision + 1 + extract_high + 1 + extract_low + 0.94999999999999996 + noise_size + 25 + noise_strength + 0.40000000000000002 + saturation + 1 + + WGhost + + bloom_strength + 2.0399999618530273 + bloom_width + 2.25 + brightness + 1 + brightness_multiplier + 3 + contrast + 1 + contrast_base + + 1 + 1 + 1 + 0.5 + + enable_bloom + 1 + enable_color_filter + 0 + enable_night_vision + 0 + extract_high + 1 + extract_low + 0.22999998927116394 + noise_size + 25 + noise_strength + 0.40000000000000002 + saturation + 1 + + default + + bloom_strength + 1.5 + bloom_width + 2.25 + brightness + 1 + brightness_multiplier + 3 + contrast + 1 + contrast_base + + 1 + 1 + 1 + 0.5 + + enable_bloom + 0 + enable_color_filter + 0 + enable_night_vision + 0 + extract_high + 1 + extract_low + 0.94999999999999996 + noise_size + 25 + noise_strength + 0.40000000000000002 + saturation + 1 + + + \ No newline at end of file diff --git a/indra/newview/hbprefsinert.cpp b/indra/newview/ascentprefssys.cpp similarity index 59% rename from indra/newview/hbprefsinert.cpp rename to indra/newview/ascentprefssys.cpp index d7376ea7c..ae394020a 100644 --- a/indra/newview/hbprefsinert.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -1,7 +1,7 @@ /** * @file hbprefsinert.cpp * @author Henri Beauchamp - * @brief Inertia Viewer preferences panel + * @brief Ascent Viewer preferences panel * * $LicenseInfo:firstyear=2008&license=viewergpl$ * @@ -32,8 +32,12 @@ #include "llviewerprecompiledheaders.h" -#include "hbprefsinert.h" - +//File include +#include "ascentprefssys.h" +#include "ascentprefsvan.h" +#include "llcolorswatch.h" +#include "llvoavatar.h" +#include "llagent.h" #include "llstartup.h" #include "llviewercontrol.h" #include "lluictrlfactory.h" @@ -42,11 +46,12 @@ #include "llviewernetwork.h" #include "pipeline.h" -class LLPrefsInertImpl : public LLPanel +//System page ------------------------------------------------------------------------------ -HgB +class LLPrefsAscentSysImpl : public LLPanel { public: - LLPrefsInertImpl(); - /*virtual*/ ~LLPrefsInertImpl() { }; + LLPrefsAscentSysImpl(); + /*virtual*/ ~LLPrefsAscentSysImpl() { }; virtual void refresh(); @@ -56,6 +61,7 @@ public: private: static void onCommitCheckBox(LLUICtrl* ctrl, void* user_data); void refreshValues(); + //System BOOL mSaveScriptsAsMono; BOOL mDoubleClickTeleport; BOOL mHideNotificationsInChat; @@ -71,66 +77,103 @@ private: BOOL mEnableClouds; BOOL mInitialEnableClouds; BOOL mBroadcastViewerEffects; + BOOL mAlwaysRezInGroup; U32 mSpeedRezInterval; U32 mLinksForChattingObjects; U32 mTimeFormat; U32 mDateFormat; - U32 mSpoofProtectionAtOpen; }; -LLPrefsInertImpl::LLPrefsInertImpl() - : LLPanel(std::string("Inert Prefs Panel")) +LLPrefsAscentSysImpl::LLPrefsAscentSysImpl() + : LLPanel(std::string("Ascent")) { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_inert.xml"); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_system.xml"); childSetCommitCallback("speed_rez_check", onCommitCheckBox, this); + refresh(); mInitialEnableClouds = mEnableClouds; } //static -void LLPrefsInertImpl::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) +void LLPrefsAscentSysImpl::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) { - LLPrefsInertImpl* self = (LLPrefsInertImpl*)user_data; + LLPrefsAscentSysImpl* self = (LLPrefsAscentSysImpl*)user_data; self->childEnable("fetch_inventory_on_login_check"); + + llinfos << "Change to " << ctrl->getControlName() << llendl; + + if (ctrl->getControlName() == "SpeedRez") + { + if (self->childGetValue("speed_rez_check").asBoolean()) + { + self->childEnable("speed_rez_interval"); + self->childEnable("speed_rez_seconds"); + } + else + { + self->childDisable("speed_rez_interval"); + self->childDisable("speed_rez_seconds"); + } + } - if (self->childGetValue("speed_rez_check").asBoolean()) - { - self->childEnable("speed_rez_interval"); - self->childEnable("speed_rez_seconds"); - } - else - { - self->childDisable("speed_rez_interval"); - self->childDisable("speed_rez_seconds"); - } } -void LLPrefsInertImpl::refreshValues() +void LLPrefsAscentSysImpl::refreshValues() { - mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveScriptsAsMono"); - mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport"); - mHideNotificationsInChat = gSavedSettings.getBOOL("HideNotificationsInChat"); - mPlayTypingSound = gSavedSettings.getBOOL("PlayTypingSound"); - mDisablePointAtAndBeam = gSavedSettings.getBOOL("DisablePointAtAndBeam"); - mPrivateLookAt = gSavedSettings.getBOOL("PrivateLookAt"); mSecondsInChatAndIMs = gSavedSettings.getBOOL("SecondsInChatAndIMs"); - mFetchInventoryOnLogin = gSavedSettings.getBOOL("FetchInventoryOnLogin"); - mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); - mSpeedRez = gSavedSettings.getBOOL("SpeedRez"); - mSpeedRezInterval = gSavedSettings.getU32("SpeedRezInterval"); - mLinksForChattingObjects = gSavedSettings.getU32("LinksForChattingObjects"); - mRevokePermsOnStandUp = gSavedSettings.getBOOL("RevokePermsOnStandUp"); + + mPlayTypingSound = gSavedSettings.getBOOL("PlayTypingSound"); + mEnableLLWind = gSavedSettings.getBOOL("WindEnabled"); mEnableClouds = gSavedSettings.getBOOL("CloudsEnabled"); + + mHideNotificationsInChat = gSavedSettings.getBOOL("AscentHideTypingNotification"); + mLinksForChattingObjects = gSavedSettings.getU32("LinksForChattingObjects"); + + mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport"); + mSpeedRez = gSavedSettings.getBOOL("SpeedRez"); + mSpeedRezInterval = gSavedSettings.getU32("SpeedRezInterval"); + mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); mBroadcastViewerEffects = gSavedSettings.getBOOL("BroadcastViewerEffects"); + mDisablePointAtAndBeam = gSavedSettings.getBOOL("DisablePointAtAndBeam"); + mPrivateLookAt = gSavedSettings.getBOOL("PrivateLookAt"); + mRevokePermsOnStandUp = gSavedSettings.getBOOL("RevokePermsOnStandUp"); + mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveScriptsAsMono"); + mFetchInventoryOnLogin = gSavedSettings.getBOOL("FetchInventoryOnLogin"); + mAlwaysRezInGroup = gSavedSettings.getBOOL("AscentAlwaysRezInGroup"); } -void LLPrefsInertImpl::refresh() +void LLPrefsAscentSysImpl::refresh() { refreshValues(); + + childSetValue("seconds_in_chat_and_ims_check", mSecondsInChatAndIMs); + + //Save Chat/IM + childSetValue("play_typing_sound_check", mPlayTypingSound); + + //Save Performance + childSetValue("enable_wind", mEnableLLWind); + childSetValue("enable_clouds", mEnableClouds); + + //Privacy + childSetValue("hide_typing_check", mHideNotificationsInChat); + + //Misc + childSetValue("double_click_teleport_check", mDoubleClickTeleport); + childSetValue("speed_rez_check", mSpeedRez); + + childSetValue("preview_anim_in_world_check", mPreviewAnimInWorld); + childSetValue("broadcast_viewer_effects", mBroadcastViewerEffects); + childSetValue("disable_point_at_and_beams_check", mDisablePointAtAndBeam); + childSetValue("private_look_at_check", mPrivateLookAt); + childSetValue("revoke_perms_on_stand_up_check", mRevokePermsOnStandUp); + childSetValue("save_scripts_as_mono_check", mSaveScriptsAsMono); + childSetValue("fetch_inventory_on_login_check", mFetchInventoryOnLogin); + childSetValue("always_rez_in_group_check", mAlwaysRezInGroup); childEnable("fetch_inventory_on_login_check"); @@ -182,28 +225,12 @@ void LLPrefsInertImpl::refresh() { combo->setCurrentByIndex(mDateFormat); } - mSpoofProtectionAtOpen = gSavedSettings.getU32("SpoofProtectionLevel"); } -void LLPrefsInertImpl::cancel() +void LLPrefsAscentSysImpl::cancel() { - gSavedSettings.setBOOL("SaveScriptsAsMono", mSaveScriptsAsMono); - gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport); - gSavedSettings.setBOOL("HideNotificationsInChat", mHideNotificationsInChat); - gSavedSettings.setBOOL("PlayTypingSound", mPlayTypingSound); - gSavedSettings.setBOOL("DisablePointAtAndBeam", mDisablePointAtAndBeam); - gSavedSettings.setBOOL("PrivateLookAt", mPrivateLookAt); - gSavedSettings.setBOOL("FetchInventoryOnLogin", mFetchInventoryOnLogin); - gSavedSettings.setBOOL("SecondsInChatAndIMs", mSecondsInChatAndIMs); - gSavedSettings.setBOOL("PreviewAnimInWorld", mPreviewAnimInWorld); - gSavedSettings.setBOOL("SpeedRez", mSpeedRez); gSavedSettings.setU32("SpeedRezInterval", mSpeedRezInterval); gSavedSettings.setU32("LinksForChattingObjects", mLinksForChattingObjects); - gSavedSettings.setBOOL("RevokePermsOnStandUp", mRevokePermsOnStandUp); - gSavedSettings.setBOOL("WindEnabled", mEnableLLWind); - gSavedSettings.setBOOL("BroadcastViewerEffects", mBroadcastViewerEffects); - gSavedSettings.setU32("SpoofProtectionLevel", mSpoofProtectionAtOpen); - gLLWindEnabled = mEnableLLWind; if(mInitialEnableClouds != gSavedSettings.getBOOL("CloudsEnabled")) @@ -213,10 +240,13 @@ void LLPrefsInertImpl::cancel() } } -void LLPrefsInertImpl::apply() +void LLPrefsAscentSysImpl::apply() { - std::string short_date, long_date, short_time, long_time, timestamp; + std::string short_date, long_date, short_time, long_time, timestamp; + + gSavedSettings.setU32("LinksForChattingObjects", childGetValue("objects_link").asInteger()); + //Save User Interface LLComboBox* combo = getChild("time_format_combobox"); if (combo) { mTimeFormat = combo->getCurrentIndex(); @@ -265,47 +295,59 @@ void LLPrefsInertImpl::apply() gSavedSettings.setString("ShortTimeFormat", short_time); gSavedSettings.setString("LongTimeFormat", long_time); gSavedSettings.setString("TimestampFormat", timestamp); - if(gMessageSystem) - { - U32 new_spoof_protection = gSavedSettings.getU32("SpoofProtectionLevel"); - if(new_spoof_protection != mSpoofProtectionAtOpen) - { - mSpoofProtectionAtOpen = new_spoof_protection; - gMessageSystem->stopSpoofProtection(); + gSavedSettings.setBOOL("SecondsInChatAndIMs", childGetValue("seconds_in_chat_and_ims_check")); + + //Save Chat/IM + gSavedSettings.setBOOL("PlayTypingSound", childGetValue("play_typing_sound_check")); + + //Save Performance + gSavedSettings.setBOOL("WindEnabled", childGetValue("enable_wind")); + + //Save Privacy + + gSavedSettings.setBOOL("AscentHideTypingNotification", childGetValue("hide_typing_check")); + + //Save Misc + gSavedSettings.setBOOL("DoubleClickTeleport", childGetValue("double_click_teleport_check")); + gSavedSettings.setBOOL("SpeedRez", childGetValue("speed_rez_check")); + gSavedSettings.setU32("SpeedRezInterval", childGetValue("speed_rez_interval").asReal()); + gSavedSettings.setBOOL("PreviewAnimInWorld", childGetValue("preview_anim_in_world_check")); + gSavedSettings.setBOOL("BroadcastViewerEffects", childGetValue("broadcast_viewer_effects")); + gSavedSettings.setBOOL("DisablePointAtAndBeam", childGetValue("disable_point_at_and_beams_check")); + gSavedSettings.setBOOL("PrivateLookAt", childGetValue("private_look_at_check")); + gSavedSettings.setBOOL("RevokePermsOnStandUp", childGetValue("revoke_perms_on_stand_up_check")); + gSavedSettings.setBOOL("SaveScriptsAsMono", childGetValue("save_scripts_as_mono_check")); + gSavedSettings.setBOOL("FetchInventoryOnLogin", childGetValue("fetch_inventory_on_login_check")); + gSavedSettings.setBOOL("AscentAlwaysRezInGroup", childGetValue("always_rez_in_group_check")); + - if(LLViewerLogin::getInstance()->getGridChoice() < GRID_INFO_LOCAL) - gMessageSystem->startSpoofProtection(new_spoof_protection); - else - gMessageSystem->startSpoofProtection(0); - } - } refreshValues(); } //--------------------------------------------------------------------------- -LLPrefsInert::LLPrefsInert() -: impl(* new LLPrefsInertImpl()) +LLPrefsAscentSys::LLPrefsAscentSys() +: impl(* new LLPrefsAscentSysImpl()) { } -LLPrefsInert::~LLPrefsInert() +LLPrefsAscentSys::~LLPrefsAscentSys() { delete &impl; } -void LLPrefsInert::apply() +void LLPrefsAscentSys::apply() { impl.apply(); } -void LLPrefsInert::cancel() +void LLPrefsAscentSys::cancel() { impl.cancel(); } -LLPanel* LLPrefsInert::getPanel() +LLPanel* LLPrefsAscentSys::getPanel() { return &impl; -} +} \ No newline at end of file diff --git a/indra/newview/ascentprefssys.h b/indra/newview/ascentprefssys.h new file mode 100644 index 000000000..e09377129 --- /dev/null +++ b/indra/newview/ascentprefssys.h @@ -0,0 +1,53 @@ +/** + * @file hbprefsinert.h + * @brief Ascent Viewer preferences panel + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, Henri Beauchamp. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef ASCENTPREFSSYS_H +#define ASCENTPREFSSYS_H + +class LLPanel; +class LLPrefsAscentSysImpl; + +class LLPrefsAscentSys +{ +public: + LLPrefsAscentSys(); + ~LLPrefsAscentSys(); + + void apply(); + void cancel(); + + LLPanel* getPanel(); + +protected: + LLPrefsAscentSysImpl& impl; +}; + +#endif \ No newline at end of file diff --git a/indra/newview/ascentprefsvan.cpp b/indra/newview/ascentprefsvan.cpp new file mode 100644 index 000000000..c5d0eed1e --- /dev/null +++ b/indra/newview/ascentprefsvan.cpp @@ -0,0 +1,223 @@ +/** + * @file hbprefsinert.cpp + * @author Henri Beauchamp + * @brief Ascent Viewer preferences panel + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, Henri Beauchamp. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +//File include +#include "ascentprefsvan.h" + +//project includes +#include "llcolorswatch.h" +#include "llvoavatar.h" +#include "llagent.h" +#include "llstartup.h" +#include "llviewercontrol.h" +#include "v4color.h" +#include "lluictrlfactory.h" +#include "llcombobox.h" +#include "llwind.h" +#include "llviewernetwork.h" +#include "pipeline.h" + +class LLPrefsAscentVanImpl : public LLPanel +{ +public: + LLPrefsAscentVanImpl(); + /*virtual*/ ~LLPrefsAscentVanImpl() { }; + + virtual void refresh(); + + void apply(); + void cancel(); + +private: + static void onCommitCheckBox(LLUICtrl* ctrl, void* user_data); + void refreshValues(); + BOOL mShowSelfClientTag; + BOOL mShowSelfClientTagColor; + BOOL mUseAccountSettings; + LLColor4 mEffectColor; + U32 mSelectedClient; +}; + + +LLPrefsAscentVanImpl::LLPrefsAscentVanImpl() + : LLPanel(std::string("Ascent")) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_vanity.xml"); + childSetCommitCallback("use_account_settings_check", onCommitCheckBox, this); + refresh(); + +} + +//static +void LLPrefsAscentVanImpl::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) +{ + LLPrefsAscentVanImpl* self = (LLPrefsAscentVanImpl*)user_data; + self->refresh(); +} + +void LLPrefsAscentVanImpl::refreshValues() +{ + //General + mUseAccountSettings = gSavedSettings.getBOOL("AscentStoreSettingsPerAccount"); + + //Colors + mShowSelfClientTag = gSavedSettings.getBOOL("AscentShowSelfTag"); + mShowSelfClientTagColor = gSavedSettings.getBOOL("AscentShowSelfTagColor"); + + + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + mSelectedClient = gSavedSettings.getU32("AscentSpoofClientIndex"); + mEffectColor = gSavedSettings.getColor4("EffectColor"); + } + else + { + mSelectedClient = gSavedPerAccountSettings.getU32("AscentSpoofClientIndex"); + mEffectColor = gSavedPerAccountSettings.getColor4("EffectColor"); + } +} + +void LLPrefsAscentVanImpl::refresh() +{ + refreshValues(); + //General + childSetValue("use_account_settings_check", mUseAccountSettings); + //Colors + llinfos << "Refreshing Vanity panel." << llendl; + childSetValue("show_self_tag_check", mShowSelfClientTag); + childSetValue("show_self_tag_color_check", mShowSelfClientTagColor); + + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + llinfos << "Retrieving color from client" << llendl; + getChild("effect_color_swatch")->set(gSavedSettings.getColor4("EffectColor")); + gSavedSettings.setColor4("EffectColor", LLColor4::white); + gSavedSettings.setColor4("EffectColor", mEffectColor); + } + else + { + llinfos << "Retrieving color from account" << llendl; + getChild("effect_color_swatch")->set(gSavedPerAccountSettings.getColor4("EffectColor")); + gSavedPerAccountSettings.setColor4("EffectColor", LLColor4::white); + gSavedPerAccountSettings.setColor4("EffectColor", mEffectColor); + } + + + // tag spoofing comboxbox + LLComboBox* combo = getChild("tag_spoofing_combobox"); + combo->setCurrentByIndex(mSelectedClient); + +} + +void LLPrefsAscentVanImpl::cancel() +{ + +} + +void LLPrefsAscentVanImpl::apply() +{ + std::string client_uuid; + U32 client_index; + + //Colors + LLComboBox* combo = getChild("tag_spoofing_combobox"); + if (combo) + { + client_index = combo->getCurrentIndex(); + //Don't rebake if it's not neccesary. + if (client_index != mSelectedClient) + { + client_uuid = combo->getSelectedValue(); + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + gSavedSettings.setString("AscentSpoofClientUUID", client_uuid); + gSavedSettings.setU32("AscentSpoofClientIndex", client_index); + } + else + { + gSavedPerAccountSettings.setString("AscentSpoofClientUUID", client_uuid); + gSavedPerAccountSettings.setU32("AscentSpoofClientIndex", client_index); + } + LLVOAvatar* avatar = gAgent.getAvatarObject(); + if (!avatar) return; + + // Slam pending upload count to "unstick" things + bool slam_for_debug = true; + avatar->forceBakeAllTextures(slam_for_debug); + } + } + + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + llinfos << "Storing color in client" << llendl; + gSavedSettings.setColor4("EffectColor", childGetValue("effect_color_swatch")); + } + else + { + llinfos << "Storing color in account" << llendl; + gSavedPerAccountSettings.setColor4("EffectColor", childGetValue("effect_color_swatch")); + } + + gSavedSettings.setBOOL("AscentShowSelfTag", childGetValue("show_self_tag_check")); + gSavedSettings.setBOOL("AscentShowSelfTagColor", childGetValue("show_self_tag_color_check")); + + refreshValues(); +} + +//--------------------------------------------------------------------------- + +LLPrefsAscentVan::LLPrefsAscentVan() +: impl(* new LLPrefsAscentVanImpl()) +{ +} + +LLPrefsAscentVan::~LLPrefsAscentVan() +{ + delete &impl; +} + +void LLPrefsAscentVan::apply() +{ + impl.apply(); +} + +void LLPrefsAscentVan::cancel() +{ + impl.cancel(); +} + +LLPanel* LLPrefsAscentVan::getPanel() +{ + return &impl; +} diff --git a/indra/newview/hbprefsinert.h b/indra/newview/ascentprefsvan.h similarity index 86% rename from indra/newview/hbprefsinert.h rename to indra/newview/ascentprefsvan.h index 5c0cc0360..ef49c2b07 100644 --- a/indra/newview/hbprefsinert.h +++ b/indra/newview/ascentprefsvan.h @@ -1,6 +1,6 @@ /** * @file hbprefsinert.h - * @brief Inertia Viewer preferences panel + * @brief Ascent Viewer preferences panel * * $LicenseInfo:firstyear=2008&license=viewergpl$ * @@ -29,17 +29,17 @@ * $/LicenseInfo$ */ -#ifndef HBPREFSINERT_H -#define HBPREFSINERT_H +#ifndef ASCENTPREFSVAN_H +#define ASCENTPREFSVAN_H class LLPanel; -class LLPrefsInertImpl; +class LLPrefsAscentVanImpl; -class LLPrefsInert +class LLPrefsAscentVan { public: - LLPrefsInert(); - ~LLPrefsInert(); + LLPrefsAscentVan(); + ~LLPrefsAscentVan(); void apply(); void cancel(); @@ -47,7 +47,7 @@ public: LLPanel* getPanel(); protected: - LLPrefsInertImpl& impl; + LLPrefsAscentVanImpl& impl; }; #endif diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index c66ba0c47..0662f9a33 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -704,61 +704,20 @@ value_min="0" value_max="1"> - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -777,61 +736,20 @@ value_max="2" camera_distance="2.2"> - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -850,61 +768,20 @@ value_max="1.5" camera_distance="1.8"> - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -926,23 +803,10 @@ camera_distance="1.2" camera_angle="0"> - - - - - - - + + + + @@ -961,19 +825,9 @@ value_max="2.8" camera_distance="1.8"> - - - - - + + + @@ -990,9 +844,7 @@ value_max="1" camera_distance="1.8"> - + @@ -1009,29 +861,12 @@ value_max="1" camera_distance="1.8"> - - - - - - - - - - - + + + + + + @@ -1046,15 +881,8 @@ value_min="-1" value_max="1"> - - - + + @@ -1069,15 +897,8 @@ value_min="-2" value_max="2"> - - - + + @@ -1092,15 +913,8 @@ value_min="-1" value_max="1"> - - - + + @@ -1115,15 +929,8 @@ value_min="-2" value_max="2"> - - - + + @@ -1140,25 +947,10 @@ value_min="-.25" value_max=".10"> - - - - - - - + + + + @@ -1173,15 +965,8 @@ value_min="0" value_max="1"> - - - + + @@ -1196,15 +981,8 @@ value_min="0" value_max="1"> - - - + + @@ -1223,15 +1001,8 @@ camera_distance="1.4" camera_angle="0"> - - - + + @@ -1251,10 +1022,7 @@ camera_distance=".8" camera_angle="15"> - + @@ -1269,15 +1037,8 @@ value_min="-1" value_max="1"> - - - + + @@ -1294,21 +1055,10 @@ value_max="1" camera_distance="2.5"> - - - - - - - + + + + @@ -1326,21 +1076,10 @@ value_default=".6" camera_distance="1.5"> - - - - - - - + + + + @@ -1360,9 +1099,7 @@ camera_distance=".8" camera_angle="15"> - + diff --git a/indra/newview/dbghelp.dll b/indra/newview/dbghelp.dll new file mode 100644 index 000000000..a5a71ca0f Binary files /dev/null and b/indra/newview/dbghelp.dll differ diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp new file mode 100644 index 000000000..1ca49c145 --- /dev/null +++ b/indra/newview/hippogridmanager.cpp @@ -0,0 +1,581 @@ + + +#include "llviewerprecompiledheaders.h" + +#include "hippogridmanager.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "llviewercontrol.h" +#include "llweb.h" + +#include "hipporestrequest.h" + + +// ******************************************************************** +// Global Variables + +HippoGridManager *gHippoGridManager = 0; + +HippoGridInfo HippoGridInfo::FALLBACK_GRIDINFO(""); + + + +// ******************************************************************** +// ******************************************************************** +// HippoGridInfo +// ******************************************************************** +// ******************************************************************** + + +// ******************************************************************** +// Initialize + +HippoGridInfo::HippoGridInfo(const std::string &gridNick) : + mPlatform(PLATFORM_OTHER), + mGridNick(gridNick), + mRenderCompat(true), + mCurrencySymbol("OS$"), + mRealCurrencySymbol("US$"), + mDirectoryFee(30) +{ + cleanUpGridNick(mGridNick); +} + + +void HippoGridInfo::setPlatform(Platform platform) +{ + mPlatform = platform; + mCurrencySymbol = (mPlatform == PLATFORM_SECONDLIFE)? "L$": "OS$"; +} + + +void HippoGridInfo::setPlatform(const std::string &platform) +{ + std::string tmp = platform; + for (unsigned i=0; imXmlState = XML_GRIDNICK; + else if (strcasecmp(name, "gridname") == 0) + self->mXmlState = XML_GRIDNAME; + else if (strcasecmp(name, "platform") == 0) + self->mXmlState = XML_PLATFORM; + else if ((strcasecmp(name, "login") == 0) || (strcasecmp(name, "loginuri") == 0)) + self->mXmlState = XML_LOGINURI; + else if ((strcasecmp(name, "welcome") == 0) || (strcasecmp(name, "loginpage") == 0)) + self->mXmlState = XML_LOGINPAGE; + else if ((strcasecmp(name, "economy") == 0) || (strcasecmp(name, "helperuri") == 0)) + self->mXmlState = XML_HELPERURI; + else if ((strcasecmp(name, "about") == 0) || (strcasecmp(name, "website") == 0)) + self->mXmlState = XML_WEBSITE; + else if ((strcasecmp(name, "help") == 0) || (strcasecmp(name, "support") == 0)) + self->mXmlState = XML_SUPPORT; + else if ((strcasecmp(name, "register") == 0) || (strcasecmp(name, "account") == 0)) + self->mXmlState = XML_REGISTER; + else if (strcasecmp(name, "password") == 0) + self->mXmlState = XML_PASSWORD; + //else if (strcasecmp(name, "search") == 0) + //self->mXmlState = XML_SEARCH; +} + +//static +void HippoGridInfo::onXmlElementEnd(void *userData, const XML_Char *name) +{ + HippoGridInfo *self = (HippoGridInfo*)userData; + self->mXmlState = XML_VOID; +} + +//static +void HippoGridInfo::onXmlCharacterData(void *userData, const XML_Char *s, int len) +{ + HippoGridInfo *self = (HippoGridInfo*)userData; + switch (self->mXmlState) { + + case XML_GRIDNICK: + if (self->mGridNick == "") self->mGridNick.assign(s, len); + cleanUpGridNick(self->mGridNick); + break; + + case XML_PLATFORM: { + std::string platform(s, len); + self->setPlatform(platform); + break; + } + + case XML_LOGINURI: + self->mLoginUri.assign(s, len); + cleanUpUri(self->mLoginUri); + break; + + case XML_HELPERURI: + self->mHelperUri.assign(s, len); + cleanUpUri(self->mHelperUri); + break; + + case XML_SEARCH: + //self->mSearchUrl.assign(s, len); + //cleanUpQueryUrl(mSearchUrl); + break; + + case XML_GRIDNAME: self->mGridName.assign(s, len); break; + case XML_LOGINPAGE: self->mLoginPage.assign(s, len); break; + case XML_WEBSITE: self->mWebSite.assign(s, len); break; + case XML_SUPPORT: self->mSupportUrl.assign(s, len); break; + case XML_REGISTER: self->mRegisterUrl.assign(s, len); break; + case XML_PASSWORD: self->mPasswordUrl.assign(s, len); break; + + case XML_VOID: break; + } +} + + +bool HippoGridInfo::retrieveGridInfo() +{ + if (mLoginUri == "") return false; + + std::string reply; + int result = HippoRestRequest::getBlocking(mLoginUri + "get_grid_info", &reply); + if (result != 200) return false; + + llinfos << "Received: " << reply << llendl; + + bool success = true; + XML_Parser parser = XML_ParserCreate(0); + XML_SetUserData(parser, this); + XML_SetElementHandler(parser, onXmlElementStart, onXmlElementEnd); + XML_SetCharacterDataHandler(parser, onXmlCharacterData); + mXmlState = XML_VOID; + if (!XML_Parse(parser, reply.data(), reply.size(), TRUE)) { + llwarns << "XML Parse Error: " << XML_ErrorString(XML_GetErrorCode(parser)) << llendl; + success = false; + } + XML_ParserFree(parser); + + return success; +} + + +std::string HippoGridInfo::getUploadFee() const +{ + std::string fee; + formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), true); + return fee; +} + +std::string HippoGridInfo::getGroupCreationFee() const +{ + std::string fee; + formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceGroupCreate(), false); + return fee; +} + +std::string HippoGridInfo::getDirectoryFee() const +{ + std::string fee; + formatFee(fee, mDirectoryFee, true); + if (fee != "free") fee += "/week"; + return fee; +} +int HippoGridInfo::getRawDirectoryFee() const +{ + return mDirectoryFee; +} + +void HippoGridInfo::formatFee(std::string &fee, int cost, bool showFree) const +{ + if (showFree && (cost == 0)) { + fee = "free"; + } else { + fee = llformat("%s%d", getCurrencySymbol().c_str(), cost); + } +} + + +// ******************************************************************** +// Static Helpers + +// static +const char *HippoGridInfo::getPlatformString(Platform platform) +{ + static const char *platformStrings[PLATFORM_LAST] = { + "Other", "OpenSim", "SecondLife" + }; + + if ((platform < PLATFORM_OTHER) || (platform >= PLATFORM_LAST)) + platform = PLATFORM_OTHER; + return platformStrings[platform]; +} + + +// static +void HippoGridInfo::cleanUpGridNick(std::string &gridnick) +{ + std::string tmp; + int size = gridnick.size(); + for (int i=0; i::iterator it, end = mGridInfo.end(); + for (it=mGridInfo.begin(); it != end; ++it) { + delete it->second; + } + mGridInfo.clear(); +} + + +void HippoGridManager::init() +{ + HippoGridInfo::initFallback(); + loadFromFile(); + + // !!!### gSavedSettings.getControl("CmdLineLoginURI"); + // !!!### gSavedSettings.getString("CmdLineLoginPage"); + // !!!### gSavedSettings.getString("CmdLineHelperURI"); + // !!!### LLString::compareInsensitive(gGridInfo[grid_index].mLabel, grid_name.c_str())) +} + + +void HippoGridManager::discardAndReload() +{ + cleanup(); + loadFromFile(); +} + + +// ******************************************************************** +// Public Access + +HippoGridInfo *HippoGridManager::getGrid(const std::string &grid) const +{ + std::map::const_iterator it; + it = mGridInfo.find(grid); + if (it != mGridInfo.end()) { + return it->second; + } else { + return 0; + } +} + + +HippoGridInfo *HippoGridManager::getCurrentGrid() const +{ + HippoGridInfo *grid = getGrid(mCurrentGrid); + if (grid) { + return grid; + } else { + return &HippoGridInfo::FALLBACK_GRIDINFO; + } +} + + +void HippoGridManager::addGrid(HippoGridInfo *grid) +{ + if (!grid) return; + const std::string &nick = grid->getGridNick(); + if (nick == "") { + llwarns << "Ignoring to try adding grid with empty nick." << llendl; + delete grid; + return; + } + if (mGridInfo.find(nick) != mGridInfo.end()) { + llwarns << "Ignoring to try adding existing grid " << nick << '.' << llendl; + delete grid; + return; + } + mGridInfo[nick] = grid; +} + + +void HippoGridManager::deleteGrid(const std::string &grid) +{ + GridIterator it = mGridInfo.find(grid); + if (it == mGridInfo.end()) { + llwarns << "Trying to delete non-existing grid " << grid << '.' << llendl; + return; + } + mGridInfo.erase(it); + llinfos << "Number of grids now: " << mGridInfo.size() << llendl; + if (mGridInfo.empty()) llinfos << "Grid info map is empty." << llendl; + if (grid == mDefaultGrid) + setDefaultGrid(""); // sets first grid, if map not empty + if (grid == mCurrentGrid) + mCurrentGrid = mDefaultGrid; +} + + +void HippoGridManager::setDefaultGrid(const std::string &grid) +{ + GridIterator it = mGridInfo.find(grid); + if (it != mGridInfo.end()) { + mDefaultGrid = grid; + } else if (mGridInfo.find("secondlife") != mGridInfo.end()) { + mDefaultGrid = "secondlife"; + } else if (!mGridInfo.empty()) { + mDefaultGrid = mGridInfo.begin()->first; + } else { + mDefaultGrid = ""; + } +} + + +void HippoGridManager::setCurrentGrid(const std::string &grid) +{ + GridIterator it = mGridInfo.find(grid); + if (it != mGridInfo.end()) { + mCurrentGrid = grid; + } else if (!mGridInfo.empty()) { + llwarns << "Unknown grid '" << grid << "'. Setting to default grid." << llendl; + mCurrentGrid = mDefaultGrid; + } +} + + +// ******************************************************************** +// Persistent Store + +void HippoGridManager::loadFromFile() +{ + mDefaultGridsVersion = 0; + // load user grid info + parseFile(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "grid_info.xml"), false); + // merge default grid info, if newer. Force load, if list of grids is empty. + parseFile(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "default_grids.xml"), !mGridInfo.empty()); + std::string last_grid = gSavedSettings.getString("LastSelectedGrid"); + if (last_grid.empty()) last_grid = gSavedSettings.getString("DefaultGrid"); + setDefaultGrid(last_grid); + setCurrentGrid(last_grid); +} + +void HippoGridManager::parseFile(const std::string &fileName, bool mergeIfNewer) +{ + llifstream infile; + infile.open(fileName.c_str()); + if(!infile.is_open()) { + llwarns << "Cannot find grid info file " << fileName << " to load." << llendl; + return; + } + + LLSD gridInfo; + if (LLSDSerialize::fromXML(gridInfo, infile) <= 0) { + llwarns << "Unable to parse grid info file " << fileName << '.' << llendl; + return; + } + + llinfos << "Loading grid info file " << fileName << '.' << llendl; + parseData(gridInfo, mergeIfNewer); +} + + +void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer) +{ + if (mergeIfNewer) { + LLSD::array_const_iterator it, end = gridInfo.endArray(); + for (it = gridInfo.beginArray(); it != end; ++it) { + LLSD gridMap = *it; + if (gridMap.has("default_grids_version")) { + int version = gridMap["default_grids_version"]; + if (version <= mDefaultGridsVersion) return; + else break; + } + } + if (it == end) { + llwarns << "Grid data has no version number." << llendl; + return; + } + } + + llinfos << "Loading grid data." << llendl; + + LLSD::array_const_iterator it, end = gridInfo.endArray(); + for (it = gridInfo.beginArray(); it != end; ++it) { + LLSD gridMap = *it; + if (gridMap.has("default_grids_version")) { + mDefaultGridsVersion = gridMap["default_grids_version"]; + } else if (gridMap.has("gridnick") && gridMap.has("loginuri")) { + std::string gridnick = gridMap["gridnick"]; + HippoGridInfo *grid; + GridIterator it = mGridInfo.find(gridnick); + bool newGrid = (it == mGridInfo.end()); + if (newGrid) { + // create new grid info + grid = new HippoGridInfo(gridnick); + } else { + // update existing grid info + grid = it->second; + } + grid->setLoginUri(gridMap["loginuri"]); + if (gridMap.has("platform")) grid->setPlatform(gridMap["platform"]); + if (gridMap.has("gridname")) grid->setGridName(gridMap["gridname"]); + if (gridMap.has("loginpage")) grid->setLoginPage(gridMap["loginpage"]); + if (gridMap.has("helperuri")) grid->setHelperUri(gridMap["helperuri"]); + if (gridMap.has("website")) grid->setWebSite(gridMap["website"]); + if (gridMap.has("support")) grid->setSupportUrl(gridMap["support"]); + if (gridMap.has("register")) grid->setRegisterUrl(gridMap["register"]); + if (gridMap.has("password")) grid->setPasswordUrl(gridMap["password"]); + //if (gridMap.has("search")) grid->setSearchUrl(gridMap["search"]); + if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]); + if (gridMap.has("firstname")) grid->setFirstName(gridMap["firstname"]); + if (gridMap.has("lastname")) grid->setLastName(gridMap["lastname"]); + if (gridMap.has("avatarpassword")) grid->setAvatarPassword(gridMap["avatarpassword"]); + if (newGrid) addGrid(grid); + } + } +} + + +void HippoGridManager::saveFile() +{ + // save default grid to client settings + gSavedSettings.setString("DefaultGrid", mDefaultGrid); + + // build LLSD + LLSD gridInfo; + gridInfo[0]["default_grids_version"] = mDefaultGridsVersion; + + // add grids + S32 i = 1; + GridIterator it, end = mGridInfo.end(); + for (it = mGridInfo.begin(); it != end; ++it, i++) { + HippoGridInfo *grid = it->second; + gridInfo[i]["gridnick"] = grid->getGridNick(); + gridInfo[i]["platform"] = HippoGridInfo::getPlatformString(grid->getPlatform()); + gridInfo[i]["gridname"] = grid->getGridName(); + gridInfo[i]["loginuri"] = grid->getLoginUri(); + gridInfo[i]["loginpage"] = grid->getLoginPage(); + gridInfo[i]["helperuri"] = grid->getHelperUri(); + gridInfo[i]["website"] = grid->getWebSite(); + gridInfo[i]["support"] = grid->getSupportUrl(); + gridInfo[i]["register"] = grid->getRegisterUrl(); + gridInfo[i]["password"] = grid->getPasswordUrl(); + gridInfo[i]["firstname"] = grid->getFirstName(); + gridInfo[i]["lastname"] = grid->getLastName(); + gridInfo[i]["avatarpassword"] = grid->getAvatarPassword(); + + //gridInfo[i]["search"] = grid->getSearchUrl(); + gridInfo[i]["render_compat"] = grid->isRenderCompat(); + } + + // write client grid info file + std::string fileName = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "grid_info.xml"); + llofstream file; + file.open(fileName.c_str()); + if (file.is_open()) { + LLSDSerialize::toPrettyXML(gridInfo, file); + file.close(); + llinfos << "Saved grids to " << fileName << llendl; + } else { + llerrs << "Unable to open grid info file: " << fileName << llendl; + } +} diff --git a/indra/newview/hippogridmanager.h b/indra/newview/hippogridmanager.h new file mode 100644 index 000000000..f22b14484 --- /dev/null +++ b/indra/newview/hippogridmanager.h @@ -0,0 +1,176 @@ +#ifndef __HIPPO_GRID_MANAGER_H__ +#define __HIPPO_GRID_MANAGER_H__ + + +#include +#include + +#ifndef XML_STATIC +#define XML_STATIC +#endif + +#ifdef LL_STANDALONE +#include +#else +#include "expat/expat.h" +#endif + +class LLSD; + + +class HippoGridInfo +{ +public: + enum Platform { + PLATFORM_OTHER = 0, + PLATFORM_OPENSIM, + PLATFORM_SECONDLIFE, + PLATFORM_LAST + }; + enum SearchType { + SEARCH_ALL_EMPTY, + SEARCH_ALL_QUERY, + SEARCH_ALL_TEMPLATE + }; + + explicit HippoGridInfo(const std::string &gridNick); + + Platform getPlatform() const { return mPlatform; } + const std::string &getGridNick() const { return mGridNick; } + const std::string &getGridName() const { return mGridName; } + const std::string &getLoginUri() const { return mLoginUri; } + const std::string &getLoginPage() const { return mLoginPage; } + const std::string &getHelperUri() const { return mHelperUri; } + const std::string &getWebSite() const { return mWebSite; } + const std::string &getSupportUrl() const { return mSupportUrl; } + const std::string &getRegisterUrl() const { return mRegisterUrl; } + const std::string &getPasswordUrl() const { return mPasswordUrl; } + const std::string &getSearchUrl() const { return mSearchUrl; } + const std::string &getFirstName() const { return mFirstName; } + const std::string &getLastName() const { return mLastName; } + const std::string &getAvatarPassword() const { return mAvatarPassword; } + std::string getSearchUrl(SearchType ty) const; + bool isRenderCompat() const { return mRenderCompat; } + + const std::string &getCurrencySymbol() const { return mCurrencySymbol; } + const std::string &getRealCurrencySymbol() const { return mRealCurrencySymbol; } + std::string getUploadFee() const; + std::string getGroupCreationFee() const; + std::string getDirectoryFee() const; + int getRawDirectoryFee() const; + + bool isOpenSimulator() const { return (mPlatform == PLATFORM_OPENSIM ); } + bool isSecondLife() const { return (mPlatform == PLATFORM_SECONDLIFE); } + + void setPlatform (const std::string &platform); + void setPlatform (Platform platform); + void setGridName (const std::string &gridName) { mGridName = gridName; } + void setLoginUri (const std::string &loginUri) { mLoginUri = loginUri; cleanUpUri(mLoginUri); } + void setLoginPage(const std::string &loginPage) { mLoginPage = loginPage; } + void setHelperUri(const std::string &helperUri) { mHelperUri = helperUri; cleanUpUri(mHelperUri); } + void setWebSite (const std::string &website) { mWebSite = website; } + void setSupportUrl(const std::string &url) { mSupportUrl = url; } + void setRegisterUrl(const std::string &url) { mRegisterUrl = url; } + void setPasswordUrl(const std::string &url) { mPasswordUrl = url; } + void setSearchUrl(const std::string &url) { mSearchUrl = url; } + void setRenderCompat(bool compat) { mRenderCompat = compat; } + void setFirstName(const std::string &firstName) { mFirstName = firstName; } //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + void setLastName(const std::string &lastName) { mLastName = lastName; } + void setAvatarPassword(const std::string &avatarPassword) { mAvatarPassword = avatarPassword; } + + void setCurrencySymbol(const std::string &sym) { mCurrencySymbol = sym.substr(0, 3); } + void setRealCurrencySymbol(const std::string &sym) { mRealCurrencySymbol = sym.substr(0, 3); } + void setDirectoryFee(int fee) { mDirectoryFee = fee; } + + bool retrieveGridInfo(); + + static const char *getPlatformString(Platform platform); + static void cleanUpGridNick(std::string &gridnick); + + static HippoGridInfo FALLBACK_GRIDINFO; + static void initFallback(); + +private: + Platform mPlatform; + std::string mGridNick; + std::string mGridName; + std::string mLoginUri; + std::string mLoginPage; + std::string mHelperUri; + std::string mWebSite; + std::string mSupportUrl; + std::string mRegisterUrl; + std::string mPasswordUrl; + std::string mSearchUrl; + std::string mFirstName; + std::string mLastName; + std::string mAvatarPassword; + bool mRenderCompat; + + std::string mCurrencySymbol; + std::string mRealCurrencySymbol; + int mDirectoryFee; + + // for parsing grid info XML + enum XmlState { + XML_VOID, XML_GRIDNICK, XML_PLATFORM, XML_GRIDNAME, + XML_LOGINURI, XML_LOGINPAGE, XML_HELPERURI, + XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PASSWORD, XML_SEARCH + }; + XmlState mXmlState; + + static void cleanUpUri(std::string &uri); + void formatFee(std::string &fee, int cost, bool showFree) const; + + static void onXmlElementStart(void *userData, const XML_Char *name, const XML_Char **atts); + static void onXmlElementEnd(void *userData, const XML_Char *name); + static void onXmlCharacterData(void *userData, const XML_Char *s, int len); +}; + + +class HippoGridManager +{ +public: + HippoGridManager(); + ~HippoGridManager(); + + void init(); + void saveFile(); + void discardAndReload(); + + HippoGridInfo *getGrid(const std::string &grid) const; + HippoGridInfo *getConnectedGrid() const { return (mConnectedGrid)? mConnectedGrid: getCurrentGrid(); } + HippoGridInfo *getCurrentGrid() const; + const std::string &getDefaultGridNick() const { return mDefaultGrid; } + const std::string &getCurrentGridNick() const { return mCurrentGrid; } + + void setDefaultGrid(const std::string &grid); + void setCurrentGrid(const std::string &grid); + void setCurrentGridAsConnected() { mConnectedGrid = getCurrentGrid(); } + + void addGrid(HippoGridInfo *grid); + void deleteGrid(const std::string &grid); + + typedef std::map::iterator GridIterator; + GridIterator beginGrid() { return mGridInfo.begin(); } + GridIterator endGrid() { return mGridInfo.end(); } + +private: + std::map mGridInfo; + std::string mDefaultGrid; + std::string mCurrentGrid; + HippoGridInfo *mConnectedGrid; + int mDefaultGridsVersion; + + void cleanup(); + void loadFromFile(); + void parseFile(const std::string &fileName, bool mergeIfNewer); + void parseUrl(const char *url, bool mergeIfNewer); + void parseData(LLSD &gridInfo, bool mergeIfNewer); +}; + + +extern HippoGridManager *gHippoGridManager; + + +#endif diff --git a/indra/newview/hipporestrequest.cpp b/indra/newview/hipporestrequest.cpp new file mode 100644 index 000000000..cf3888d40 --- /dev/null +++ b/indra/newview/hipporestrequest.cpp @@ -0,0 +1,56 @@ + + +#include "llviewerprecompiledheaders.h" + +#include "hipporestrequest.h" + +#ifndef CURL_STATICLIB +#define CURL_STATICLIB 1 +#endif +#include + +#include +#include + + +static size_t curlWrite(void *ptr, size_t size, size_t nmemb, void *userData) +{ + std::string *result = (std::string*)userData; + size_t bytes = (size * nmemb); + result->append((char*)ptr, bytes); + return nmemb; +} + + +//static +int HippoRestRequest::getBlocking(const std::string &url, std::string *result) +{ + llinfos << "Requesting: " << url << llendl; + + char curlErrorBuffer[CURL_ERROR_SIZE]; + CURL* curlp = curl_easy_init(); + + curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts + curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds + + curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, curlWrite); + curl_easy_setopt(curlp, CURLOPT_WRITEDATA, result); + curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curlErrorBuffer); + curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1); + + *result = ""; + S32 curlSuccess = curl_easy_perform(curlp); + S32 httpStatus = 499; + curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &httpStatus); + + if (curlSuccess != 0) { + llwarns << "CURL ERROR (HTTP Status " << httpStatus << "): " << curlErrorBuffer << llendl; + } else if (httpStatus != 200) { + llwarns << "HTTP Error " << httpStatus << ", but no Curl error." << llendl; + } + + curl_easy_cleanup(curlp); + return httpStatus; +} + diff --git a/indra/newview/hipporestrequest.h b/indra/newview/hipporestrequest.h new file mode 100644 index 000000000..1dcb4a09b --- /dev/null +++ b/indra/newview/hipporestrequest.h @@ -0,0 +1,16 @@ +#ifndef __HIPPO_REST_REQTUEST_H__ +#define __HIPPO_REST_REQTUEST_H__ + + +#include + + +class HippoRestRequest +{ + public: + static int getBlocking(const std::string &url, std::string *result); + +}; + + +#endif diff --git a/indra/newview/importtracker.cpp b/indra/newview/importtracker.cpp new file mode 100644 index 000000000..448fa7bb7 --- /dev/null +++ b/indra/newview/importtracker.cpp @@ -0,0 +1,1122 @@ +/** + * @file importtracker.cpp + * @brief A utility for importing linksets from XML. + * Discrete wuz here + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llframetimer.h" +#include "llprimitive.h" +#include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llvolumemessage.h" +#include "llchat.h" +#include "importtracker.h" +#include "llsdserialize.h" +#include "lltooldraganddrop.h" +#include "llassetuploadresponders.h" +#include "lleconomy.h" + +#include "llfloaterperms.h" + + +#include "llviewertexteditor.h" + +#include "jclslpreproc.h" + +ImportTracker gImportTracker; + +extern LLAgent gAgent; + +void ImportTracker::importer(std::string file, void (*callback)(LLViewerObject*)) +{ + mDownCallback = callback; + asset_insertions = 0; + + llifstream importer(file); + LLSD data; + LLSDSerialize::fromXMLDocument(data, importer); + + LLSD file_data = data["Objects"]; + data = LLSD(); + + filepath = file; + asset_dir = filepath.substr(0,filepath.find_last_of(".")) + "_assets"; + + linksetgroups=file_data; + //llinfos << "LOADED LINKSETS, PREPARING.." << llendl; + groupcounter=0; + LLSD ls_llsd; + ls_llsd=linksetgroups[groupcounter]["Object"]; + linksetoffset=linksetgroups[groupcounter]["ObjectPos"]; + initialPos=gAgent.getCameraPositionAgent(); + import(ls_llsd); +} + +void ImportTracker::import(LLSD& ls_data) +{ + if(!(linkset.size())) + if(!(linksetgroups.size())) + initialPos=gAgent.getCameraPositionAgent(); + linkset = ls_data; + updated=0; + LLSD rot = linkset[0]["rotation"]; + rootrot.mQ[VX] = (F32)(rot[0].asReal()); + rootrot.mQ[VY] = (F32)(rot[1].asReal()); + rootrot.mQ[VZ] = (F32)(rot[2].asReal()); + rootrot.mQ[VW] = (F32)(rot[3].asReal()); + state = BUILDING; + //llinfos << "IMPORTED, BUILDING.." << llendl; + plywood_above_head(); +} + +void ImportTracker::expectRez() +{ + numberExpected++; + state = WAND; + //llinfos << "EXPECTING CUBE..." << llendl; +} + +void ImportTracker::clear() +{ + if(linkset.isDefined())lastrootid = linkset[0]["LocalID"].asInteger(); + localids.clear(); + linkset.clear(); + state = IDLE; + finish(); +} +void cmdline_printchat(std::string message); +LLViewerObject* find(U32 local) +{ + S32 i; + S32 total = gObjectList.getNumObjects(); + + for (i = 0; i < total; i++) + { + LLViewerObject *objectp = gObjectList.getObject(i); + if (objectp) + { + if(objectp->getLocalID() == local)return objectp; + } + } + return NULL; +} +void ImportTracker::finish() +{ + if(asset_insertions == 0) + { + if(lastrootid != 0) + { + if(mDownCallback) + { + LLViewerObject* objectp = find(lastrootid); + mDownCallback(objectp); + } + cmdline_printchat("import completed"); + } + } +} + +void ImportTracker::cleargroups() +{ + linksetgroups.clear(); + groupcounter=0; + linksetoffset=LLVector3(0.0f,0.0f,0.0f); + initialPos=LLVector3(0.0f,0.0f,0.0f); + state = IDLE; +} + +void ImportTracker::cleanUp() +{ + clear(); + if(linksetgroups.size()) + { + if(groupcounter < (linksetgroups.size() - 1)) + { + ++groupcounter; + LLSD ls_llsd; + ls_llsd=linksetgroups[groupcounter]["Object"]; + linksetoffset=linksetgroups[groupcounter]["ObjectPos"]; + import(ls_llsd); + } + } + else cleargroups(); +} + +void ImportTracker::get_update(S32 newid, BOOL justCreated, BOOL createSelected) +{ + switch (state) + { + //lgg crap + case WAND: + if(justCreated && createSelected) + { + numberExpected--; + if(numberExpected<=0) + state=IDLE; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectImage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (U32)newid); + msg->addStringFast(_PREHASH_MediaURL, NULL); + + LLPrimitive obj; + obj.setNumTEs(U8(10)); + S32 shinnyLevel = 0; + if(gSavedSettings.getString("EmeraldBuildPrefs_Shiny")== "None") shinnyLevel = 0; + if(gSavedSettings.getString("EmeraldBuildPrefs_Shiny")== "Low") shinnyLevel = 1; + if(gSavedSettings.getString("EmeraldBuildPrefs_Shiny")== "Medium") shinnyLevel = 2; + if(gSavedSettings.getString("EmeraldBuildPrefs_Shiny")== "High") shinnyLevel = 3; + + for (int i = 0; i < 10; i++) + { + LLTextureEntry tex = LLTextureEntry(LLUUID(gSavedSettings.getString("EmeraldBuildPrefs_Texture"))); + tex.setColor(gSavedSettings.getColor4("EmeraldBuildPrefs_Color")); + tex.setAlpha(1.0 - ((gSavedSettings.getF32("EmeraldBuildPrefs_Alpha")) / 100.0)); + tex.setGlow(gSavedSettings.getF32("EmeraldBuildPrefs_Glow")); + if(gSavedSettings.getBOOL("EmeraldBuildPrefs_FullBright")) + { + tex.setFullbright(TEM_FULLBRIGHT_MASK); + } + + tex.setShiny((U8) shinnyLevel & TEM_SHINY_MASK); + + obj.setTE(U8(i), tex); + } + + obj.packTEMessage(gMessageSystem); + + msg->sendReliable(gAgent.getRegion()->getHost()); + + msg->newMessage("ObjectFlagUpdate"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_ObjectLocalID, (U32)newid ); + msg->addBOOLFast(_PREHASH_UsePhysics, gSavedSettings.getBOOL("EmeraldBuildPrefs_Physical")); + msg->addBOOL("IsTemporary", gSavedSettings.getBOOL("EmeraldBuildPrefs_Temporary")); + msg->addBOOL("IsPhantom", gSavedSettings.getBOOL("EmeraldBuildPrefs_Phantom") ); + msg->addBOOL("CastsShadows", true ); + msg->sendReliable(gAgent.getRegion()->getHost()); + + if(gSavedSettings.getBOOL("EmeraldBuildPrefs_EmbedItem")) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem((LLUUID)gSavedSettings.getString("EmeraldBuildPrefs_Item")); + LLViewerObject* objectp = find((U32)newid); + if(objectp) + if(item) + { + if(item->getType()==LLAssetType::AT_LSL_TEXT) + { + LLToolDragAndDrop::dropScript(objectp, + item, + TRUE, + LLToolDragAndDrop::SOURCE_AGENT, + gAgent.getID()); + }else + { + LLToolDragAndDrop::dropInventory(objectp,item,LLToolDragAndDrop::SOURCE_AGENT,gAgent.getID()); + } + } + } + + msg->newMessageFast(_PREHASH_ObjectPermissions); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_HeaderData); + msg->addBOOLFast(_PREHASH_Override, FALSE); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (U32)newid); + msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER); + msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED); + U32 flags = 0; + if ( gSavedSettings.getBOOL("NextOwnerCopy") ) + { + flags |= PERM_COPY; + } + if ( gSavedSettings.getBOOL("NextOwnerModify") ) + { + flags |= PERM_MODIFY; + } + if ( gSavedSettings.getBOOL("NextOwnerTransfer") ) + { + flags |= PERM_TRANSFER; + } + msg->addU32Fast(_PREHASH_Mask, flags); + msg->sendReliable(gAgent.getRegion()->getHost()); + + //llinfos << "LGG SENDING CUBE TEXTURE.." << llendl; + } + break; + case BUILDING: + + if (justCreated && (int)localids.size() < linkset.size()) + { + localids.push_back(newid); + localids.sort(); + localids.unique(); + + linkset[localids.size() -1]["LocalID"] = newid; + LLSD prim = linkset[localids.size() -1]; + + //MAKERIGHT + if (!(prim).has("Updated")) + { + ++updated; + send_shape(prim); + send_image(prim); + send_extras(prim); + send_namedesc(prim); + send_vectors(prim,updated); + send_properties(prim, updated); + send_inventory(prim); + (prim)["Updated"] = true; + } + if ((int)localids.size() < linkset.size()) + { + plywood_above_head(); + return; + } + else + { + if (updated >= linkset.size()) + { + updated=0; + llinfos << "FINISHED BUILDING, LINKING.." << llendl; + state = LINKING; + link(); + } + } + } + break; + case LINKING: + link(); + break; + } +} +struct InventoryImportInfo +{ + U32 localid; + LLAssetType::EType type; + LLInventoryType::EType inv_type; + EWearableType wear_type; + LLTransactionID tid; + LLUUID assetid; + std::string name; + std::string description; + bool compiled; + std::string filename; + U32 perms; +}; + +void insert(LLViewerInventoryItem* item, LLViewerObject* objectp, InventoryImportInfo* data) +{ + if(!item) + { + return; + } + if(objectp) + { + LLToolDragAndDrop::dropScript(objectp, + item, + TRUE, + LLToolDragAndDrop::SOURCE_AGENT, + gAgent.getID()); + //cmdline_printchat("inserted."); + } + delete data; + gImportTracker.asset_insertions -= 1; + if(gImportTracker.asset_insertions == 0) + { + gImportTracker.finish(); + } +} + +class JCImportTransferCallback : public LLInventoryCallback +{ +public: + JCImportTransferCallback(InventoryImportInfo* idata) + { + data = idata; + } + void fire(const LLUUID &inv_item) + { + //cmdline_printchat("fired transfer for "+inv_item.asString()+"|"+data->assetid.asString()); + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); + LLViewerObject* objectp = find(data->localid); + insert(item, objectp, data); + } +private: + InventoryImportInfo* data; +}; + +class JCImportInventoryResponder : public LLAssetUploadResponder +{ +public: + JCImportInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type, InventoryImportInfo* idata) : LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + data = idata; + } + + JCImportInventoryResponder(const LLSD& post_data, const std::string& file_name, + LLAssetType::EType asset_type) : LLAssetUploadResponder(post_data, file_name, asset_type) + { + + } + virtual void uploadComplete(const LLSD& content) + { + LLPointer cb = new JCImportTransferCallback(data); + LLPermissions perm; + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH), data->tid, data->name, + data->description, data->type, LLInventoryType::defaultForAssetType(data->type), data->wear_type, + LLFloaterPerms::getNextOwnerPerms(), + cb); + + } +private: + InventoryImportInfo* data; +}; + +class JCPostInvUploadResponder : public LLAssetUploadResponder +{ +public: + JCPostInvUploadResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type, LLUUID item, InventoryImportInfo* idata) : LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + item_id = item; + data = idata; + } + + JCPostInvUploadResponder(const LLSD& post_data, + const std::string& file_name, + LLAssetType::EType asset_type) : LLAssetUploadResponder(post_data, file_name, asset_type) + { + } + virtual void uploadComplete(const LLSD& content) + { + //cmdline_printchat("completed upload, inserting"); + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id); + LLViewerObject* objectp = find(data->localid); + insert(item, objectp, data); + } +private: + LLUUID item_id; + InventoryImportInfo* data; +}; + +class JCPostInvCallback : public LLInventoryCallback +{ +public: + JCPostInvCallback(InventoryImportInfo* idata) + { + data = idata; + } + void fire(const LLUUID &inv_item) + { + S32 file_size; + LLAPRFile infile ; + infile.open(data->filename, LL_APR_RB, NULL, &file_size); + if (infile.getFileHandle()) + { + //cmdline_printchat("got file handle @ postinv"); + LLVFile file(gVFS, data->assetid, data->type, LLVFile::WRITE); + file.setMaxSize(file_size); + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = infile.read(copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + switch(data->type) + { + case LLAssetType::AT_NOTECARD: + //cmdline_printchat("case notecard @ postinv"); + { + /*LLViewerTextEditor* edit = new LLViewerTextEditor("",LLRect(0,0,0,0),S32_MAX,""); + S32 size = gVFS->getSize(data->assetid, data->type); + U8* buffer = new U8[size]; + gVFS->getData(data->assetid, data->type, buffer, 0, size); + edit->setText(LLStringExplicit((char*)buffer)); + std::string card; + edit->exportBuffer(card); + cmdline_printchat("Encoded notecard");; + edit->die(); + delete buffer; + //buffer = new U8[card.size()]; + //size = card.size(); + //strcpy((char*)buffer,card.c_str()); + file.remove(); + LLVFile newfile(gVFS, data->assetid, data->type, LLVFile::APPEND); + newfile.setMaxSize(size); + newfile.write((const U8*)card.c_str(),size);*/ + //FAIL. + + + + std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory"); + LLSD body; + body["item_id"] = inv_item; + //cmdline_printchat("posting content as " + data->assetid.asString()); + LLHTTPClient::post(agent_url, body, + new JCPostInvUploadResponder(body, data->assetid, data->type,inv_item,data)); + } + break; + case LLAssetType::AT_LSL_TEXT: + //cmdline_printchat("case lsltext @ postinv"); + { + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); + LLSD body; + body["item_id"] = inv_item; + S32 size = gVFS->getSize(data->assetid, data->type); + U8* buffer = new U8[size]; + gVFS->getData(data->assetid, data->type, buffer, 0, size); + std::string script((char*)buffer); + BOOL domono = JCLSLPreprocessor::mono_directive(script); + /*if(script.find("//mono\n") != -1) + { + domono = TRUE; + }else if(script.find("//lsl2\n") != -1) + { + domono = FALSE; + }*/ + delete buffer; + buffer = 0; + body["target"] = (domono == TRUE) ? "mono" : "lsl2"; + //cmdline_printchat("posting content as " + data->assetid.asString()); + LLHTTPClient::post(url, body, new JCPostInvUploadResponder(body, data->assetid, data->type,inv_item,data)); + } + break; + default: + break; + } + } + } +private: + InventoryImportInfo* data; +}; + +void JCImportInventorycallback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ + if(result == LL_ERR_NOERR) + { + //cmdline_printchat("fired importinvcall for "+uuid.asString()); + InventoryImportInfo* data = (InventoryImportInfo*)user_data; + + LLPointer cb = new JCImportTransferCallback(data); + LLPermissions perm; + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH), data->tid, data->name, + data->description, data->type, LLInventoryType::defaultForAssetType(data->type), data->wear_type, + LLFloaterPerms::getNextOwnerPerms(), + cb); + }else cmdline_printchat("err: "+std::string(LLAssetStorage::getErrorString(result))); +} + + +void ImportTracker::send_inventory(LLSD& prim) +{ + U32 local_id = prim["LocalID"].asInteger(); + if (prim.has("inventory")) + { + std::string assetpre = asset_dir + gDirUtilp->getDirDelimiter(); + LLSD inventory = prim["inventory"]; + for (LLSD::array_iterator inv = inventory.beginArray(); inv != inventory.endArray(); ++inv) + { + LLSD item = (*inv); + InventoryImportInfo* data = new InventoryImportInfo; + data->localid = local_id; + LLTransactionID tid; + tid.generate(); + LLUUID assetid = tid.makeAssetID(gAgent.getSecureSessionID()); + data->tid = tid; + data->assetid = assetid; + data->type = LLAssetType::lookup(item["type"].asString());////LLAssetType::EType(U32(item["type"].asInteger())); + data->name = item["name"].asString(); + data->description = item["desc"].asString(); + if(item.has("item_id")) + { + //cmdline_printchat("item id found"); + std::string filename = assetpre + item["item_id"].asString() + "." + item["type"].asString(); + //S32 file_size; + //LLAPRFile infile ; + //infile.open(filename, LL_APR_RB, NULL, &file_size); + //apr_file_t* fp = infile.getFileHandle(); + //if(fp) + if(LLFile::isfile(filename)) + { + //cmdline_printchat("file "+filename+" exists"); + data->filename = filename; + //infile.close(); + }else + { + //cmdline_printchat("file "+filename+" does not exist"); + delete data; + continue; + } + }else + { + //cmdline_printchat("item id not found"); + delete data; + continue; + } + + data->wear_type = NOT_WEARABLE; + + //if(data->type == LLAssetType::AT_LSL_TEXT) + { + data->inv_type = LLInventoryType::defaultForAssetType(data->type); + //printchat("is script"); + data->compiled = false; + // + switch(data->type) + { + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_TEXTURE_TGA: + //cmdline_printchat("case textures"); + { + std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); + S32 file_size; + LLAPRFile infile ; + infile.open(data->filename, LL_APR_RB, NULL, &file_size); + if (infile.getFileHandle()) + { + //cmdline_printchat("got file handle"); + LLVFile file(gVFS, data->assetid, data->type, LLVFile::WRITE); + file.setMaxSize(file_size); + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = infile.read(copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + body["asset_type"] = LLAssetType::lookup(data->type); + body["inventory_type"] = LLInventoryType::lookup(data->inv_type); + body["name"] = data->name; + body["description"] = data->description; + body["next_owner_mask"] = LLSD::Integer(U32_MAX); + body["group_mask"] = LLSD::Integer(U32_MAX); + body["everyone_mask"] = LLSD::Integer(U32_MAX); + body["expected_upload_cost"] = LLSD::Integer(LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); + //cmdline_printchat("posting "+ data->assetid.asString()); + LLHTTPClient::post(url, body, new JCImportInventoryResponder(body, data->assetid, data->type,data)); + //error = TRUE; + } + } + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + //cmdline_printchat("case cloth/bodypart"); + { + S32 file_size; + LLAPRFile infile ; + infile.open(data->filename, LL_APR_RB, NULL, &file_size); + if (infile.getFileHandle()) + { + //cmdline_printchat("got file handle @ cloth"); + LLVFile file(gVFS, data->assetid, data->type, LLVFile::WRITE); + file.setMaxSize(file_size); + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = infile.read(copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + + LLFILE* fp = LLFile::fopen(data->filename, "rb"); + if(fp)//HACK LOL LOL LOL + { + LLWearable* wearable = new LLWearable(LLUUID::null); + wearable->importFile( fp ); + //if (!res) + { + data->wear_type = wearable->getType(); + } + delete wearable; + } + //cmdline_printchat("storing "+data->assetid.asString()); + gAssetStorage->storeAssetData(data->tid, data->type, + JCImportInventorycallback, + (void*)data, + FALSE, + TRUE, + FALSE); + } + } + break; + case LLAssetType::AT_NOTECARD: + //cmdline_printchat("case notecard"); + { + //std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory"); + LLPointer cb = new JCPostInvCallback(data); + LLPermissions perm; + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH), data->tid, data->name, + data->description, data->type, LLInventoryType::defaultForAssetType(data->type), data->wear_type, + LLFloaterPerms::getNextOwnerPerms(), + cb); + } + break; + case LLAssetType::AT_LSL_TEXT: + { + LLPointer cb = new JCPostInvCallback(data); + LLPermissions perm; + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH), data->tid, data->name, + data->description, data->type, LLInventoryType::defaultForAssetType(data->type), data->wear_type, + LLFloaterPerms::getNextOwnerPerms(), + cb); + } + break; + case LLAssetType::AT_SCRIPT://this shouldn't happen as this is legacy shit + case LLAssetType::AT_GESTURE://we don't import you atm... + default: + break; + } + asset_insertions += 1; + } + } + } +} + +void ImportTracker::send_properties(LLSD& prim, int counter) +{ + if(prim.has("properties")) + { + if(counter == 1)//root only shit + { + //prim["LocalID"] + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectPermissions); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_HeaderData); + msg->addBOOLFast(_PREHASH_Override, FALSE); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER); + msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED); + msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["next_owner_mask"].asString().c_str()))); + /*msg->sendReliable(gAgent.getRegion()->getHost()); + + //LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectPermissions); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_HeaderData); + msg->addBOOLFast(_PREHASH_Override, data->mOverride);*/ + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Field, PERM_GROUP); + msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED); + msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["group_mask"].asString().c_str()))); + /*msg->sendReliable(gAgent.getRegion()->getHost()); + + //LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectPermissions); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_HeaderData); + msg->addBOOLFast(_PREHASH_Override, data->mOverride);*/ + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Field, PERM_EVERYONE); + msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED); + msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["everyone_mask"].asString().c_str()))); + msg->sendReliable(gAgent.getRegion()->getHost()); + + msg->newMessageFast(_PREHASH_ObjectSaleInfo); + + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_LocalID, prim["LocalID"].asInteger()); + LLSaleInfo sale_info; + BOOL a; + U32 b; + sale_info.fromLLSD(prim["sale_info"],a,b); + sale_info.packMessage(msg); + msg->sendReliable(gAgent.getRegion()->getHost()); + + //no facilities exist to send any other information at this time. + } + } +} + +void ImportTracker::send_vectors(LLSD& prim,int counter) +{ + LLVector3 position = ((LLVector3)prim["position"] * rootrot) + root; + LLSD rot = prim["rotation"]; + LLQuaternion rotq; + rotq.mQ[VX] = (F32)(rot[0].asReal()); + rotq.mQ[VY] = (F32)(rot[1].asReal()); + rotq.mQ[VZ] = (F32)(rot[2].asReal()); + rotq.mQ[VW] = (F32)(rot[3].asReal()); + LLVector3 rotation; + if(counter == 1) + rotation = rotq.packToVector3(); + else + rotation = (rotq * rootrot).packToVector3(); + LLVector3 scale = prim["scale"]; + U8 data[256]; + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MultipleObjectUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Type, U8(0x01)); + htonmemcpy(&data[0], &(position.mV), MVT_LLVector3, 12); + msg->addBinaryDataFast(_PREHASH_Data, data, 12); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Type, U8(0x02)); + htonmemcpy(&data[0], &(rotation.mV), MVT_LLQuaternion, 12); + msg->addBinaryDataFast(_PREHASH_Data, data, 12); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addU8Fast(_PREHASH_Type, U8(0x04)); + htonmemcpy(&data[0], &(scale.mV), MVT_LLVector3, 12); + msg->addBinaryDataFast(_PREHASH_Data, data, 12); + + msg->sendReliable(gAgent.getRegion()->getHost()); +} + +void ImportTracker::send_shape(LLSD& prim) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectShape); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + + LLVolumeParams params; + params.fromLLSD(prim["volume"]); + LLVolumeMessage::packVolumeParams(¶ms, msg); + + msg->sendReliable(gAgent.getRegion()->getHost()); +} + +void ImportTracker::send_image(LLSD& prim) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectImage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addStringFast(_PREHASH_MediaURL, NULL); + + LLPrimitive obj; + LLSD tes = prim["textures"]; + obj.setNumTEs(U8(tes.size())); + + for (int i = 0; i < tes.size(); i++) + { + LLTextureEntry tex; + tex.fromLLSD(tes[i]); + obj.setTE(U8(i), tex); + } + + obj.packTEMessage(gMessageSystem); + + msg->sendReliable(gAgent.getRegion()->getHost()); +} +void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel); +void ImportTracker::send_extras(LLSD& prim) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectExtraParams); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + LLPrimitive obj; + + if (prim.has("flexible")) + { + LLFlexibleObjectData flexi; + flexi.fromLLSD(prim["flexible"]); + U8 tmp[MAX_OBJECT_PARAMS_SIZE]; + LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); + + if (flexi.pack(dpb)) + { + U32 datasize = (U32)dpb.getCurrentSize(); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + + msg->addU16Fast(_PREHASH_ParamType, 0x10); + msg->addBOOLFast(_PREHASH_ParamInUse, true); + + msg->addU32Fast(_PREHASH_ParamSize, datasize); + msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); + } + } + + if (prim.has("light")) + { + LLLightParams light; + light.fromLLSD(prim["light"]); + + U8 tmp[MAX_OBJECT_PARAMS_SIZE]; + LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); + + if (light.pack(dpb)) + { + U32 datasize = (U32)dpb.getCurrentSize(); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + + msg->addU16Fast(_PREHASH_ParamType, 0x20); + msg->addBOOLFast(_PREHASH_ParamInUse, true); + + msg->addU32Fast(_PREHASH_ParamSize, datasize); + msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); + } + } + + if (prim.has("sculpt")) + { + LLSculptParams sculpt; + sculpt.fromLLSD(prim["sculpt"]); + + U8 tmp[MAX_OBJECT_PARAMS_SIZE]; + LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); + + if (sculpt.pack(dpb)) + { + U32 datasize = (U32)dpb.getCurrentSize(); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + + msg->addU16Fast(_PREHASH_ParamType, 0x30); + msg->addBOOLFast(_PREHASH_ParamInUse, true); + + msg->addU32Fast(_PREHASH_ParamSize, datasize); + msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); + } + } + + msg->sendReliable(gAgent.getRegion()->getHost()); +} + +void ImportTracker::send_namedesc(LLSD& prim) +{ + if(prim.has("name")) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectName); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_LocalID, prim["LocalID"].asInteger()); + msg->addStringFast(_PREHASH_Name, prim["name"]); + + msg->sendReliable(gAgent.getRegion()->getHost()); + } + + if(prim.has("description")) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectDescription); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + LLVector3 scale = prim["scale"]; + if((scale.mV[VX] > 10.) || (scale.mV[VY] > 10.) || (scale.mV[VZ] > 10.) ) + prim["description"] = llformat("<%d, %d, %d>", (U8)scale.mV[VX], (U8)scale.mV[VY], (U8)scale.mV[VZ]); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_LocalID, prim["LocalID"].asInteger()); + msg->addStringFast(_PREHASH_Description, prim["description"]); + + msg->sendReliable(gAgent.getRegion()->getHost()); + } +} + +void ImportTracker::link() +{ + if(linkset.size() == 256) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectLink); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + LLSD::array_iterator prim = linkset.beginArray(); + ++prim; + for (; prim != linkset.endArray(); ++prim) + { + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (*prim)["LocalID"].asInteger()); + } + + msg->sendReliable(gAgent.getRegion()->getHost()); + + LLMessageSystem* msg2 = gMessageSystem; + msg2->newMessageFast(_PREHASH_ObjectLink); + msg2->nextBlockFast(_PREHASH_AgentData); + msg2->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg2->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + LLSD prim2 = linkset[0]; + msg2->nextBlockFast(_PREHASH_ObjectData); + msg2->addU32Fast(_PREHASH_ObjectLocalID, (prim2)["LocalID"].asInteger()); + prim2 = linkset[1]; + msg2->nextBlockFast(_PREHASH_ObjectData); + msg2->addU32Fast(_PREHASH_ObjectLocalID, (prim2)["LocalID"].asInteger()); + + msg2->sendReliable(gAgent.getRegion()->getHost()); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectLink); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + for (LLSD::array_iterator prim = linkset.beginArray(); prim != linkset.endArray(); ++prim) + { + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (*prim)["LocalID"].asInteger()); + } + msg->sendReliable(gAgent.getRegion()->getHost()); + } + + llinfos << "FINISHED IMPORT" << llendl; + + if (linkset[0].has("Attachment")) + { + llinfos << "OBJECT IS ATTACHMENT, WAITING FOR POSITION PACKETS.." << llendl; + state = POSITIONING; + wear(linkset[0]); + } + else + cleanUp(); +} + +void ImportTracker::wear(LLSD &prim) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectAttach); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU8Fast(_PREHASH_AttachmentPoint, U8(prim["Attachment"].asInteger())); + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg->addQuatFast(_PREHASH_Rotation, LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f)); + + msg->sendReliable(gAgent.getRegion()->getHost()); + + LLVector3 position = prim["attachpos"]; + + LLSD rot = prim["attachrot"]; + LLQuaternion rotq; + rotq.mQ[VX] = (F32)(rot[0].asReal()); + rotq.mQ[VY] = (F32)(rot[1].asReal()); + rotq.mQ[VZ] = (F32)(rot[2].asReal()); + rotq.mQ[VW] = (F32)(rot[3].asReal()); + LLVector3 rotation = rotq.packToVector3(); + U8 data[256]; + + LLMessageSystem* msg2 = gMessageSystem; + msg2->newMessageFast(_PREHASH_MultipleObjectUpdate); + msg2->nextBlockFast(_PREHASH_AgentData); + msg2->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg2->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg2->nextBlockFast(_PREHASH_ObjectData); + msg2->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg2->addU8Fast(_PREHASH_Type, U8(0x01 | 0x08)); + htonmemcpy(&data[0], &(position.mV), MVT_LLVector3, 12); + msg2->addBinaryDataFast(_PREHASH_Data, data, 12); + + msg2->nextBlockFast(_PREHASH_ObjectData); + msg2->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger()); + msg2->addU8Fast(_PREHASH_Type, U8(0x02 | 0x08)); + htonmemcpy(&data[0], &(rotation.mV), MVT_LLQuaternion, 12); + msg2->addBinaryDataFast(_PREHASH_Data, data, 12); + + msg2->sendReliable(gAgent.getRegion()->getHost()); + llinfos << "POSITIONED, IMPORT COMPLETED" << llendl; + cleanUp(); +} + +void ImportTracker::plywood_above_head() +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectAdd); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_Material, 3); + msg->addU32Fast(_PREHASH_AddFlags, FLAGS_CREATE_SELECTED); + LLVolumeParams volume_params; + volume_params.setType(0x01, 0x10); + volume_params.setBeginAndEndS(0.f, 1.f); + volume_params.setBeginAndEndT(0.f, 1.f); + volume_params.setRatio(1, 1); + volume_params.setShear(0, 0); + LLVolumeMessage::packVolumeParams(&volume_params, msg); + msg->addU8Fast(_PREHASH_PCode, 9); + msg->addVector3Fast(_PREHASH_Scale, LLVector3(0.52345f, 0.52346f, 0.52347f)); + LLQuaternion rot; + msg->addQuatFast(_PREHASH_Rotation, rot); + LLViewerRegion *region = gAgent.getRegion(); + + if (!localids.size()) + root = (initialPos + linksetoffset); + + msg->addVector3Fast(_PREHASH_RayStart, root); + msg->addVector3Fast(_PREHASH_RayEnd, root); + msg->addU8Fast(_PREHASH_BypassRaycast, (U8)TRUE ); + msg->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE ); + msg->addU8Fast(_PREHASH_State, (U8)0); + msg->addUUIDFast(_PREHASH_RayTargetID, LLUUID::null); + msg->sendReliable(region->getHost()); +} + diff --git a/indra/newview/importtracker.h b/indra/newview/importtracker.h new file mode 100644 index 000000000..c9a7fb4e5 --- /dev/null +++ b/indra/newview/importtracker.h @@ -0,0 +1,81 @@ +/** + * @file importtracker.h + * @brief A utility for importing linksets from XML. + * Discrete wuz here + */ + +#ifndef IMPORTTRACKER_H +#define IMPORTTRACKER_H + +#include "llviewerobject.h" + + + +class ImportTracker +{ + public: + enum ImportState { IDLE, WAND, BUILDING, LINKING, POSITIONING }; + + ImportTracker() + : numberExpected(0), + state(IDLE), + last(0), + groupcounter(0), + updated(0) + { } + ImportTracker(LLSD &data) { state = IDLE; linkset = data; numberExpected=0;} + ~ImportTracker() { localids.clear(); linkset.clear(); } + + //Chalice - support import of linkset groups + void importer(std::string file, void (*callback)(LLViewerObject*)); + void cleargroups(); + void import(LLSD &ls_data); + void expectRez(); + void clear(); + void finish(); + void cleanUp(); + void get_update(S32 newid, BOOL justCreated = false, BOOL createSelected = false); + + const int getState() { return state; } + + U32 asset_insertions; + + protected: + void send_inventory(LLSD &prim); + void send_properties(LLSD &prim, int counter); + void send_vectors(LLSD &prim, int counter); + void send_shape(LLSD &prim); + void send_image(LLSD &prim); + void send_extras(LLSD &prim); + void send_namedesc(LLSD &prim); + void link(); + void wear(LLSD &prim); + void position(LLSD &prim); + void plywood_above_head(); + + private: + int numberExpected; + int state; + S32 last; + LLVector3 root; + LLQuaternion rootrot; + std::list localids; + LLSD linksetgroups; + int groupcounter; + int updated; + LLVector3 linksetoffset; + LLVector3 initialPos; + LLSD linkset; + + std::string filepath; + std::string asset_dir; + void (*mDownCallback)(LLViewerObject*); + + U32 lastrootid; +}; + +extern ImportTracker gImportTracker; + +//extern LLAgent gAgent; + +#endif diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index fd053d02d..0108f0058 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -61,15 +61,9 @@ fi ## you're building your own viewer, bear in mind that the executable ## in the bin directory will be stripped: you should replace it with ## an unstripped binary before you run. -## -## I keep crashing without having GDB running, always run it if an -## environment variable is set. - -if [ $INERT_DEVELOPER -eq 1 ]; then -# export LL_WRAPPER='cgdb --args' - export LL_WRAPPER='gdb --args' -# export LL_WRAPPER='valgrind --smc-check=all --error-limit=no --log-file=secondlife.vg --leak-check=full --suppressions=/usr/lib/valgrind/glibc-2.5.supp --suppressions=secondlife-i686.supp' -fi +#export LL_WRAPPER='cgdb --args' +#export LL_WRAPPER='gdb --args' +#export LL_WRAPPER='valgrind --smc-check=all --error-limit=no --log-file=secondlife.vg --leak-check=full --suppressions=/usr/lib/valgrind/glibc-2.5.supp --suppressions=secondlife-i686.supp' ## - Avoids an often-buggy X feature that doesn't really benefit us anyway. export SDL_VIDEO_X11_DGAMOUSE=0 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 76602eb0d..6bb93479f 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1,8126 +1,8170 @@ -/** - * @file llagent.cpp - * @brief LLAgent class implementation - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "stdtypes.h" -#include "stdenums.h" - -#include "llagent.h" - -#include "llcamera.h" -#include "llcoordframe.h" -#include "indra_constants.h" -#include "llmath.h" -#include "llcriticaldamp.h" -#include "llfocusmgr.h" -#include "llglheaders.h" -#include "llparcel.h" -#include "llpermissions.h" -#include "llregionhandle.h" -#include "m3math.h" -#include "m4math.h" -#include "message.h" -#include "llquaternion.h" -#include "v3math.h" -#include "v4math.h" -#include "llsmoothstep.h" -#include "llsdutil.h" -//#include "vmath.h" - -#include "imageids.h" -#include "llbox.h" -#include "llbutton.h" -#include "llcallingcard.h" -#include "llchatbar.h" -#include "llconsole.h" -#include "lldrawable.h" -#include "llface.h" -#include "llfirstuse.h" -#include "llfloater.h" -#include "llfloateractivespeakers.h" -#include "llfloateravatarinfo.h" -#include "llfloaterbuildoptions.h" -#include "llfloatercamera.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfloaterdirectory.h" -#include "llfloatergroupinfo.h" -#include "llfloatergroups.h" -#include "llfloaterland.h" -#include "llfloatermap.h" -#include "llfloatermute.h" -#include "llfloatersnapshot.h" -#include "llfloatertools.h" -#include "llfloaterworldmap.h" -#include "llgroupmgr.h" -#include "llhomelocationresponder.h" -#include "llhudeffectlookat.h" -#include "llhudmanager.h" -#include "llinventorymodel.h" -#include "llinventoryview.h" -#include "lljoystickbutton.h" -#include "llmenugl.h" -#include "llmorphview.h" -#include "llmoveview.h" -#include "llnotify.h" -#include "llquantize.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llsky.h" -#include "llrendersphere.h" -#include "llstatusbar.h" -#include "llstartup.h" -#include "llimview.h" -#include "lltexturestats.h" -#include "lltool.h" -#include "lltoolcomp.h" -#include "lltoolfocus.h" -#include "lltoolgrab.h" -#include "lltoolmgr.h" -#include "lltoolpie.h" -#include "lltoolview.h" -#include "llui.h" // for make_ui_sound -#include "llurldispatcher.h" -#include "llviewercamera.h" -#include "llviewerinventory.h" -#include "llviewermediafocus.h" -#include "llviewermenu.h" -#include "llviewernetwork.h" -#include "llviewerobjectlist.h" -#include "llviewerparcelmgr.h" -#include "llviewerparceloverlay.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llviewerdisplay.h" -#include "llvoavatar.h" -#include "llvoground.h" -#include "llvosky.h" -#include "llwearable.h" -#include "llwearablelist.h" -#include "llworld.h" -#include "llworldmap.h" -#include "pipeline.h" -#include "roles_constants.h" -#include "llviewercontrol.h" -#include "llappviewer.h" -#include "llviewerjoystick.h" -#include "llfollowcam.h" -// -#include "llao.h" -#include "llworldmapmessage.h" -// -using namespace LLVOAvatarDefines; - -extern LLMenuBarGL* gMenuBarView; - -//drone wandering constants -const F32 MAX_WANDER_TIME = 20.f; // seconds -const F32 MAX_HEADING_HALF_ERROR = 0.2f; // radians -const F32 WANDER_MAX_SLEW_RATE = 2.f * DEG_TO_RAD; // radians / frame -const F32 WANDER_TARGET_MIN_DISTANCE = 10.f; // meters - -// Autopilot constants -const F32 AUTOPILOT_HEADING_HALF_ERROR = 10.f * DEG_TO_RAD; // radians -const F32 AUTOPILOT_MAX_SLEW_RATE = 1.f * DEG_TO_RAD; // radians / frame -const F32 AUTOPILOT_STOP_DISTANCE = 2.f; // meters -const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f; // meters -const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters -const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f; // seconds - -// face editing constants -const LLVector3d FACE_EDIT_CAMERA_OFFSET(0.4f, -0.05f, 0.07f); -const LLVector3d FACE_EDIT_TARGET_OFFSET(0.f, 0.f, 0.05f); - -// Mousewheel camera zoom -const F32 MIN_ZOOM_FRACTION = 0.25f; -const F32 INITIAL_ZOOM_FRACTION = 1.f; -const F32 MAX_ZOOM_FRACTION = 8.f; -const F32 METERS_PER_WHEEL_CLICK = 1.f; - -const F32 MAX_TIME_DELTA = 1.f; - -const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds -const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds - -const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f; -const F32 CAMERA_LAG_HALF_LIFE = 0.25f; -const F32 MIN_CAMERA_LAG = 0.5f; -const F32 MAX_CAMERA_LAG = 5.f; - -const F32 CAMERA_COLLIDE_EPSILON = 0.1f; -const F32 MIN_CAMERA_DISTANCE = 0.1f; -const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.55f; -const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.7f; -const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 1.15f; - -const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f; - -const F32 MAX_CAMERA_SMOOTH_DISTANCE = 50.0f; - -const F32 HEAD_BUFFER_SIZE = 0.3f; -const F32 CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP = 0.2f; - -const F32 LAND_MIN_ZOOM = 0.15f; -const F32 AVATAR_MIN_ZOOM = 0.5f; -const F32 OBJECT_MIN_ZOOM = 0.02f; - -const F32 APPEARANCE_MIN_ZOOM = 0.39f; -const F32 APPEARANCE_MAX_ZOOM = 8.f; - -// fidget constants -const F32 MIN_FIDGET_TIME = 8.f; // seconds -const F32 MAX_FIDGET_TIME = 20.f; // seconds - -const S32 MAX_NUM_CHAT_POSITIONS = 10; -const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f; -const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f; - -const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f; - -const F32 MAX_FOCUS_OFFSET = 20.f; - -const F32 OBJECT_EXTENTS_PADDING = 0.5f; - -const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f; - -const F64 CHAT_AGE_FAST_RATE = 3.0; - -// The agent instance. -LLAgent gAgent; -// -LLUUID gReSitTargetID; -LLVector3 gReSitOffset; -// -// -// Statics -// - -// -// For MapBlockReply funk 'cause I dunno what I'm doing -BOOL LLAgent::lure_show = FALSE; -std::string LLAgent::lure_name; -LLVector3d LLAgent::lure_posglobal; -U16 LLAgent::lure_global_x; -U16 LLAgent::lure_global_y; -int LLAgent::lure_x; -int LLAgent::lure_y; -int LLAgent::lure_z; -std::string LLAgent::lure_maturity; - -// - -const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; - -std::map LLAgent::sTeleportErrorMessages; -std::map LLAgent::sTeleportProgressMessages; - -class LLAgentFriendObserver : public LLFriendObserver -{ -public: - LLAgentFriendObserver() {} - virtual ~LLAgentFriendObserver() {} - virtual void changed(U32 mask); -}; - -void LLAgentFriendObserver::changed(U32 mask) -{ - // if there's a change we're interested in. - if((mask & (LLFriendObserver::POWERS)) != 0) - { - gAgent.friendsChanged(); - } -} - -// ************************************************************ -// Enabled this definition to compile a 'hacked' viewer that -// locally believes the end user has godlike powers. -// #define HACKED_GODLIKE_VIEWER -// For a toggled version, see viewer.h for the -// TOGGLE_HACKED_GODLIKE_VIEWER define, instead. -// ************************************************************ - -// Constructors and Destructors - -// JC - Please try to make this order match the order in the header -// file. Otherwise it's hard to find variables that aren't initialized. -//----------------------------------------------------------------------------- -// LLAgent() -//----------------------------------------------------------------------------- -LLAgent::LLAgent() : - mDrawDistance( DEFAULT_FAR_PLANE ), - - mGroupPowers(0), - mHideGroupTitle(FALSE), - mGroupID(), - - mMapOriginX(0.F), - mMapOriginY(0.F), - mMapWidth(0), - mMapHeight(0), - - mLookAt(NULL), - mPointAt(NULL), - - mHUDTargetZoom(1.f), - mHUDCurZoom(1.f), - mInitialized(FALSE), - mNumPendingQueries(0), - mActiveCacheQueries(NULL), - mForceMouselook(FALSE), - - mDoubleTapRunTimer(), - mDoubleTapRunMode(DOUBLETAP_NONE), - - mbAlwaysRun(false), - mbRunning(false), - - mAgentAccess(gSavedSettings), - mTeleportState( TELEPORT_NONE ), - mRegionp(NULL), - - mAgentOriginGlobal(), - mPositionGlobal(), - - mDistanceTraveled(0.F), - mLastPositionGlobal(LLVector3d::zero), - - mAvatarObject(NULL), - - mRenderState(0), - mTypingTimer(), - - mCameraMode( CAMERA_MODE_THIRD_PERSON ), - mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), - mViewsPushed(FALSE), - - mCustomAnim(FALSE), - mShowAvatar(TRUE), - mCameraAnimating( FALSE ), - mAnimationCameraStartGlobal(), - mAnimationFocusStartGlobal(), - mAnimationTimer(), - mAnimationDuration(0.33f), - - mCameraFOVZoomFactor(0.f), - mCameraCurrentFOVZoomFactor(0.f), - mCameraFocusOffset(), - mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW), - - mCameraOffsetDefault(), - mCameraCollidePlane(), - - mCurrentCameraDistance(2.f), // meters, set in init() - mTargetCameraDistance(2.f), - mCameraZoomFraction(1.f), // deprecated - mThirdPersonHeadOffset(0.f, 0.f, 1.f), - mSitCameraEnabled(FALSE), - mCameraSmoothingLastPositionGlobal(), - mCameraSmoothingLastPositionAgent(), - mCameraSmoothingStop(FALSE), - - mCameraUpVector(LLVector3::z_axis), // default is straight up - - mFocusOnAvatar(TRUE), - mFocusGlobal(), - mFocusTargetGlobal(), - mFocusObject(NULL), - mFocusObjectDist(0.f), - mFocusObjectOffset(), - mFocusDotRadius( 0.1f ), // meters - mTrackFocusObject(TRUE), - mUIOffset(0.f), - - mFrameAgent(), - - mIsBusy(FALSE), - - mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed - mWalkKey(0), // like AtKey, but causes less forward thrust - mLeftKey(0), - mUpKey(0), - mYawKey(0.f), - mPitchKey(0), - - mOrbitLeftKey(0.f), - mOrbitRightKey(0.f), - mOrbitUpKey(0.f), - mOrbitDownKey(0.f), - mOrbitInKey(0.f), - mOrbitOutKey(0.f), - - mPanUpKey(0.f), - mPanDownKey(0.f), - mPanLeftKey(0.f), - mPanRightKey(0.f), - mPanInKey(0.f), - mPanOutKey(0.f), - - mControlFlags(0x00000000), - mbFlagsDirty(FALSE), - mbFlagsNeedReset(FALSE), - - mbJump(FALSE), - - mAutoPilot(FALSE), - mAutoPilotFlyOnStop(FALSE), - mAutoPilotTargetGlobal(), - mAutoPilotStopDistance(1.f), - mAutoPilotUseRotation(FALSE), - mAutoPilotTargetFacing(LLVector3::zero), - mAutoPilotTargetDist(0.f), - mAutoPilotNoProgressFrameCount(0), - mAutoPilotRotationThreshold(0.f), - mAutoPilotFinishedCallback(NULL), - mAutoPilotCallbackData(NULL), - - mCapabilities(), - - mEffectColor(0.f, 1.f, 1.f, 1.f), - - mHaveHomePosition(FALSE), - mHomeRegionHandle( 0 ), - mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f), - - mNextFidgetTime(0.f), - mCurrentFidget(0), - mFirstLogin(FALSE), - mGenderChosen(FALSE), - - mAgentWearablesUpdateSerialNum(0), - mWearablesLoaded(FALSE), - mTextureCacheQueryID(0), - mAppearanceSerialNum(0), - mbTeleportKeepsLookAt(false) -{ - U32 i; - for (i = 0; i < TOTAL_CONTROLS; i++) - { - mControlsTakenCount[i] = 0; - mControlsTakenPassedOnCount[i] = 0; - } - - mActiveCacheQueries = new S32[BAKED_NUM_INDICES]; - for (i = 0; i < (U32)BAKED_NUM_INDICES; i++) - { - mActiveCacheQueries[i] = 0; - } - - mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); -} - -// Requires gSavedSettings to be initialized. -//----------------------------------------------------------------------------- -// init() -//----------------------------------------------------------------------------- -void LLAgent::init() -{ - mDrawDistance = gSavedSettings.getF32("RenderFarClip"); - - // *Note: this is where LLViewerCamera::getInstance() used to be constructed. - - LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); - // Leave at 0.1 meters until we have real near clip management - LLViewerCamera::getInstance()->setNear(0.1f); - LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h - LLViewerCamera::getInstance()->setAspect( gViewerWindow->getDisplayAspectRatio() ); // default, overridden in LLViewerWindow::reshape - LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape - - setFlying( gSavedSettings.getBOOL("FlyingAtExit") ); - - mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); - mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault"); - mCameraCollidePlane.clearVec(); - mCurrentCameraDistance = mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"); - mTargetCameraDistance = mCurrentCameraDistance; - mCameraZoomFraction = 1.f; - mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); - -// LLDebugVarMessageBox::show("Camera Lag", &CAMERA_FOCUS_HALF_LIFE, 0.5f, 0.01f); - - mEffectColor = gSavedSettings.getColor4("EffectColor"); - - mInitialized = TRUE; -} - -//----------------------------------------------------------------------------- -// cleanup() -//----------------------------------------------------------------------------- -void LLAgent::cleanup() -{ - setSitCamera(LLUUID::null); - mAvatarObject = NULL; - if(mLookAt) - { - mLookAt->markDead() ; - mLookAt = NULL; - } - if(mPointAt) - { - mPointAt->markDead() ; - mPointAt = NULL; - } - mRegionp = NULL; - setFocusObject(NULL); -} - -//----------------------------------------------------------------------------- -// LLAgent() -//----------------------------------------------------------------------------- -LLAgent::~LLAgent() -{ - cleanup(); - - delete [] mActiveCacheQueries; - mActiveCacheQueries = NULL; - - // *Note: this is where LLViewerCamera::getInstance() used to be deleted. -} - -// Change camera back to third person, stop the autopilot, -// deselect stuff, etc. -//----------------------------------------------------------------------------- -// resetView() -//----------------------------------------------------------------------------- -void LLAgent::resetView(BOOL reset_camera, BOOL change_camera) -{ - if (mAutoPilot) - { - stopAutoPilot(TRUE); - } - - if (!gNoRender) - { - LLSelectMgr::getInstance()->unhighlightAll(); - - // By popular request, keep land selection while walking around. JC - // LLViewerParcelMgr::getInstance()->deselectLand(); - - // force deselect when walking and attachment is selected - // this is so people don't wig out when their avatar moves without animating - if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - // Hide all popup menus - gMenuHolder->hideMenus(); - } - - if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) - { - changeCameraToDefault(); - - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - handle_toggle_flycam(); - } - - // reset avatar mode from eventual residual motion - if (LLToolMgr::getInstance()->inBuildMode()) - { - LLViewerJoystick::getInstance()->moveAvatar(true); - } - - gFloaterTools->close(); - - gViewerWindow->showCursor(); - - // Switch back to basic toolset - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - - if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) - { - if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) - { - // leaving mouse-steer mode - LLVector3 agent_at_axis = getAtAxis(); - agent_at_axis -= projected_vec(agent_at_axis, getReferenceUpVector()); - agent_at_axis.normalize(); - gAgent.resetAxes(lerp(getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f))); - } - - setFocusOnAvatar(TRUE, ANIMATE); - } - - mHUDTargetZoom = 1.f; -} - -// Handle any actions that need to be performed when the main app gains focus -// (such as through alt-tab). -//----------------------------------------------------------------------------- -// onAppFocusGained() -//----------------------------------------------------------------------------- -void LLAgent::onAppFocusGained() -{ - if (CAMERA_MODE_MOUSELOOK == mCameraMode) - { - changeCameraToDefault(); - LLToolMgr::getInstance()->clearSavedTool(); - } -} - - -void LLAgent::ageChat() -{ - if (mAvatarObject.notNull()) - { - // get amount of time since I last chatted - F64 elapsed_time = (F64)mAvatarObject->mChatTimer.getElapsedTimeF32(); - // add in frame time * 3 (so it ages 4x) - mAvatarObject->mChatTimer.setAge(elapsed_time + (F64)gFrameDTClamped * (CHAT_AGE_FAST_RATE - 1.0)); - } -} - -// Allow camera to be moved somewhere other than behind avatar. -//----------------------------------------------------------------------------- -// unlockView() -//----------------------------------------------------------------------------- -void LLAgent::unlockView() -{ - if (getFocusOnAvatar()) - { - if (mAvatarObject.notNull()) - { - setFocusGlobal( LLVector3d::zero, mAvatarObject->mID ); - } - setFocusOnAvatar(FALSE, FALSE); // no animation - } -} - - -//----------------------------------------------------------------------------- -// moveAt() -//----------------------------------------------------------------------------- -void LLAgent::moveAt(S32 direction, bool reset) -{ - // age chat timer so it fades more quickly when you are intentionally moving - ageChat(); - - setKey(direction, mAtKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT); - } - - if (reset) - { - resetView(); - } -} - -//----------------------------------------------------------------------------- -// moveAtNudge() -//----------------------------------------------------------------------------- -void LLAgent::moveAtNudge(S32 direction) -{ - // age chat timer so it fades more quickly when you are intentionally moving - ageChat(); - - setKey(direction, mWalkKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_NUDGE_AT_POS); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG); - } - - resetView(); -} - -//----------------------------------------------------------------------------- -// moveLeft() -//----------------------------------------------------------------------------- -void LLAgent::moveLeft(S32 direction) -{ - // age chat timer so it fades more quickly when you are intentionally moving - ageChat(); - - setKey(direction, mLeftKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT); - } - - resetView(); -} - -//----------------------------------------------------------------------------- -// moveLeftNudge() -//----------------------------------------------------------------------------- -void LLAgent::moveLeftNudge(S32 direction) -{ - // age chat timer so it fades more quickly when you are intentionally moving - ageChat(); - - setKey(direction, mLeftKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_NUDGE_LEFT_POS); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG); - } - - resetView(); -} - -//----------------------------------------------------------------------------- -// moveUp() -//----------------------------------------------------------------------------- -void LLAgent::moveUp(S32 direction) -{ - // age chat timer so it fades more quickly when you are intentionally moving - ageChat(); - - setKey(direction, mUpKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP); - } - - resetView(); -} - -//----------------------------------------------------------------------------- -// moveYaw() -//----------------------------------------------------------------------------- -void LLAgent::moveYaw(F32 mag, bool reset_view) -{ - mYawKey = mag; - - if (mag > 0) - { - setControlFlags(AGENT_CONTROL_YAW_POS); - } - else if (mag < 0) - { - setControlFlags(AGENT_CONTROL_YAW_NEG); - } - - if (reset_view) - { - resetView(); - } -} - -//----------------------------------------------------------------------------- -// movePitch() -//----------------------------------------------------------------------------- -void LLAgent::movePitch(S32 direction) -{ - setKey(direction, mPitchKey); - - if (direction > 0) - { - setControlFlags(AGENT_CONTROL_PITCH_POS ); - } - else if (direction < 0) - { - setControlFlags(AGENT_CONTROL_PITCH_NEG); - } -} - - -// Does this parcel allow you to fly? -BOOL LLAgent::canFly() -{ - if (isGodlike()) return TRUE; - - // - if(gSavedSettings.getBOOL("AlwaysAllowFly")) return TRUE; - // - - LLViewerRegion* regionp = getRegion(); - if (regionp && regionp->getBlockFly()) return FALSE; - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!parcel) return FALSE; - - // Allow owners to fly on their own land. - if (LLViewerParcelMgr::isParcelOwnedByAgent(parcel, GP_LAND_ALLOW_FLY)) - { - return TRUE; - } - - return parcel->getAllowFly(); -} - - -//----------------------------------------------------------------------------- -// setFlying() -//----------------------------------------------------------------------------- -void LLAgent::setFlying(BOOL fly) -{ - if (mAvatarObject.notNull()) - { - if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) - { - return; - } - - // don't allow taking off while sitting - if (fly && mAvatarObject->mIsSitting) - { - return; - } - } - - if (fly) - { - BOOL was_flying = getFlying(); - if (!canFly() && !was_flying) - { - // parcel doesn't let you start fly - // gods can always fly - // and it's OK if you're already flying - make_ui_sound("UISndBadKeystroke"); - return; - } - if( !was_flying ) - { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT); - } - setControlFlags(AGENT_CONTROL_FLY); - gSavedSettings.setBOOL("FlyBtnState", TRUE); - } - else - { - clearControlFlags(AGENT_CONTROL_FLY); - gSavedSettings.setBOOL("FlyBtnState", FALSE); - } - mbFlagsDirty = TRUE; -} - - -// UI based mechanism of setting fly state -//----------------------------------------------------------------------------- -// toggleFlying() -//----------------------------------------------------------------------------- -void LLAgent::toggleFlying() -{ - BOOL fly = !(mControlFlags & AGENT_CONTROL_FLY); - - setFlying( fly ); - resetView(); -} - - -//----------------------------------------------------------------------------- -// setRegion() -//----------------------------------------------------------------------------- -void LLAgent::setRegion(LLViewerRegion *regionp) -{ - llassert(regionp); - if (mRegionp != regionp) - { - // std::string host_name; - // host_name = regionp->getHost().getHostName(); - - std::string ip = regionp->getHost().getString(); - llinfos << "Moving agent into region: " << regionp->getName() - << " located at " << ip << llendl; - if (mRegionp) - { - // We've changed regions, we're now going to change our agent coordinate frame. - mAgentOriginGlobal = regionp->getOriginGlobal(); - LLVector3d agent_offset_global = mRegionp->getOriginGlobal(); - - LLVector3 delta; - delta.setVec(regionp->getOriginGlobal() - mRegionp->getOriginGlobal()); - - setPositionAgent(getPositionAgent() - delta); - - LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin(); - LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta); - - // Update all of the regions. - LLWorld::getInstance()->updateAgentOffset(agent_offset_global); - - // Hack to keep sky in the agent's region, otherwise it may get deleted - DJS 08/02/02 - // *TODO: possibly refactor into gSky->setAgentRegion(regionp)? -Brad - if (gSky.mVOSkyp) - { - gSky.mVOSkyp->setRegion(regionp); - } - if (gSky.mVOGroundp) - { - gSky.mVOGroundp->setRegion(regionp); - } - - } - else - { - // First time initialization. - // We've changed regions, we're now going to change our agent coordinate frame. - mAgentOriginGlobal = regionp->getOriginGlobal(); - - LLVector3 delta; - delta.setVec(regionp->getOriginGlobal()); - - setPositionAgent(getPositionAgent() - delta); - LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin(); - LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta); - - // Update all of the regions. - LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal); - } - } - mRegionp = regionp; - - // Must shift hole-covering water object locations because local - // coordinate frame changed. - LLWorld::getInstance()->updateWaterObjects(); - - // keep a list of regions we've been too - // this is just an interesting stat, logged at the dataserver - // we could trake this at the dataserver side, but that's harder - U64 handle = regionp->getHandle(); - mRegionsVisited.insert(handle); - - LLSelectMgr::getInstance()->updateSelectionCenter(); -} - - -//----------------------------------------------------------------------------- -// getRegion() -//----------------------------------------------------------------------------- -LLViewerRegion *LLAgent::getRegion() const -{ - return mRegionp; -} - - -const LLHost& LLAgent::getRegionHost() const -{ - if (mRegionp) - { - return mRegionp->getHost(); - } - else - { - return LLHost::invalid; - } -} - -//----------------------------------------------------------------------------- -// getSLURL() -// returns empty() if getRegion() == NULL -//----------------------------------------------------------------------------- -std::string LLAgent::getSLURL() const -{ - std::string slurl; - LLViewerRegion *regionp = getRegion(); - if (regionp) - { - LLVector3d agentPos = getPositionGlobal(); - S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) ); - S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); - S32 z = llround( (F32)agentPos.mdV[VZ] ); - slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z); - } - return slurl; -} - -//----------------------------------------------------------------------------- -// inPrelude() -//----------------------------------------------------------------------------- -BOOL LLAgent::inPrelude() -{ - return mRegionp && mRegionp->isPrelude(); -} - - -//----------------------------------------------------------------------------- -// canManageEstate() -//----------------------------------------------------------------------------- - -BOOL LLAgent::canManageEstate() const -{ - return mRegionp && mRegionp->canManageEstate(); -} - -//----------------------------------------------------------------------------- -// sendMessage() -//----------------------------------------------------------------------------- -void LLAgent::sendMessage() -{ - if (gDisconnected) - { - llwarns << "Trying to send message when disconnected!" << llendl; - return; - } - if (!mRegionp) - { - llerrs << "No region for agent yet!" << llendl; - } - gMessageSystem->sendMessage(mRegionp->getHost()); -} - - -//----------------------------------------------------------------------------- -// sendReliableMessage() -//----------------------------------------------------------------------------- -void LLAgent::sendReliableMessage() -{ - if (gDisconnected) - { - lldebugs << "Trying to send message when disconnected!" << llendl; - return; - } - if (!mRegionp) - { - lldebugs << "LLAgent::sendReliableMessage No region for agent yet, not sending message!" << llendl; - return; - } - gMessageSystem->sendReliable(mRegionp->getHost()); -} - -//----------------------------------------------------------------------------- -// getVelocity() -//----------------------------------------------------------------------------- -LLVector3 LLAgent::getVelocity() const -{ - if (mAvatarObject.notNull()) - { - return mAvatarObject->getVelocity(); - } - else - { - return LLVector3::zero; - } -} - - -//----------------------------------------------------------------------------- -// setPositionAgent() -//----------------------------------------------------------------------------- -void LLAgent::setPositionAgent(const LLVector3 &pos_agent) -{ - if (!pos_agent.isFinite()) - { - llerrs << "setPositionAgent is not a number" << llendl; - } - - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLVector3 pos_agent_sitting; - LLVector3d pos_agent_d; - LLViewerObject *parent = (LLViewerObject*)mAvatarObject->getParent(); - - pos_agent_sitting = mAvatarObject->getPosition() * parent->getRotation() + parent->getPositionAgent(); - pos_agent_d.setVec(pos_agent_sitting); - - mFrameAgent.setOrigin(pos_agent_sitting); - mPositionGlobal = pos_agent_d + mAgentOriginGlobal; - } - else - { - mFrameAgent.setOrigin(pos_agent); - - LLVector3d pos_agent_d; - pos_agent_d.setVec(pos_agent); - mPositionGlobal = pos_agent_d + mAgentOriginGlobal; - } -} - -//----------------------------------------------------------------------------- -// slamLookAt() -//----------------------------------------------------------------------------- -void LLAgent::slamLookAt(const LLVector3 &look_at) -{ - LLVector3 look_at_norm = look_at; - look_at_norm.mV[VZ] = 0.f; - look_at_norm.normalize(); - resetAxes(look_at_norm); -} - -//----------------------------------------------------------------------------- -// getPositionGlobal() -//----------------------------------------------------------------------------- -const LLVector3d &LLAgent::getPositionGlobal() const -{ - if (mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull()) - { - mPositionGlobal = getPosGlobalFromAgent(mAvatarObject->getRenderPosition()); - } - else - { - mPositionGlobal = getPosGlobalFromAgent(mFrameAgent.getOrigin()); - } - - return mPositionGlobal; -} - -//----------------------------------------------------------------------------- -// getPositionAgent() -//----------------------------------------------------------------------------- -const LLVector3 &LLAgent::getPositionAgent() -{ - if(mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull()) - { - mFrameAgent.setOrigin(mAvatarObject->getRenderPosition()); - } - - return mFrameAgent.getOrigin(); -} - -//----------------------------------------------------------------------------- -// getRegionsVisited() -//----------------------------------------------------------------------------- -S32 LLAgent::getRegionsVisited() const -{ - return mRegionsVisited.size(); -} - -//----------------------------------------------------------------------------- -// getDistanceTraveled() -//----------------------------------------------------------------------------- -F64 LLAgent::getDistanceTraveled() const -{ - return mDistanceTraveled; -} - - -//----------------------------------------------------------------------------- -// getPosAgentFromGlobal() -//----------------------------------------------------------------------------- -LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const -{ - LLVector3 pos_agent; - pos_agent.setVec(pos_global - mAgentOriginGlobal); - return pos_agent; -} - - -//----------------------------------------------------------------------------- -// getPosGlobalFromAgent() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const -{ - LLVector3d pos_agent_d; - pos_agent_d.setVec(pos_agent); - return pos_agent_d + mAgentOriginGlobal; -} - - -//----------------------------------------------------------------------------- -// resetAxes() -//----------------------------------------------------------------------------- -void LLAgent::resetAxes() -{ - mFrameAgent.resetAxes(); -} - - -// Copied from LLCamera::setOriginAndLookAt -// Look_at must be unit vector -//----------------------------------------------------------------------------- -// resetAxes() -//----------------------------------------------------------------------------- -void LLAgent::resetAxes(const LLVector3 &look_at) -{ - LLVector3 skyward = getReferenceUpVector(); - - // if look_at has zero length, fail - // if look_at and skyward are parallel, fail - // - // Test both of these conditions with a cross product. - LLVector3 cross(look_at % skyward); - if (cross.isNull()) - { - llinfos << "LLAgent::resetAxes cross-product is zero" << llendl; - return; - } - - // Make sure look_at and skyward are not parallel - // and neither are zero length - LLVector3 left(skyward % look_at); - LLVector3 up(look_at % left); - - mFrameAgent.setAxes(look_at, left, up); -} - - -//----------------------------------------------------------------------------- -// rotate() -//----------------------------------------------------------------------------- -void LLAgent::rotate(F32 angle, const LLVector3 &axis) -{ - mFrameAgent.rotate(angle, axis); -} - - -//----------------------------------------------------------------------------- -// rotate() -//----------------------------------------------------------------------------- -void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z) -{ - mFrameAgent.rotate(angle, x, y, z); -} - - -//----------------------------------------------------------------------------- -// rotate() -//----------------------------------------------------------------------------- -void LLAgent::rotate(const LLMatrix3 &matrix) -{ - mFrameAgent.rotate(matrix); -} - - -//----------------------------------------------------------------------------- -// rotate() -//----------------------------------------------------------------------------- -void LLAgent::rotate(const LLQuaternion &quaternion) -{ - mFrameAgent.rotate(quaternion); -} - - -//----------------------------------------------------------------------------- -// getReferenceUpVector() -//----------------------------------------------------------------------------- -LLVector3 LLAgent::getReferenceUpVector() -{ - // this vector is in the coordinate frame of the avatar's parent object, or the world if none - LLVector3 up_vector = LLVector3::z_axis; - if (mAvatarObject.notNull() && - mAvatarObject->getParent() && - mAvatarObject->mDrawable.notNull()) - { - U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; - // and in third person... - if (camera_mode == CAMERA_MODE_THIRD_PERSON) - { - // make the up vector point to the absolute +z axis - up_vector = up_vector * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - } - else if (camera_mode == CAMERA_MODE_MOUSELOOK) - { - // make the up vector point to the avatar's +z axis - up_vector = up_vector * mAvatarObject->mDrawable->getRotation(); - } - } - - return up_vector; -} - - -// Radians, positive is forward into ground -//----------------------------------------------------------------------------- -// pitch() -//----------------------------------------------------------------------------- -void LLAgent::pitch(F32 angle) -{ - // don't let user pitch if pointed almost all the way down or up - mFrameAgent.pitch(clampPitchToLimits(angle)); -} - - -// Radians, positive is forward into ground -//----------------------------------------------------------------------------- -// clampPitchToLimits() -//----------------------------------------------------------------------------- -F32 LLAgent::clampPitchToLimits(F32 angle) -{ - // A dot B = mag(A) * mag(B) * cos(angle between A and B) - // so... cos(angle between A and B) = A dot B / mag(A) / mag(B) - // = A dot B for unit vectors - - LLVector3 skyward = getReferenceUpVector(); - - F32 look_down_limit; - F32 look_up_limit = 10.f * DEG_TO_RAD; - - F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward ); - - if (mAvatarObject.notNull() && mAvatarObject->mIsSitting) - { - look_down_limit = 130.f * DEG_TO_RAD; - } - else - { - look_down_limit = 170.f * DEG_TO_RAD; - } - - // clamp pitch to limits - if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit)) - { - angle = look_down_limit - angle_from_skyward; - } - else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit)) - { - angle = look_up_limit - angle_from_skyward; - } - - return angle; -} - - -//----------------------------------------------------------------------------- -// roll() -//----------------------------------------------------------------------------- -void LLAgent::roll(F32 angle) -{ - mFrameAgent.roll(angle); -} - - -//----------------------------------------------------------------------------- -// yaw() -//----------------------------------------------------------------------------- -void LLAgent::yaw(F32 angle) -{ - if (!rotateGrabbed()) - { - mFrameAgent.rotate(angle, getReferenceUpVector()); - } -} - - -// Returns a quat that represents the rotation of the agent in the absolute frame -//----------------------------------------------------------------------------- -// getQuat() -//----------------------------------------------------------------------------- -LLQuaternion LLAgent::getQuat() const -{ - return mFrameAgent.getQuaternion(); -} - - -//----------------------------------------------------------------------------- -// calcFocusOffset() -//----------------------------------------------------------------------------- -LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y) -{ - LLMatrix4 obj_matrix = object->getRenderMatrix(); - LLQuaternion obj_rot = object->getRenderRotation(); - LLVector3 obj_pos = object->getRenderPosition(); - - BOOL is_avatar = object->isAvatar(); - // if is avatar - don't do any funk heuristics to position the focal point - // see DEV-30589 - if (is_avatar) - { - return original_focus_point - obj_pos; - } - - - LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation - LLVector3 object_extents = object->getScale(); - // make sure they object extents are non-zero - object_extents.clamp(0.001f, F32_MAX); - - // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object - LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); - obj_to_cam_ray.rotVec(inv_obj_rot); - obj_to_cam_ray.normalize(); - - // obj_to_cam_ray_proportions are the (positive) ratios of - // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. - LLVector3 obj_to_cam_ray_proportions; - obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); - obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); - obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); - - // find the largest ratio stored in obj_to_cam_ray_proportions - // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera - LLVector3 longest_object_axis; - // is x-axis longest? - if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY] - && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) - { - // then grab it - longest_object_axis.setVec(obj_matrix.getFwdRow4()); - } - // is y-axis longest? - else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) - { - // then grab it - longest_object_axis.setVec(obj_matrix.getLeftRow4()); - } - // otherwise, use z axis - else - { - longest_object_axis.setVec(obj_matrix.getUpRow4()); - } - - // Use this axis as the normal to project mouse click on to plane with that normal, at the object center. - // This generates a point behind the mouse cursor that is approximately in the middle of the object in - // terms of depth. - // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. - // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable - // eccentricity to the object orientation - LLVector3 focus_plane_normal(longest_object_axis); - focus_plane_normal.normalize(); - - LLVector3d focus_pt_global; - gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); - LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); - - // find vector from camera to focus point in object space - LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); - camera_to_focus_vec.rotVec(inv_obj_rot); - - // find vector from object origin to focus point in object coordinates - LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; - // convert to object-local space - focus_offset_from_object_center.rotVec(inv_obj_rot); - - // We need to project the focus point back into the bounding box of the focused object. - // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis - LLVector3 clip_fraction; - - // for each axis... - for (U32 axis = VX; axis <= VZ; axis++) - { - //...calculate distance that focus offset sits outside of bounding box along that axis... - //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center - F32 dist_out_of_bounds; - if (focus_offset_from_object_center.mV[axis] > 0.f) - { - dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); - } - else - { - dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); - } - - //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis - if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) - { - // don't divide by very small number - clip_fraction.mV[axis] = 0.f; - } - else - { - clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; - } - } - - LLVector3 abs_clip_fraction = clip_fraction; - abs_clip_fraction.abs(); - - // find axis of focus offset that is *most* outside the bounding box and use that to - // rescale focus offset to inside object extents - if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] - && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) - { - focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; - } - else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) - { - focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; - } - else - { - focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; - } - - // convert back to world space - focus_offset_from_object_center.rotVec(obj_rot); - - // now, based on distance of camera from object relative to object size - // push the focus point towards the near surface of the object when (relatively) close to the objcet - // or keep the focus point in the object middle when (relatively) far - // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars - // is almost always "tumble about middle" and not "spin around surface point" - if (!is_avatar) - { - LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); - - //now that we have the object relative position, we should bias toward the center of the object - //based on the distance of the camera to the focus point vs. the distance of the camera to the focus - - F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); - F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); - - - LLBBox obj_bbox = object->getBoundingBoxAgent(); - F32 bias = 0.f; - - // virtual_camera_pos is the camera position we are simulating by backing the camera off - // and adjusting the FOV - LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); - - // if the camera is inside the object (large, hollow objects, for example) - // leave focus point all the way to destination depth, away from object center - if(!obj_bbox.containsPointAgent(virtual_camera_pos)) - { - // perform magic number biasing of focus point towards surface vs. planar center - bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); - obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); - } - - focus_offset_from_object_center = obj_rel; - } - - return focus_offset_from_object_center; -} - -//----------------------------------------------------------------------------- -// calcCameraMinDistance() -//----------------------------------------------------------------------------- -BOOL LLAgent::calcCameraMinDistance(F32 &obj_min_distance) -{ - BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) - - if (!mFocusObject || mFocusObject->isDead()) - { - obj_min_distance = 0.f; - return TRUE; - } - - if (mFocusObject->mDrawable.isNull()) - { -#ifdef LL_RELEASE_FOR_DOWNLOAD - llwarns << "Focus object with no drawable!" << llendl; -#else - mFocusObject->dump(); - llerrs << "Focus object with no drawable!" << llendl; -#endif - obj_min_distance = 0.f; - return TRUE; - } - - LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); - LLVector3 target_offset_origin = mFocusObjectOffset; - LLVector3 camera_offset_target(getCameraPositionAgent() - getPosAgentFromGlobal(mFocusTargetGlobal)); - - // convert offsets into object local space - camera_offset_target.rotVec(inv_object_rot); - target_offset_origin.rotVec(inv_object_rot); - - // push around object extents based on target offset - LLVector3 object_extents = mFocusObject->getScale(); - if (mFocusObject->isAvatar()) - { - // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) - object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; - object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; - object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; - soft_limit = TRUE; - } - LLVector3 abs_target_offset = target_offset_origin; - abs_target_offset.abs(); - - LLVector3 target_offset_dir = target_offset_origin; - F32 object_radius = mFocusObject->getVObjRadius(); - - BOOL target_outside_object_extents = FALSE; - - for (U32 i = VX; i <= VZ; i++) - { - if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) - { - target_outside_object_extents = TRUE; - } - if (camera_offset_target.mV[i] > 0.f) - { - object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; - } - else - { - object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; - } - } - - // don't shrink the object extents so far that the object inverts - object_extents.clamp(0.001f, F32_MAX); - - // move into first octant - LLVector3 camera_offset_target_abs_norm = camera_offset_target; - camera_offset_target_abs_norm.abs(); - // make sure offset is non-zero - camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); - camera_offset_target_abs_norm.normalize(); - - // find camera position relative to normalized object extents - LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; - camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; - camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; - camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; - - if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && - camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) - { - if (camera_offset_target_abs_norm.mV[VX] < 0.001f) - { - obj_min_distance = object_extents.mV[VX] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; - } - } - else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) - { - if (camera_offset_target_abs_norm.mV[VY] < 0.001f) - { - obj_min_distance = object_extents.mV[VY] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; - } - } - else - { - if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) - { - obj_min_distance = object_extents.mV[VZ] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; - } - } - - LLVector3 object_split_axis; - LLVector3 target_offset_scaled = target_offset_origin; - target_offset_scaled.abs(); - target_offset_scaled.normalize(); - target_offset_scaled.mV[VX] /= object_extents.mV[VX]; - target_offset_scaled.mV[VY] /= object_extents.mV[VY]; - target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; - - if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && - target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) - { - object_split_axis = LLVector3::x_axis; - } - else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) - { - object_split_axis = LLVector3::y_axis; - } - else - { - object_split_axis = LLVector3::z_axis; - } - - LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); - - // length projected orthogonal to target offset - F32 camera_offset_dist = (camera_offset_object - target_offset_dir * (camera_offset_object * target_offset_dir)).magVec(); - - // calculate whether the target point would be "visible" if it were outside the bounding box - // on the opposite of the splitting plane defined by object_split_axis; - BOOL exterior_target_visible = FALSE; - if (camera_offset_dist > object_radius) - { - // target is visible from camera, so turn off fov zoom - exterior_target_visible = TRUE; - } - - F32 camera_offset_clip = camera_offset_object * object_split_axis; - F32 target_offset_clip = target_offset_dir * object_split_axis; - - // target has moved outside of object extents - // check to see if camera and target are on same side - if (target_outside_object_extents) - { - if (camera_offset_clip > 0.f && target_offset_clip > 0.f) - { - return FALSE; - } - else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) - { - return FALSE; - } - } - - // clamp obj distance to diagonal of 10 by 10 cube - obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); - - obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); - - return TRUE; -} - -F32 LLAgent::getCameraZoomFraction() -{ - // 0.f -> camera zoomed all the way out - // 1.f -> camera zoomed all the way in - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // already [0,1] - return mHUDTargetZoom; - } - else if (mFocusOnAvatar && cameraThirdPerson()) - { - return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); - } - else if (cameraCustomizeAvatar()) - { - F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); - return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); - } - else - { - F32 min_zoom; - const F32 DIST_FUDGE = 16.f; // meters - F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, - MAX_CAMERA_DISTANCE_FROM_AGENT); - - F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - else - { - min_zoom = LAND_MIN_ZOOM; - } - - return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f); - } -} - -void LLAgent::setCameraZoomFraction(F32 fraction) -{ - // 0.f -> camera zoomed all the way out - // 1.f -> camera zoomed all the way in - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - mHUDTargetZoom = fraction; - } - else if (mFocusOnAvatar && cameraThirdPerson()) - { - mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); - } - else if (cameraCustomizeAvatar()) - { - LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; - camera_offset_dir.normalize(); - mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); - } - else - { - F32 min_zoom = LAND_MIN_ZOOM; - const F32 DIST_FUDGE = 16.f; // meters - F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, - MAX_CAMERA_DISTANCE_FROM_AGENT); - - if (mFocusObject.notNull()) - { - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - } - - LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; - camera_offset_dir.normalize(); - mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); - } - startCameraAnimation(); -} - - -//----------------------------------------------------------------------------- -// cameraOrbitAround() -//----------------------------------------------------------------------------- -void LLAgent::cameraOrbitAround(const F32 radians) -{ - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // do nothing for hud selection - } - else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) - { - mFrameAgent.rotate(radians, getReferenceUpVector()); - } - else - { - mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); - - cameraZoomIn(1.f); - } -} - - -//----------------------------------------------------------------------------- -// cameraOrbitOver() -//----------------------------------------------------------------------------- -void LLAgent::cameraOrbitOver(const F32 angle) -{ - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // do nothing for hud selection - } - else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - pitch(angle); - } - else - { - LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); - camera_offset_unit.normalize(); - - F32 angle_from_up = acos( camera_offset_unit * getReferenceUpVector() ); - - LLVector3d left_axis; - left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); - F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); - mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); - - cameraZoomIn(1.f); - } -} - -//----------------------------------------------------------------------------- -// cameraZoomIn() -//----------------------------------------------------------------------------- -void LLAgent::cameraZoomIn(const F32 fraction) -{ - if (gDisconnected) - { - return; - } - - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // just update hud zoom level - mHUDTargetZoom /= fraction; - return; - } - - - LLVector3d camera_offset(mCameraFocusOffsetTarget); - LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); - F32 min_zoom = LAND_MIN_ZOOM; - F32 current_distance = (F32)camera_offset_unit.normalize(); - F32 new_distance = current_distance * fraction; - - // Don't move through focus point - if (mFocusObject) - { - LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); - - if (mFocusObject->isAvatar()) - { - calcCameraMinDistance(min_zoom); - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - - new_distance = llmax(new_distance, min_zoom); - - // Don't zoom too far back - const F32 DIST_FUDGE = 16.f; // meters - F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); - - if (new_distance > max_distance) - { - // screw cam constraints - //new_distance = max_distance; - // - - /* - // Unless camera is unlocked - if (!LLViewerCamera::sDisableCameraConstraints) - { - return; - } - */ - } - - if( cameraCustomizeAvatar() ) - { - new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM ); - } - - mCameraFocusOffsetTarget = new_distance * camera_offset_unit; -} - -//----------------------------------------------------------------------------- -// cameraOrbitIn() -//----------------------------------------------------------------------------- -void LLAgent::cameraOrbitIn(const F32 meters) -{ - if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - F32 camera_offset_dist = llmax(0.001f, mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - - mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; - - if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) - { - // No need to animate, camera is already there. - changeCameraToMouselook(FALSE); - } - - mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); - } - else - { - LLVector3d camera_offset(mCameraFocusOffsetTarget); - LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); - F32 current_distance = (F32)camera_offset_unit.normalize(); - F32 new_distance = current_distance - meters; - F32 min_zoom = LAND_MIN_ZOOM; - - // Don't move through focus point - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - - new_distance = llmax(new_distance, min_zoom); - - // Don't zoom too far back - const F32 DIST_FUDGE = 16.f; // meters - F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); - - if (new_distance > max_distance) - { - // Unless camera is unlocked - if (!gSavedSettings.getBOOL("DisableCameraConstraints")) - { - return; - } - } - - if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() ) - { - new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM ); - } - - // Compute new camera offset - mCameraFocusOffsetTarget = new_distance * camera_offset_unit; - cameraZoomIn(1.f); - } -} - - -//----------------------------------------------------------------------------- -// cameraPanIn() -//----------------------------------------------------------------------------- -void LLAgent::cameraPanIn(F32 meters) -{ - LLVector3d at_axis; - at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); - - mFocusTargetGlobal += meters * at_axis; - mFocusGlobal = mFocusTargetGlobal; - // don't enforce zoom constraints as this is the only way for users to get past them easily - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); -} - -//----------------------------------------------------------------------------- -// cameraPanLeft() -//----------------------------------------------------------------------------- -void LLAgent::cameraPanLeft(F32 meters) -{ - LLVector3d left_axis; - left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); - - mFocusTargetGlobal += meters * left_axis; - mFocusGlobal = mFocusTargetGlobal; - - // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = TRUE; - - cameraZoomIn(1.f); - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); -} - -//----------------------------------------------------------------------------- -// cameraPanUp() -//----------------------------------------------------------------------------- -void LLAgent::cameraPanUp(F32 meters) -{ - LLVector3d up_axis; - up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); - - mFocusTargetGlobal += meters * up_axis; - mFocusGlobal = mFocusTargetGlobal; - - // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = TRUE; - - cameraZoomIn(1.f); - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); -} - -//----------------------------------------------------------------------------- -// setKey() -//----------------------------------------------------------------------------- -void LLAgent::setKey(const S32 direction, S32 &key) -{ - if (direction > 0) - { - key = 1; - } - else if (direction < 0) - { - key = -1; - } - else - { - key = 0; - } -} - - -//----------------------------------------------------------------------------- -// getControlFlags() -//----------------------------------------------------------------------------- -U32 LLAgent::getControlFlags() -{ -/* - // HACK -- avoids maintenance of control flags when camera mode is turned on or off, - // only worries about it when the flags are measured - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - if ( !(mControlFlags & AGENT_CONTROL_MOUSELOOK) ) - { - mControlFlags |= AGENT_CONTROL_MOUSELOOK; - } - } -*/ - return mControlFlags; -} - -//----------------------------------------------------------------------------- -// setControlFlags() -//----------------------------------------------------------------------------- -void LLAgent::setControlFlags(U32 mask) -{ - mControlFlags |= mask; - mbFlagsDirty = TRUE; -} - - -//----------------------------------------------------------------------------- -// clearControlFlags() -//----------------------------------------------------------------------------- -void LLAgent::clearControlFlags(U32 mask) -{ - U32 old_flags = mControlFlags; - mControlFlags &= ~mask; - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } -} - -//----------------------------------------------------------------------------- -// controlFlagsDirty() -//----------------------------------------------------------------------------- -BOOL LLAgent::controlFlagsDirty() const -{ - return mbFlagsDirty; -} - -//----------------------------------------------------------------------------- -// enableControlFlagReset() -//----------------------------------------------------------------------------- -void LLAgent::enableControlFlagReset() -{ - mbFlagsNeedReset = TRUE; -} - -//----------------------------------------------------------------------------- -// resetControlFlags() -//----------------------------------------------------------------------------- -void LLAgent::resetControlFlags() -{ - if (mbFlagsNeedReset) - { - mbFlagsNeedReset = FALSE; - mbFlagsDirty = FALSE; - // reset all of the ephemeral flags - // some flags are managed elsewhere - mControlFlags &= AGENT_CONTROL_AWAY | AGENT_CONTROL_FLY | AGENT_CONTROL_MOUSELOOK; - } -} - -//----------------------------------------------------------------------------- -// setAFK() -//----------------------------------------------------------------------------- -void LLAgent::setAFK() -{ - // Drones can't go AFK - if (gNoRender) - { - return; - } - - if (!gAgent.getRegion()) - { - // Don't set AFK if we're not talking to a region yet. - return; - } - - if (!(mControlFlags & AGENT_CONTROL_AWAY)) - { - sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); - setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP); - gAwayTimer.start(); - if (gAFKMenu) - { - //*TODO:Translate - gAFKMenu->setLabel(std::string("Set Not Away")); - } - } -} - -//----------------------------------------------------------------------------- -// clearAFK() -//----------------------------------------------------------------------------- -void LLAgent::clearAFK() -{ - gAwayTriggerTimer.reset(); - - // Gods can sometimes get into away state (via gestures) - // without setting the appropriate control flag. JC - LLVOAvatar* av = mAvatarObject; - if (mControlFlags & AGENT_CONTROL_AWAY - || (av - && (av->mSignaledAnimations.find(ANIM_AGENT_AWAY) != av->mSignaledAnimations.end()))) - { - sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); - clearControlFlags(AGENT_CONTROL_AWAY); - if (gAFKMenu) - { - //*TODO:Translate - gAFKMenu->setLabel(std::string("Set Away")); - } - } -} - -//----------------------------------------------------------------------------- -// getAFK() -//----------------------------------------------------------------------------- -BOOL LLAgent::getAFK() const -{ - return (mControlFlags & AGENT_CONTROL_AWAY) != 0; -} - -//----------------------------------------------------------------------------- -// setBusy() -//----------------------------------------------------------------------------- -void LLAgent::setBusy() -{ - sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START); - mIsBusy = TRUE; - if (gBusyMenu) - { - //*TODO:Translate - gBusyMenu->setLabel(std::string("Set Not Busy")); - } - LLFloaterMute::getInstance()->updateButtons(); -} - -//----------------------------------------------------------------------------- -// clearBusy() -//----------------------------------------------------------------------------- -void LLAgent::clearBusy() -{ - mIsBusy = FALSE; - sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP); - if (gBusyMenu) - { - //*TODO:Translate - gBusyMenu->setLabel(std::string("Set Busy")); - } - LLFloaterMute::getInstance()->updateButtons(); -} - -//----------------------------------------------------------------------------- -// getBusy() -//----------------------------------------------------------------------------- -BOOL LLAgent::getBusy() const -{ - return mIsBusy; -} - - -//----------------------------------------------------------------------------- -// startAutoPilotGlobal() -//----------------------------------------------------------------------------- -void LLAgent::startAutoPilotGlobal(const LLVector3d &target_global, const std::string& behavior_name, const LLQuaternion *target_rotation, void (*finish_callback)(BOOL, void *), void *callback_data, F32 stop_distance, F32 rot_threshold) -{ - if (!gAgent.getAvatarObject()) - { - return; - } - - mAutoPilotFinishedCallback = finish_callback; - mAutoPilotCallbackData = callback_data; - mAutoPilotRotationThreshold = rot_threshold; - mAutoPilotBehaviorName = behavior_name; - - LLVector3d delta_pos( target_global ); - delta_pos -= getPositionGlobal(); - F64 distance = delta_pos.magVec(); - LLVector3d trace_target = target_global; - - trace_target.mdV[VZ] -= 10.f; - - LLVector3d intersection; - LLVector3 normal; - LLViewerObject *hit_obj; - F32 heightDelta = LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, trace_target, intersection, normal, &hit_obj); - - if (stop_distance > 0.f) - { - mAutoPilotStopDistance = stop_distance; - } - else - { - // Guess at a reasonable stop distance. - mAutoPilotStopDistance = fsqrtf( distance ); - if (mAutoPilotStopDistance < 0.5f) - { - mAutoPilotStopDistance = 0.5f; - } - } - - mAutoPilotFlyOnStop = getFlying(); - - if (distance > 30.0) - { - setFlying(TRUE); - } - - if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f)) - { - setFlying(TRUE); - mAutoPilotFlyOnStop = TRUE; - } - - mAutoPilot = TRUE; - mAutoPilotTargetGlobal = target_global; - - // trace ray down to find height of destination from ground - LLVector3d traceEndPt = target_global; - traceEndPt.mdV[VZ] -= 20.f; - - LLVector3d targetOnGround; - LLVector3 groundNorm; - LLViewerObject *obj; - - LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj); - F64 target_height = llmax((F64)gAgent.getAvatarObject()->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]); - - // clamp z value of target to minimum height above ground - mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height; - mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal); - if (target_rotation) - { - mAutoPilotUseRotation = TRUE; - mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation; - mAutoPilotTargetFacing.mV[VZ] = 0.f; - mAutoPilotTargetFacing.normalize(); - } - else - { - mAutoPilotUseRotation = FALSE; - } - - mAutoPilotNoProgressFrameCount = 0; -} - - -//----------------------------------------------------------------------------- -// startFollowPilot() -//----------------------------------------------------------------------------- -void LLAgent::startFollowPilot(const LLUUID &leader_id) -{ - if (!mAutoPilot) return; - - mLeaderID = leader_id; - if ( mLeaderID.isNull() ) return; - - LLViewerObject* object = gObjectList.findObject(mLeaderID); - if (!object) - { - mLeaderID = LLUUID::null; - return; - } - - startAutoPilotGlobal(object->getPositionGlobal()); -} - - -//----------------------------------------------------------------------------- -// stopAutoPilot() -//----------------------------------------------------------------------------- -void LLAgent::stopAutoPilot(BOOL user_cancel) -{ - if (mAutoPilot) - { - mAutoPilot = FALSE; - if (mAutoPilotUseRotation && !user_cancel) - { - resetAxes(mAutoPilotTargetFacing); - } - //NB: auto pilot can terminate for a reason other than reaching the destination - if (mAutoPilotFinishedCallback) - { - mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData); - } - mLeaderID = LLUUID::null; - - // If the user cancelled, don't change the fly state - if (!user_cancel) - { - setFlying(mAutoPilotFlyOnStop); - } - setControlFlags(AGENT_CONTROL_STOP); - - if (user_cancel && !mAutoPilotBehaviorName.empty()) - { - if (mAutoPilotBehaviorName == "Sit") - LLNotifications::instance().add("CancelledSit"); - else if (mAutoPilotBehaviorName == "Attach") - LLNotifications::instance().add("CancelledAttach"); - else - LLNotifications::instance().add("Cancelled"); - } - } -} - - -// Returns necessary agent pitch and yaw changes, radians. -//----------------------------------------------------------------------------- -// autoPilot() -//----------------------------------------------------------------------------- -void LLAgent::autoPilot(F32 *delta_yaw) -{ - if (mAutoPilot) - { - if (!mLeaderID.isNull()) - { - LLViewerObject* object = gObjectList.findObject(mLeaderID); - if (!object) - { - stopAutoPilot(); - return; - } - mAutoPilotTargetGlobal = object->getPositionGlobal(); - } - - if (mAvatarObject.isNull()) - { - return; - } - - if (mAvatarObject->mInAir) - { - setFlying(TRUE); - } - - LLVector3 at; - at.setVec(mFrameAgent.getAtAxis()); - LLVector3 target_agent = getPosAgentFromGlobal(mAutoPilotTargetGlobal); - LLVector3 direction = target_agent - getPositionAgent(); - - F32 target_dist = direction.magVec(); - - if (target_dist >= mAutoPilotTargetDist) - { - mAutoPilotNoProgressFrameCount++; - if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped) - { - stopAutoPilot(); - return; - } - } - - mAutoPilotTargetDist = target_dist; - - // Make this a two-dimensional solution - at.mV[VZ] = 0.f; - direction.mV[VZ] = 0.f; - - at.normalize(); - F32 xy_distance = direction.normalize(); - - F32 yaw = 0.f; - if (mAutoPilotTargetDist > mAutoPilotStopDistance) - { - yaw = angle_between(mFrameAgent.getAtAxis(), direction); - } - else if (mAutoPilotUseRotation) - { - // we're close now just aim at target facing - yaw = angle_between(at, mAutoPilotTargetFacing); - direction = mAutoPilotTargetFacing; - } - - yaw = 4.f * yaw / gFPSClamped; - - // figure out which direction to turn - LLVector3 scratch(at % direction); - - if (scratch.mV[VZ] > 0.f) - { - setControlFlags(AGENT_CONTROL_YAW_POS); - } - else - { - yaw = -yaw; - setControlFlags(AGENT_CONTROL_YAW_NEG); - } - - *delta_yaw = yaw; - - // Compute when to start slowing down and when to stop - F32 stop_distance = mAutoPilotStopDistance; - F32 slow_distance; - if (getFlying()) - { - slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f); - stop_distance = llmax(2.f, mAutoPilotStopDistance); - } - else - { - slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f); - } - - // If we're flying, handle autopilot points above or below you. - if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE) - { - if (mAvatarObject.notNull()) - { - F64 current_height = mAvatarObject->getPositionGlobal().mdV[VZ]; - F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height); - F32 slope = delta_z / xy_distance; - if (slope > 0.45f && delta_z > 6.f) - { - setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS); - } - else if (slope > 0.002f && delta_z > 0.5f) - { - setControlFlags(AGENT_CONTROL_UP_POS); - } - else if (slope < -0.45f && delta_z < -6.f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND) - { - setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG); - } - else if (slope < -0.002f && delta_z < -0.5f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND) - { - setControlFlags(AGENT_CONTROL_UP_NEG); - } - } - } - - // calculate delta rotation to target heading - F32 delta_target_heading = angle_between(mFrameAgent.getAtAxis(), mAutoPilotTargetFacing); - - if (xy_distance > slow_distance && yaw < (F_PI / 10.f)) - { - // walking/flying fast - setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS); - } - else if (mAutoPilotTargetDist > mAutoPilotStopDistance) - { - // walking/flying slow - if (at * direction > 0.9f) - { - setControlFlags(AGENT_CONTROL_AT_POS); - } - else if (at * direction < -0.9f) - { - setControlFlags(AGENT_CONTROL_AT_NEG); - } - } - - // check to see if we need to keep rotating to target orientation - if (mAutoPilotTargetDist < mAutoPilotStopDistance) - { - setControlFlags(AGENT_CONTROL_STOP); - if(!mAutoPilotUseRotation || (delta_target_heading < mAutoPilotRotationThreshold)) - { - stopAutoPilot(); - } - } - } -} - - -//----------------------------------------------------------------------------- -// propagate() -//----------------------------------------------------------------------------- -void LLAgent::propagate(const F32 dt) -{ - // Update UI based on agent motion - LLFloaterMove *floater_move = LLFloaterMove::getInstance(); - if (floater_move) - { - floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 ); - floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 ); - floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 ); - floater_move->mSlideRightButton->setToggleState( mLeftKey < 0 ); - floater_move->mTurnLeftButton ->setToggleState( mYawKey > 0.f ); - floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f ); - floater_move->mMoveUpButton ->setToggleState( mUpKey > 0 ); - floater_move->mMoveDownButton ->setToggleState( mUpKey < 0 ); - } - - // handle rotation based on keyboard levels - const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second - yaw( YAW_RATE * mYawKey * dt ); - - const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second - pitch(PITCH_RATE * (F32) mPitchKey * dt); - - // handle auto-land behavior - if (mAvatarObject.notNull()) - { - BOOL in_air = mAvatarObject->mInAir; - LLVector3 land_vel = getVelocity(); - land_vel.mV[VZ] = 0.f; - - if (!in_air - && mUpKey < 0 - && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED - && gSavedSettings.getBOOL("AutomaticFly")) - { - // land automatically - setFlying(FALSE); - } - } - - // clear keys - mAtKey = 0; - mWalkKey = 0; - mLeftKey = 0; - mUpKey = 0; - mYawKey = 0.f; - mPitchKey = 0; -} - -//----------------------------------------------------------------------------- -// updateAgentPosition() -//----------------------------------------------------------------------------- -void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y) -{ - propagate(dt); - - // static S32 cameraUpdateCount = 0; - - rotate(yaw_radians, 0, 0, 1); - - // - // Check for water and land collision, set underwater flag - // - - updateLookAt(mouse_x, mouse_y); -} - -//----------------------------------------------------------------------------- -// updateLookAt() -//----------------------------------------------------------------------------- -void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y) -{ - static LLVector3 last_at_axis; - - - if (mAvatarObject.isNull()) - { - return; - } - - LLQuaternion av_inv_rot = ~mAvatarObject->mRoot.getWorldRotation(); - LLVector3 root_at = LLVector3::x_axis * mAvatarObject->mRoot.getWorldRotation(); - - if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && - (root_at * last_at_axis > 0.95f )) - { - LLVector3 vel = mAvatarObject->getVelocity(); - if (vel.magVecSquared() > 4.f) - { - setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, vel * av_inv_rot); - } - else - { - // *FIX: rotate mframeagent by sit object's rotation? - LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation - LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; - setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset); - } - last_at_axis = root_at; - return; - } - - last_at_axis = root_at; - - if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) - { - setLookAt(LOOKAT_TARGET_NONE, mAvatarObject, LLVector3(-2.f, 0.f, 0.f)); - } - else - { - // Move head based on cursor position - ELookAtType lookAtType = LOOKAT_TARGET_NONE; - LLVector3 headLookAxis; - LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); - - if (cameraMouselook()) - { - lookAtType = LOOKAT_TARGET_MOUSELOOK; - } - else if (cameraThirdPerson()) - { - // range from -.5 to .5 - F32 x_from_center = - ((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f; - F32 y_from_center = - ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f; - - frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); - frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); - lookAtType = LOOKAT_TARGET_FREELOOK; - } - - headLookAxis = frameCamera.getAtAxis(); - // RN: we use world-space offset for mouselook and freelook - //headLookAxis = headLookAxis * av_inv_rot; - setLookAt(lookAtType, mAvatarObject, headLookAxis); - } -} - -// friends and operators - -std::ostream& operator<<(std::ostream &s, const LLAgent &agent) -{ - // This is unfinished, but might never be used. - // We'll just leave it for now; we can always delete it. - s << " { " - << " Frame = " << agent.mFrameAgent << "\n" - << " }"; - return s; -} - - -// ------------------- Beginning of legacy LLCamera hack ---------------------- -// This section is included for legacy LLCamera support until -// it is no longer needed. Some legacy code must exist in -// non-legacy functions, and is labeled with "// legacy" comments. - -//----------------------------------------------------------------------------- -// setAvatarObject() -//----------------------------------------------------------------------------- -void LLAgent::setAvatarObject(LLVOAvatar *avatar) -{ - mAvatarObject = avatar; - - if (!avatar) - { - llinfos << "Setting LLAgent::mAvatarObject to NULL" << llendl; - return; - } - - if (!mLookAt) - { - mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); - } - if (!mPointAt) - { - mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); - } - - if (!mLookAt.isNull()) - { - mLookAt->setSourceObject(avatar); - } - if (!mPointAt.isNull()) - { - mPointAt->setSourceObject(avatar); - } - - sendAgentWearablesRequest(); -} - -// TRUE if your own avatar needs to be rendered. Usually only -// in third person and build. -//----------------------------------------------------------------------------- -// needsRenderAvatar() -//----------------------------------------------------------------------------- -BOOL LLAgent::needsRenderAvatar() -{ - if (cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson) - { - return FALSE; - } - - return mShowAvatar && mGenderChosen; -} - -// TRUE if we need to render your own avatar's head. -BOOL LLAgent::needsRenderHead() -{ - return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook()); -} - -//----------------------------------------------------------------------------- -// startTyping() -//----------------------------------------------------------------------------- -void LLAgent::startTyping() -{ - mTypingTimer.reset(); - - if (getRenderState() & AGENT_STATE_TYPING) - { - // already typing, don't trigger a different animation - return; - } - setRenderState(AGENT_STATE_TYPING); - - if (mChatTimer.getElapsedTimeF32() < 2.f) - { - LLViewerObject* chatter = gObjectList.findObject(mLastChatterID); - if (chatter && chatter->isAvatar()) - { - gAgent.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero); - } - } - - if (gSavedSettings.getBOOL("PlayTypingAnim")) - { - sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); - } - gChatBar->sendChatFromViewer("", CHAT_TYPE_START, FALSE); -} - -//----------------------------------------------------------------------------- -// stopTyping() -//----------------------------------------------------------------------------- -void LLAgent::stopTyping() -{ - if (mRenderState & AGENT_STATE_TYPING) - { - clearRenderState(AGENT_STATE_TYPING); - sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - gChatBar->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); - } -} - -//----------------------------------------------------------------------------- -// setRenderState() -//----------------------------------------------------------------------------- -void LLAgent::setRenderState(U8 newstate) -{ - mRenderState |= newstate; -} - -//----------------------------------------------------------------------------- -// clearRenderState() -//----------------------------------------------------------------------------- -void LLAgent::clearRenderState(U8 clearstate) -{ - mRenderState &= ~clearstate; -} - - -//----------------------------------------------------------------------------- -// getRenderState() -//----------------------------------------------------------------------------- -U8 LLAgent::getRenderState() -{ - if (gNoRender || gKeyboard == NULL) - { - return 0; - } - - // *FIX: don't do stuff in a getter! This is infinite loop city! - if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS) - && (mRenderState & AGENT_STATE_TYPING)) - { - stopTyping(); - } - - if ((!LLSelectMgr::getInstance()->getSelection()->isEmpty() && LLSelectMgr::getInstance()->shouldShowSelection()) - || LLToolMgr::getInstance()->getCurrentTool()->isEditing() ) - { - setRenderState(AGENT_STATE_EDITING); - } - else - { - clearRenderState(AGENT_STATE_EDITING); - } - - return mRenderState; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -static const LLFloaterView::skip_list_t& get_skip_list() -{ - static LLFloaterView::skip_list_t skip_list; - skip_list.insert(LLFloaterMap::getInstance()); - return skip_list; -} - -//----------------------------------------------------------------------------- -// endAnimationUpdateUI() -//----------------------------------------------------------------------------- -void LLAgent::endAnimationUpdateUI() -{ - if (mCameraMode == mLastCameraMode) - { - // We're already done endAnimationUpdateUI for this transition. - return; - } - - // clean up UI from mode we're leaving - if ( mLastCameraMode == CAMERA_MODE_MOUSELOOK ) - { - // show mouse cursor - gViewerWindow->showCursor(); - // show menus - gMenuBarView->setVisible(TRUE); - gStatusBar->setVisibleForMouselook(true); - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - - // Only pop if we have pushed... - if (TRUE == mViewsPushed) - { - mViewsPushed = FALSE; - gFloaterView->popVisibleAll(get_skip_list()); - } - - gAgent.setLookAt(LOOKAT_TARGET_CLEAR); - if( gMorphView ) - { - gMorphView->setVisible( FALSE ); - } - - // Disable mouselook-specific animations - if (mAvatarObject.notNull()) - { - if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) ) - { - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_RIFLE_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BOW_L) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_START); - } - } - } - } - else - if( mLastCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR ) - { - // make sure we ask to save changes - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - - // HACK: If we're quitting, and we were in customize avatar, don't - // let the mini-map go visible again. JC - if (!LLAppViewer::instance()->quitRequested()) - { - LLFloaterMap::getInstance()->popVisible(); - } - - if( gMorphView ) - { - gMorphView->setVisible( FALSE ); - } - - if (mAvatarObject.notNull()) - { - if(mCustomAnim) - { - sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_CUSTOMIZE_DONE, ANIM_REQUEST_START); - - mCustomAnim = FALSE ; - } - - } - setLookAt(LOOKAT_TARGET_CLEAR); - } - - //--------------------------------------------------------------------- - // Set up UI for mode we're entering - //--------------------------------------------------------------------- - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - // hide menus - gMenuBarView->setVisible(FALSE); - gStatusBar->setVisibleForMouselook(false); - - // clear out camera lag effect - mCameraLag.clearVec(); - - // JC - Added for always chat in third person option - gFocusMgr.setKeyboardFocus(NULL); - - LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - - mViewsPushed = TRUE; - - gFloaterView->pushVisibleAll(FALSE, get_skip_list()); - - if( gMorphView ) - { - gMorphView->setVisible(FALSE); - } - - gConsole->setVisible( TRUE ); - - if (mAvatarObject.notNull()) - { - // Trigger mouselook-specific animations - if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) ) - { - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_RIFLE_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_START); - } - if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BOW_L) != mAvatarObject->mSignaledAnimations.end()) - { - sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_STOP); - sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_START); - } - } - if (mAvatarObject->getParent()) - { - LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); - LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot(); - if (root_object->flagCameraDecoupled()) - { - resetAxes(at_axis); - } - else - { - resetAxes(at_axis * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation()); - } - } - } - - } - else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) - { - LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); - - LLFloaterMap::getInstance()->pushVisible(FALSE); - /* - LLView *view; - for (view = gFloaterView->getFirstChild(); view; view = gFloaterView->getNextChild()) - { - view->pushVisible(FALSE); - } - */ - - if( gMorphView ) - { - gMorphView->setVisible( TRUE ); - } - - // freeze avatar - if (mAvatarObject.notNull()) - { - // - //mPauseRequest = mAvatarObject->requestPause(); - // - } - } - - if (getAvatarObject()) - { - getAvatarObject()->updateAttachmentVisibility(mCameraMode); - } - - gFloaterTools->dirty(); - - // Don't let this be called more than once if the camera - // mode hasn't changed. --JC - mLastCameraMode = mCameraMode; - -} - - -//----------------------------------------------------------------------------- -// updateCamera() -//----------------------------------------------------------------------------- -void LLAgent::updateCamera() -{ - //Ventrella - changed camera_skyward to the new global "mCameraUpVector" - mCameraUpVector = LLVector3::z_axis; - //LLVector3 camera_skyward(0.f, 0.f, 1.f); - //end Ventrella - - U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; - - validateFocusObject(); - - if (mAvatarObject.notNull() && - mAvatarObject->mIsSitting && - camera_mode == CAMERA_MODE_MOUSELOOK) - { - //Ventrella - //changed camera_skyward to the new global "mCameraUpVector" - mCameraUpVector = mCameraUpVector * mAvatarObject->getRenderRotation(); - //end Ventrella - } - - if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) - { - changeCameraToFollow(); - } - - //Ventrella - //NOTE - this needs to be integrated into a general upVector system here within llAgent. - if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - mCameraUpVector = mFollowCam.getUpVector(); - } - //end Ventrella - - if (mSitCameraEnabled) - { - if (mSitCameraReferenceObject->isDead()) - { - setSitCamera(LLUUID::null); - } - } - - // Update UI with our camera inputs - LLFloaterCamera::getInstance()->mRotate->setToggleState( - mOrbitRightKey > 0.f, // left - mOrbitUpKey > 0.f, // top - mOrbitLeftKey > 0.f, // right - mOrbitDownKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->mZoom->setToggleState( - mOrbitInKey > 0.f, // top - mOrbitOutKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->mTrack->setToggleState( - mPanLeftKey > 0.f, // left - mPanUpKey > 0.f, // top - mPanRightKey > 0.f, // right - mPanDownKey > 0.f); // bottom - - // Handle camera movement based on keyboard. - const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second - const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second - const F32 PAN_RATE = 5.f; // meters per second - - if( mOrbitUpKey || mOrbitDownKey ) - { - F32 input_rate = mOrbitUpKey - mOrbitDownKey; - cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); - } - - if( mOrbitLeftKey || mOrbitRightKey) - { - F32 input_rate = mOrbitLeftKey - mOrbitRightKey; - cameraOrbitAround( input_rate * ORBIT_AROUND_RATE / gFPSClamped ); - } - - if( mOrbitInKey || mOrbitOutKey ) - { - F32 input_rate = mOrbitInKey - mOrbitOutKey; - - LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); - F32 distance_to_focus = (F32)to_focus.magVec(); - // Move at distance (in meters) meters per second - cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); - } - - if( mPanInKey || mPanOutKey ) - { - F32 input_rate = mPanInKey - mPanOutKey; - cameraPanIn( input_rate * PAN_RATE / gFPSClamped ); - } - - if( mPanRightKey || mPanLeftKey ) - { - F32 input_rate = mPanRightKey - mPanLeftKey; - cameraPanLeft( input_rate * -PAN_RATE / gFPSClamped ); - } - - if( mPanUpKey || mPanDownKey ) - { - F32 input_rate = mPanUpKey - mPanDownKey; - cameraPanUp( input_rate * PAN_RATE / gFPSClamped ); - } - - // Clear camera keyboard keys. - mOrbitLeftKey = 0.f; - mOrbitRightKey = 0.f; - mOrbitUpKey = 0.f; - mOrbitDownKey = 0.f; - mOrbitInKey = 0.f; - mOrbitOutKey = 0.f; - - mPanRightKey = 0.f; - mPanLeftKey = 0.f; - mPanUpKey = 0.f; - mPanDownKey = 0.f; - mPanInKey = 0.f; - mPanOutKey = 0.f; - - // lerp camera focus offset - mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); - - //Ventrella - if ( mCameraMode == CAMERA_MODE_FOLLOW ) - { - if ( mAvatarObject.notNull() ) - { - //-------------------------------------------------------------------------------- - // this is where the avatar's position and rotation are given to followCam, and - // where it is updated. All three of its attributes are updated: (1) position, - // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. - //-------------------------------------------------------------------------------- - // *TODO: use combined rotation of frameagent and sit object - LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); - - LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams(); - if (current_cam) - { - mFollowCam.copyParams(*current_cam); - mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam ); - mFollowCam.update(); - } - else - { - changeCameraToThirdPerson(TRUE); - } - } - } - // end Ventrella - - BOOL hit_limit; - LLVector3d camera_pos_global; - LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); - mCameraVirtualPositionAgent = getPosAgentFromGlobal(camera_target_global); - LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); - - // perform field of view correction - mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); - camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); - - mShowAvatar = TRUE; // can see avatar by default - - // Adjust position for animation - if (mCameraAnimating) - { - F32 time = mAnimationTimer.getElapsedTimeF32(); - - // yet another instance of critically damped motion, hooray! - // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); - - // linear interpolation - F32 fraction_of_animation = time / mAnimationDuration; - - BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; - BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; - F32 fraction_animation_to_skip; - - if (mAnimationCameraStartGlobal == camera_target_global) - { - fraction_animation_to_skip = 0.f; - } - else - { - LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; - fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); - } - F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; - F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; - - if (fraction_of_animation < animation_finish_fraction) - { - if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) - { - mShowAvatar = FALSE; - } - - // ...adjust position for animation - F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); - camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); - mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); - } - else - { - // ...animation complete - mCameraAnimating = FALSE; - - camera_pos_global = camera_target_global; - mFocusGlobal = focus_target_global; - - endAnimationUpdateUI(); - mShowAvatar = TRUE; - } - - if (getAvatarObject() && mCameraMode != CAMERA_MODE_MOUSELOOK) - { - getAvatarObject()->updateAttachmentVisibility(mCameraMode); - } - } - else - { - camera_pos_global = camera_target_global; - mFocusGlobal = focus_target_global; - mShowAvatar = TRUE; - } - - // smoothing - if (TRUE) - { - LLVector3d agent_pos = getPositionGlobal(); - LLVector3d camera_pos_agent = camera_pos_global - agent_pos; - // Sitting on what you're manipulating can cause camera jitter with smoothing. - // This turns off smoothing while editing. -MG - mCameraSmoothingStop |= (BOOL)LLToolMgr::getInstance()->inBuildMode(); - - if (cameraThirdPerson() && !mCameraSmoothingStop) - { - const F32 SMOOTHING_HALF_LIFE = 0.02f; - - F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); - - if (!mFocusObject) // we differentiate on avatar mode - { - // for avatar-relative focus, we smooth in avatar space - - // the avatar moves too jerkily w/r/t global space to smooth there. - - LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); - camera_pos_global = camera_pos_agent + agent_pos; - } - } - else - { - LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); - } - } - } - - mCameraSmoothingLastPositionGlobal = camera_pos_global; - mCameraSmoothingLastPositionAgent = camera_pos_agent; - mCameraSmoothingStop = FALSE; - } - - - mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); - -// llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl; - - F32 ui_offset = 0.f; - if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) - { - ui_offset = calcCustomizeAvatarUIOffset( camera_pos_global ); - } - - - LLVector3 focus_agent = getPosAgentFromGlobal(mFocusGlobal); - - mCameraPositionAgent = getPosAgentFromGlobal(camera_pos_global); - - // Move the camera - - //Ventrella - LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); - //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); - //end Ventrella - - //RN: translate UI offset after camera is oriented properly - LLViewerCamera::getInstance()->translate(LLViewerCamera::getInstance()->getLeftAxis() * ui_offset); - - // Change FOV - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); - - // follow camera when in customize mode - if (cameraCustomizeAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); - } - - // update the travel distance stat - // this isn't directly related to the camera - // but this seemed like the best place to do this - LLVector3d global_pos = getPositionGlobal(); - if (! mLastPositionGlobal.isExactlyZero()) - { - LLVector3d delta = global_pos - mLastPositionGlobal; - mDistanceTraveled += delta.magVec(); - } - mLastPositionGlobal = global_pos; - - if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook()) - { - LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + - LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + - LLVector3(0.1f, 0.f, 0.f) * mAvatarObject->mPelvisp->getWorldRotation(); - LLVector3 diff = mCameraPositionAgent - head_pos; - diff = diff * ~mAvatarObject->mRoot.getWorldRotation(); - - LLJoint* torso_joint = mAvatarObject->mTorsop; - LLJoint* chest_joint = mAvatarObject->mChestp; - LLVector3 torso_scale = torso_joint->getScale(); - LLVector3 chest_scale = chest_joint->getScale(); - - // shorten avatar skeleton to avoid foot interpenetration - if (!mAvatarObject->mInAir) - { - LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); - F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); - F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); - torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - - LLJoint* neck_joint = mAvatarObject->mNeckp; - LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); - scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); - chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - diff.mV[VZ] = 0.f; - } - - mAvatarObject->mPelvisp->setPosition(mAvatarObject->mPelvisp->getPosition() + diff); - - mAvatarObject->mRoot.updateWorldMatrixChildren(); - - for (LLVOAvatar::attachment_map_t::iterator iter = mAvatarObject->mAttachmentPoints.begin(); - iter != mAvatarObject->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLViewerObject *attached_object = attachment->getObject(); - if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) - { - // clear any existing "early" movements of attachment - attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); - gPipeline.updateMoveNormalAsync(attached_object->mDrawable); - attached_object->updateText(); - } - } - - torso_joint->setScale(torso_scale); - chest_joint->setScale(chest_scale); - } -} - -void LLAgent::updateFocusOffset() -{ - validateFocusObject(); - if (mFocusObject.notNull()) - { - LLVector3d obj_pos = getPosGlobalFromAgent(mFocusObject->getRenderPosition()); - mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); - } -} - -void LLAgent::validateFocusObject() -{ - if (mFocusObject.notNull() && - (mFocusObject->isDead())) - { - mFocusObjectOffset.clearVec(); - clearFocusObject(); - mCameraFOVZoomFactor = 0.f; - } -} - -//----------------------------------------------------------------------------- -// calcCustomizeAvatarUIOffset() -//----------------------------------------------------------------------------- -F32 LLAgent::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ) -{ - F32 ui_offset = 0.f; - - if( gFloaterCustomize ) - { - const LLRect& rect = gFloaterCustomize->getRect(); - - // Move the camera so that the avatar isn't covered up by this floater. - F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth())))); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); // radians - F32 offset = tan(apparent_angle); - - if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) ) - { - // Move the avatar to the right (camera to the left) - ui_offset = offset; - } - else - { - // Move the avatar to the left (camera to the right) - ui_offset = -offset; - } - } - F32 range = (F32)dist_vec(camera_pos_global, gAgent.getFocusGlobal()); - mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f)); - return mUIOffset * range; -} - -//----------------------------------------------------------------------------- -// calcFocusPositionTargetGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::calcFocusPositionTargetGlobal() -{ - if (mFocusObject.notNull() && mFocusObject->isDead()) - { - clearFocusObject(); - } - - // Ventrella - if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); - return mFocusTargetGlobal; - }// End Ventrella - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - LLVector3d at_axis(1.0, 0.0, 0.0); - LLQuaternion agent_rot = mFrameAgent.getQuaternion(); - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot(); - if (!root_object->flagCameraDecoupled()) - { - agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); - } - } - at_axis = at_axis * agent_rot; - mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; - return mFocusTargetGlobal; - } - else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) - { - return mFocusTargetGlobal; - } - else if (!mFocusOnAvatar) - { - if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) - { - LLDrawable* drawablep = mFocusObject->mDrawable; - - if (mTrackFocusObject && - drawablep && - drawablep->isActive()) - { - if (!mFocusObject->isAvatar()) - { - if (mFocusObject->isSelected()) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - gPipeline.updateMoveDampedAsync(drawablep); - } - } - } - } - // if not tracking object, update offset based on new object position - else - { - updateFocusOffset(); - } - LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; - mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent)); - } - return mFocusTargetGlobal; - } - else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); - return getPosGlobalFromAgent(target_pos); - } - else - { - return getPositionGlobal() + calcThirdPersonFocusOffset(); - } -} - -LLVector3d LLAgent::calcThirdPersonFocusOffset() -{ - // ...offset from avatar - LLVector3d focus_offset; - focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault")); - - LLQuaternion agent_rot = mFrameAgent.getQuaternion(); - if (!mAvatarObject.isNull() && mAvatarObject->getParent()) - { - agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); - } - - focus_offset = focus_offset * agent_rot; - return focus_offset; -} - -void LLAgent::setupSitCamera() -{ - // agent frame entering this function is in world coordinates - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = mFrameAgent.getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~parent_rot); - } -} - -//----------------------------------------------------------------------------- -// getCameraPositionAgent() -//----------------------------------------------------------------------------- -const LLVector3 &LLAgent::getCameraPositionAgent() const -{ - return LLViewerCamera::getInstance()->getOrigin(); -} - -//----------------------------------------------------------------------------- -// getCameraPositionGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::getCameraPositionGlobal() const -{ - return getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); -} - -//----------------------------------------------------------------------------- -// calcCameraFOVZoomFactor() -//----------------------------------------------------------------------------- -F32 LLAgent::calcCameraFOVZoomFactor() -{ - LLVector3 camera_offset_dir; - camera_offset_dir.setVec(mCameraFocusOffset); - - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } - else if (mFocusObject.notNull() && !mFocusObject->isAvatar()) - { - // don't FOV zoom on mostly transparent objects - LLVector3 focus_offset = mFocusObjectOffset; - F32 obj_min_dist = 0.f; - calcCameraMinDistance(obj_min_dist); - F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); - - mFocusObjectDist = obj_min_dist - current_distance; - - F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); - return new_fov_zoom; - } - else // focusing on land or avatar - { - // keep old field of view until user changes focus explicitly - return mCameraFOVZoomFactor; - //return 0.f; - } -} - -//----------------------------------------------------------------------------- -// calcCameraPositionTargetGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) -{ - // Compute base camera position and look-at points. - F32 camera_land_height; - LLVector3d frame_center_global = mAvatarObject.isNull() ? getPositionGlobal() - : getPosGlobalFromAgent(mAvatarObject->mRoot.getWorldPosition()); - - LLVector3 upAxis = getUpAxis(); - BOOL isConstrained = FALSE; - LLVector3d head_offset; - head_offset.setVec(mThirdPersonHeadOffset); - - LLVector3d camera_position_global; - - // Ventrella - if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); - }// End Ventrella - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - if (mAvatarObject.isNull() || mAvatarObject->mDrawable.isNull()) - { - llwarns << "Null avatar drawable!" << llendl; - return LLVector3d::zero; - } - head_offset.clearVec(); - if (mAvatarObject->mIsSitting && mAvatarObject->getParent()) - { - mAvatarObject->updateHeadOffset(); - head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX]; - head_offset.mdV[VY] = mAvatarObject->mHeadOffset.mV[VY]; - head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ] + 0.1f; - const LLMatrix4& mat = ((LLViewerObject*) mAvatarObject->getParent())->getRenderMatrix(); - camera_position_global = getPosGlobalFromAgent - ((mAvatarObject->getPosition()+ - LLVector3(head_offset)*mAvatarObject->getRotation()) * mat); - } - else - { - head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ]; - if (mAvatarObject->mIsSitting) - { - head_offset.mdV[VZ] += 0.1; - } - camera_position_global = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());//frame_center_global; - head_offset = head_offset * mAvatarObject->getRenderRotation(); - camera_position_global = camera_position_global + head_offset; - } - } - else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) - { - LLVector3 local_camera_offset; - F32 camera_distance = 0.f; - - if (mSitCameraEnabled - && mAvatarObject.notNull() - && mAvatarObject->mIsSitting - && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); - - camera_position_global = getPosGlobalFromAgent(target_pos); - } - else - { - local_camera_offset = mCameraZoomFraction * mCameraOffsetDefault * gSavedSettings.getF32("CameraOffsetScale"); - - // are we sitting down? - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = mFrameAgent.getAtAxis() * parent_rot; - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~parent_rot); - - local_camera_offset = local_camera_offset * mFrameAgent.getQuaternion() * parent_rot; - } - else - { - local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset ); - } - - if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->mIsSitting)) - { - LLVector3 plane_normal; - plane_normal.setVec(mCameraCollidePlane.mV); - - F32 offset_dot_norm = local_camera_offset * plane_normal; - if (llabs(offset_dot_norm) < 0.001f) - { - offset_dot_norm = 0.001f; - } - - camera_distance = local_camera_offset.normalize(); - - F32 pos_dot_norm = getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; - - // if agent is outside the colliding half-plane - if (pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - // check to see if camera is on the opposite side (inside) the half-plane - if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) - { - // diminish offset by factor to push it back outside the half-plane - camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; - } - } - else - { - if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; - } - } - } - else - { - camera_distance = local_camera_offset.normalize(); - } - - mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); - - if (mTargetCameraDistance != mCurrentCameraDistance) - { - F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); - - mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); - } - - // Make the camera distance current - local_camera_offset *= mCurrentCameraDistance; - - // set the global camera position - LLVector3d camera_offset; - - LLVector3 av_pos = mAvatarObject.isNull() ? LLVector3::zero : mAvatarObject->getRenderPosition(); - camera_offset.setVec( local_camera_offset ); - camera_position_global = frame_center_global + head_offset + camera_offset; - - if (mAvatarObject.notNull()) - { - LLVector3d camera_lag_d; - F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); - LLVector3 target_lag; - LLVector3 vel = getVelocity(); - - // lag by appropriate amount for flying - F32 time_in_air = mAvatarObject->mTimeInAir.getElapsedTimeF32(); - if(!mCameraAnimating && mAvatarObject->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) - { - LLVector3 frame_at_axis = mFrameAgent.getAtAxis(); - frame_at_axis -= projected_vec(frame_at_axis, getReferenceUpVector()); - frame_at_axis.normalize(); - - //transition smoothly in air mode, to avoid camera pop - F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; - u = llclamp(u, 0.f, 1.f); - - lag_interp *= u; - - if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == mAvatarObject->getID()) - { - // disable camera lag when using mouse-directed steering - target_lag.clearVec(); - } - else - { - target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; - } - - mCameraLag = lerp(mCameraLag, target_lag, lag_interp); - - F32 lag_dist = mCameraLag.magVec(); - if (lag_dist > MAX_CAMERA_LAG) - { - mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; - } - - // clamp camera lag so that avatar is always in front - F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; - if (dot < -(MIN_CAMERA_LAG * u)) - { - mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; - } - } - else - { - mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); - } - - camera_lag_d.setVec(mCameraLag); - camera_position_global = camera_position_global - camera_lag_d; - } - } - } - else - { - LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); - // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value - camera_position_global = focusPosGlobal + mCameraFocusOffset; - } - - if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike()) - { - LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal( - camera_position_global); - bool constrain = true; - if(regionp && regionp->canManageEstate()) - { - constrain = false; - } - if(constrain) - { - F32 max_dist = ( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) ? - APPEARANCE_MAX_ZOOM : mDrawDistance; - - LLVector3d camera_offset = camera_position_global - - gAgent.getPositionGlobal(); - F32 camera_distance = (F32)camera_offset.magVec(); - - if(camera_distance > max_dist) - { - camera_position_global = gAgent.getPositionGlobal() + - (max_dist / camera_distance) * camera_offset; - isConstrained = TRUE; - } - } - -// JC - Could constrain camera based on parcel stuff here. -// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); -// -// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) -// { -// camera_position_global = last_position_global; -// -// isConstrained = TRUE; -// } - } - - // Don't let camera go underground - F32 camera_min_off_ground = getCameraMinOffGround(); - - camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); - - if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground) - { - camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground; - isConstrained = TRUE; - } - - - if (hit_limit) - { - *hit_limit = isConstrained; - } - - return camera_position_global; -} - - -//----------------------------------------------------------------------------- -// handleScrollWheel() -//----------------------------------------------------------------------------- -void LLAgent::handleScrollWheel(S32 clicks) -{ - if ( mCameraMode == CAMERA_MODE_FOLLOW && gAgent.getFocusOnAvatar()) - { - if ( ! mFollowCam.getPositionLocked() ) // not if the followCam position is locked in place - { - mFollowCam.zoom( clicks ); - if ( mFollowCam.isZoomedToMinimumDistance() ) - { - changeCameraToMouselook(FALSE); - } - } - } - else - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); - - // Block if camera is animating - if (mCameraAnimating) - { - return; - } - - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom_factor = (F32)pow(0.8, -clicks); - cameraZoomIn(zoom_factor); - } - else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - F32 current_zoom_fraction = mTargetCameraDistance / (mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); - - cameraOrbitIn(current_zoom_fraction * mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - } - else - { - F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); - cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); - } - } -} - - -//----------------------------------------------------------------------------- -// getCameraMinOffGround() -//----------------------------------------------------------------------------- -F32 LLAgent::getCameraMinOffGround() -{ - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } - else - { - if (gSavedSettings.getBOOL("DisableCameraConstraints")) - { - return -1000.f; - } - else - { - return 0.5f; - } - } -} - - -//----------------------------------------------------------------------------- -// resetCamera() -//----------------------------------------------------------------------------- -void LLAgent::resetCamera() -{ - // Remove any pitch from the avatar - LLVector3 at = mFrameAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - // have to explicitly clear field of view zoom now - mCameraFOVZoomFactor = 0.f; - - updateCamera(); -} - -//----------------------------------------------------------------------------- -// changeCameraToMouselook() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToMouselook(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - // visibility changes at end of animation - gViewerWindow->getWindow()->resetBusyCount(); - - // Menus should not remain open on switching to mouselook... - LLMenuGL::sMenuContainer->hideMenus(); - - // unpause avatar animation - mPauseRequest = NULL; - - LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", TRUE); - gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - if (mAvatarObject.notNull()) - { - mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->stopMotion( ANIM_AGENT_BREATHE_ROT ); - } - - //gViewerWindow->stopGrab(); - LLSelectMgr::getInstance()->deselectAll(); - gViewerWindow->hideCursor(); - gViewerWindow->moveCursorToCenter(); - - if( mCameraMode != CAMERA_MODE_MOUSELOOK ) - { - gFocusMgr.setKeyboardFocus( NULL ); - - mLastCameraMode = mCameraMode; - mCameraMode = CAMERA_MODE_MOUSELOOK; - U32 old_flags = mControlFlags; - setControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - } -} - - -//----------------------------------------------------------------------------- -// changeCameraToDefault() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToDefault() -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - if (LLFollowCamMgr::getActiveFollowCamParams()) - { - changeCameraToFollow(); - } - else - { - changeCameraToThirdPerson(); - } -} - - -// Ventrella -//----------------------------------------------------------------------------- -// changeCameraToFollow() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToFollow(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - if( mCameraMode != CAMERA_MODE_FOLLOW ) - { - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - animate = FALSE; - } - startCameraAnimation(); - - mLastCameraMode = mCameraMode; - mCameraMode = CAMERA_MODE_FOLLOW; - - // bang-in the current focus, position, and up vector of the follow cam - mFollowCam.reset( mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis ); - - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - if (mAvatarObject.notNull()) - { - mAvatarObject->mPelvisp->setPosition(LLVector3::zero); - mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - // unpause avatar animation - mPauseRequest = NULL; - - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - } -} - -//----------------------------------------------------------------------------- -// changeCameraToThirdPerson() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToThirdPerson(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - gViewerWindow->getWindow()->resetBusyCount(); - - mCameraZoomFraction = INITIAL_ZOOM_FRACTION; - - if (mAvatarObject.notNull()) - { - if (!mAvatarObject->mIsSitting) - { - mAvatarObject->mPelvisp->setPosition(LLVector3::zero); - } - mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - LLVector3 at_axis; - - // unpause avatar animation - mPauseRequest = NULL; - - if( mCameraMode != CAMERA_MODE_THIRD_PERSON ) - { - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - mCameraLag.clearVec(); - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - mCurrentCameraDistance = MIN_CAMERA_DISTANCE; - mTargetCameraDistance = MIN_CAMERA_DISTANCE; - animate = FALSE; - } - mLastCameraMode = mCameraMode; - mCameraMode = CAMERA_MODE_THIRD_PERSON; - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - } - - // Remove any pitch from the avatar - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~obj_rot); - } - else - { - at_axis = mFrameAgent.getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis); - } - - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } -} - -//----------------------------------------------------------------------------- -// changeCameraToCustomizeAvatar() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - // - //setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up - // - gViewerWindow->getWindow()->resetBusyCount(); - - if (gFaceEditToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - if (camera_animate) - { - // - if(gSavedSettings.getBOOL("AppearanceCameraMovement")) - // - startCameraAnimation(); - } - - // Remove any pitch from the avatar - //LLVector3 at = mFrameAgent.getAtAxis(); - //at.mV[VZ] = 0.f; - //at.normalize(); - //gAgent.resetAxes(at); - - if( mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR ) - { - mLastCameraMode = mCameraMode; - mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - gFocusMgr.setKeyboardFocus( NULL ); - gFocusMgr.setMouseCapture( NULL ); - - LLVOAvatar::onCustomizeStart(); - } - - if (mAvatarObject.notNull()) - { - if(avatar_animate) - { - // Remove any pitch from the avatar - LLVector3 at = mFrameAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - - sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); - mCustomAnim = TRUE ; - mAvatarObject->startMotion(ANIM_AGENT_CUSTOMIZE); - LLMotion* turn_motion = mAvatarObject->findMotion(ANIM_AGENT_CUSTOMIZE); - - if (turn_motion) - { - mAnimationDuration = turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP; - - } - else - { - mAnimationDuration = gSavedSettings.getF32("ZoomTime"); - } - } - - - - gAgent.setFocusGlobal(LLVector3d::zero); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - - // - if(!gSavedSettings.getBOOL("AppearanceCameraMovement")) - { - //hmm - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - -} - - -// -// Focus point management -// - -//----------------------------------------------------------------------------- -// startCameraAnimation() -//----------------------------------------------------------------------------- -void LLAgent::startCameraAnimation() -{ - mAnimationCameraStartGlobal = getCameraPositionGlobal(); - mAnimationFocusStartGlobal = mFocusGlobal; - mAnimationTimer.reset(); - mCameraAnimating = TRUE; - mAnimationDuration = gSavedSettings.getF32("ZoomTime"); -} - -//----------------------------------------------------------------------------- -// stopCameraAnimation() -//----------------------------------------------------------------------------- -void LLAgent::stopCameraAnimation() -{ - mCameraAnimating = FALSE; -} - -void LLAgent::clearFocusObject() -{ - if (mFocusObject.notNull()) - { - startCameraAnimation(); - - setFocusObject(NULL); - mFocusObjectOffset.clearVec(); - } -} - -void LLAgent::setFocusObject(LLViewerObject* object) -{ - mFocusObject = object; -} - -// Focus on a point, but try to keep camera position stable. -//----------------------------------------------------------------------------- -// setFocusGlobal() -//----------------------------------------------------------------------------- -void LLAgent::setFocusGlobal(const LLPickInfo& pick) -{ - LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); - - if (objectp) - { - // focus on object plus designated offset - // which may or may not be same as pick.mPosGlobal - setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); - } - else - { - // focus directly on point where user clicked - setFocusGlobal(pick.mPosGlobal, pick.mObjectID); - } -} - - -void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) -{ - setFocusObject(gObjectList.findObject(object_id)); - LLVector3d old_focus = mFocusTargetGlobal; - LLViewerObject *focus_obj = mFocusObject; - - // if focus has changed - if (old_focus != focus) - { - if (focus.isExactlyZero()) - { - if (mAvatarObject.notNull()) - { - mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = getPositionGlobal(); - } - mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; - mCameraFocusOffset = mCameraFocusOffsetTarget; - setLookAt(LOOKAT_TARGET_CLEAR); - } - else - { - mFocusTargetGlobal = focus; - if (!focus_obj) - { - mCameraFOVZoomFactor = 0.f; - } - - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; - - startCameraAnimation(); - - if (focus_obj) - { - if (focus_obj->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); - } - } - } - else // focus == mFocusTargetGlobal - { - if (focus.isExactlyZero()) - { - if (mAvatarObject.notNull()) - { - mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = getPositionGlobal(); - } - } - mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; - mCameraFocusOffset = mCameraFocusOffsetTarget; - } - - if (mFocusObject.notNull()) - { - // for attachments, make offset relative to avatar, not the attachment - if (mFocusObject->isAttachment()) - { - while (mFocusObject.notNull() // DEV-29123 - can crash with a messed-up attachment - && !mFocusObject->isAvatar()) - { - mFocusObject = (LLViewerObject*) mFocusObject->getParent(); - } - setFocusObject((LLViewerObject*)mFocusObject); - } - updateFocusOffset(); - } -} - -// Used for avatar customization -//----------------------------------------------------------------------------- -// setCameraPosAndFocusGlobal() -//----------------------------------------------------------------------------- -void LLAgent::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id) -{ - LLVector3d old_focus = mFocusTargetGlobal; - - F64 focus_delta_squared = (old_focus - focus).magVecSquared(); - const F64 ANIM_EPSILON_SQUARED = 0.0001; - if( focus_delta_squared > ANIM_EPSILON_SQUARED ) - { - startCameraAnimation(); - - if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) - { - // Compensate for the fact that the camera has already been offset to make room for LLFloaterCustomize. - mAnimationCameraStartGlobal -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * calcCustomizeAvatarUIOffset( mAnimationCameraStartGlobal )); - } - } - - //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); - setFocusObject(gObjectList.findObject(object_id)); - mFocusTargetGlobal = focus; - mCameraFocusOffsetTarget = camera_pos - focus; - mCameraFocusOffset = mCameraFocusOffsetTarget; - - if (mFocusObject) - { - if (mFocusObject->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); - } - - if( mCameraAnimating ) - { - const F64 ANIM_METERS_PER_SECOND = 10.0; - const F64 MIN_ANIM_SECONDS = 0.5; - F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); - setAnimationDuration( (F32)anim_duration ); - } - - updateFocusOffset(); -} - -//----------------------------------------------------------------------------- -// setSitCamera() -//----------------------------------------------------------------------------- -void LLAgent::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus) -{ - BOOL camera_enabled = !object_id.isNull(); - - if (camera_enabled) - { - LLViewerObject *reference_object = gObjectList.findObject(object_id); - if (reference_object) - { - //convert to root object relative? - mSitCameraPos = camera_pos; - mSitCameraFocus = camera_focus; - mSitCameraReferenceObject = reference_object; - mSitCameraEnabled = TRUE; - } - } - else - { - mSitCameraPos.clearVec(); - mSitCameraFocus.clearVec(); - mSitCameraReferenceObject = NULL; - mSitCameraEnabled = FALSE; - } -} - -//----------------------------------------------------------------------------- -// setFocusOnAvatar() -//----------------------------------------------------------------------------- -void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) -{ - if (focus_on_avatar != mFocusOnAvatar) - { - if (animate) - { - startCameraAnimation(); - } - else - { - stopCameraAnimation(); - } - } - - //RN: when focused on the avatar, we're not "looking" at it - // looking implies intent while focusing on avatar means - // you're just walking around with a camera on you...eesh. - if (!mFocusOnAvatar && focus_on_avatar) - { - setFocusGlobal(LLVector3d::zero); - mCameraFOVZoomFactor = 0.f; - if (mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - LLVector3 at_axis; - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~obj_rot); - } - else - { - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis); - } - } - } - // unlocking camera from avatar - else if (mFocusOnAvatar && !focus_on_avatar) - { - // keep camera focus point consistent, even though it is now unlocked - setFocusGlobal(getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); - } - - mFocusOnAvatar = focus_on_avatar; -} - -//----------------------------------------------------------------------------- -// heardChat() -//----------------------------------------------------------------------------- -void LLAgent::heardChat(const LLUUID& id) -{ - // log text and voice chat to speaker mgr - // for keeping track of active speakers, etc. - LLLocalSpeakerMgr::getInstance()->speakerChatted(id); - - // don't respond to your own voice - if (id == getID()) return; - - if (ll_rand(2) == 0) - { - LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); - setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); - } - - mLastChatterID = id; - mChatTimer.reset(); -} - -//----------------------------------------------------------------------------- -// lookAtLastChat() -//----------------------------------------------------------------------------- -void LLAgent::lookAtLastChat() -{ - // Block if camera is animating or not in normal third person camera mode - if (mCameraAnimating || !cameraThirdPerson()) - { - return; - } - - LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); - if (chatter) - { - LLVector3 delta_pos; - if (chatter->isAvatar()) - { - LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; - if (mAvatarObject.notNull() && chatter_av->mHeadp) - { - delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); - } - else - { - delta_pos = chatter->getPositionAgent() - getPositionAgent(); - } - delta_pos.normalize(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - if (chatter_av->mHeadp) - { - setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - } - else - { - setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - } - setFocusOnAvatar(FALSE, TRUE); - } - else - { - delta_pos = chatter->getRenderPosition() - getPositionAgent(); - delta_pos.normalize(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - setFocusOnAvatar(FALSE, TRUE); - } - } -} - -void LLAgent::lookAtObject(LLUUID object_id, ECameraPosition camera_pos) -{ - // Block if camera is animating or not in normal third person camera mode - if (mCameraAnimating || !cameraThirdPerson()) - { - return; - } - - LLViewerObject *chatter = gObjectList.findObject(object_id); - if (chatter) - { - LLVector3 delta_pos; - if (chatter->isAvatar()) - { - LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; - if (!mAvatarObject.isNull() && chatter_av->mHeadp) - { - delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); - } - else - { - delta_pos = chatter->getPositionAgent() - getPositionAgent(); - } - delta_pos.normVec(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normVec(); - LLVector3 up = left % delta_pos; - up.normVec(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - F32 radius = chatter_av->getVObjRadius(); - LLVector3d view_dist(radius, radius, 0.0f); - - if (chatter_av->mHeadp) - { - setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), object_id); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - break; - case CAMERA_POSITION_OBJECT: - mCameraFocusOffsetTarget = view_dist; - break; - } - } - else - { - setFocusGlobal(chatter->getPositionGlobal(), object_id); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - break; - case CAMERA_POSITION_OBJECT: - mCameraFocusOffsetTarget = view_dist; - break; - } - } - setFocusOnAvatar(FALSE, TRUE); - } - else - { - delta_pos = chatter->getRenderPosition() - getPositionAgent(); - delta_pos.normVec(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normVec(); - LLVector3 up = left % delta_pos; - up.normVec(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusGlobal(chatter->getPositionGlobal(), object_id); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - break; - case CAMERA_POSITION_OBJECT: - F32 radius = chatter->getVObjRadius(); - LLVector3d view_dist(radius, radius, 0.0f); - mCameraFocusOffsetTarget = view_dist; - break; - } - - setFocusOnAvatar(FALSE, TRUE); - } - } -} - -const F32 SIT_POINT_EXTENTS = 0.2f; - -void LLAgent::setStartPosition( U32 location_id ) -{ - LLViewerObject *object; - - if ( !(gAgentID == LLUUID::null) ) - { - // we've got an ID for an agent viewerobject - object = gObjectList.findObject(gAgentID); - if (object) - { - // we've got the viewer object - // Sometimes the agent can be velocity interpolated off of - // this simulator. Clamp it to the region the agent is - // in, a little bit in on each side. - const F32 INSET = 0.5f; //meters - const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters(); - - LLVector3 agent_pos = getPositionAgent(); - LLVector3 agent_look_at = mFrameAgent.getAtAxis(); - - if (mAvatarObject.notNull()) - { - // the z height is at the agent's feet - agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ]; - } - - agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET ); - agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET ); - - // Don't let them go below ground, or too high. - agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ], - mRegionp->getLandHeightRegion( agent_pos ), - LLWorld::getInstance()->getRegionMaxHeight() ); - // Send the CapReq - - LLSD body; - - std::string url = gAgent.getRegion()->getCapability("HomeLocation"); - std::ostringstream strBuffer; - if( url.empty() ) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetStartLocationRequest); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msg->nextBlockFast( _PREHASH_StartLocationData); - // corrected by sim - msg->addStringFast(_PREHASH_SimName, ""); - msg->addU32Fast(_PREHASH_LocationID, location_id); - msg->addVector3Fast(_PREHASH_LocationPos, agent_pos); - msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis()); - - // Reliable only helps when setting home location. Last - // location is sent on quit, and we don't have time to ack - // the packets. - msg->sendReliable(mRegionp->getHost()); - - const U32 HOME_INDEX = 1; - if( HOME_INDEX == location_id ) - { - setHomePosRegion( mRegionp->getHandle(), getPositionAgent() ); - } - } - else - { - strBuffer << location_id; - body["HomeLocation"]["LocationId"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VX]; - body["HomeLocation"]["LocationPos"]["X"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VY]; - body["HomeLocation"]["LocationPos"]["Y"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VZ]; - body["HomeLocation"]["LocationPos"]["Z"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VX]; - body["HomeLocation"]["LocationLookAt"]["X"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VY]; - body["HomeLocation"]["LocationLookAt"]["Y"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VZ]; - body["HomeLocation"]["LocationLookAt"]["Z"] = strBuffer.str(); - - LLHTTPClient::post( url, body, new LLHomeLocationResponder() ); - } - } - else - { - llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl; - } - } -} - -void LLAgent::requestStopMotion( LLMotion* motion ) -{ - // Notify all avatars that a motion has stopped. - // This is needed to clear the animation state bits - LLUUID anim_state = motion->getID(); - onAnimStop(motion->getID()); - - // if motion is not looping, it could have stopped by running out of time - // so we need to tell the server this -// llinfos << "Sending stop for motion " << motion->getName() << llendl; - sendAnimationRequest( anim_state, ANIM_REQUEST_STOP ); -} - -void LLAgent::onAnimStop(const LLUUID& id) -{ - // handle automatic state transitions (based on completion of animation playback) - if(id == ANIM_AGENT_STAND - // - // I really do not like doing this - || id == ANIM_AGENT_STAND_1 - || id == ANIM_AGENT_STAND_2 - || id == ANIM_AGENT_STAND_3 - || id == ANIM_AGENT_STAND_4) - // - { - // - if(LLAO::isEnabled()) - LLAO::mTimer->pause();//Timer only pauses if its not paused, check is inside function. - // - stopFidget(); - } - else if (id == ANIM_AGENT_AWAY) - { - clearAFK(); - } - else if (id == ANIM_AGENT_STANDUP) - { - // send stand up command - setControlFlags(AGENT_CONTROL_FINISH_ANIM); - - // now trigger dusting self off animation - if (mAvatarObject.notNull() && !mAvatarObject->mBelowWater && rand() % 3 == 0) - sendAnimationRequest( ANIM_AGENT_BRUSH, ANIM_REQUEST_START ); - } - else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND) - { - setControlFlags(AGENT_CONTROL_FINISH_ANIM); - } -} - -BOOL LLAgent::isGodlike() const -{ - return mAgentAccess.isGodlike(); -} - -U8 LLAgent::getGodLevel() const -{ - return mAgentAccess.getGodLevel(); -} - -bool LLAgent::wantsPGOnly() const -{ - return mAgentAccess.wantsPGOnly(); -} - -bool LLAgent::canAccessMature() const -{ - return mAgentAccess.canAccessMature(); -} - -bool LLAgent::canAccessAdult() const -{ - return mAgentAccess.canAccessAdult(); -} - -bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const -{ - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle( region_handle ); - if( regionp ) - { - switch( regionp->getSimAccess() ) - { - case SIM_ACCESS_MATURE: - if( !canAccessMature() ) - return false; - break; - case SIM_ACCESS_ADULT: - if( !canAccessAdult() ) - return false; - break; - default: - // Oh, go on and hear the silly noises. - break; - } - } - - return true; -} - -bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const -{ - U64 region_handle = to_region_handle_global( pos_global.mdV[0], pos_global.mdV[1] ); - return canAccessMaturityInRegion( region_handle ); -} - -bool LLAgent::prefersPG() const -{ - return mAgentAccess.prefersPG(); -} - -bool LLAgent::prefersMature() const -{ - return mAgentAccess.prefersMature(); -} - -bool LLAgent::prefersAdult() const -{ - return mAgentAccess.prefersAdult(); -} - -bool LLAgent::isTeen() const -{ - return mAgentAccess.isTeen(); -} - -bool LLAgent::isMature() const -{ - return mAgentAccess.isMature(); -} - -bool LLAgent::isAdult() const -{ - return mAgentAccess.isAdult(); -} - -void LLAgent::setTeen(bool teen) -{ - mAgentAccess.setTeen(teen); -} - -//static -int LLAgent::convertTextToMaturity(char text) -{ - return LLAgentAccess::convertTextToMaturity(text); -} - -bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) -{ - // Update agent access preference on the server - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - if (!url.empty()) - { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - if (preferredMaturity == SIM_ACCESS_PG) - { - access_prefs["max"] = "PG"; - } - else if (preferredMaturity == SIM_ACCESS_MATURE) - { - access_prefs["max"] = "M"; - } - if (preferredMaturity == SIM_ACCESS_ADULT) - { - access_prefs["max"] = "A"; - } - - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " - << url << llendl; - LLHTTPClient::post(url, body, new LLHTTPClient::Responder()); // Ignore response - return true; - } - return false; -} - -BOOL LLAgent::getAdminOverride() const -{ - return mAgentAccess.getAdminOverride(); -} - -void LLAgent::setMaturity(char text) -{ - mAgentAccess.setMaturity(text); -} - -void LLAgent::setAdminOverride(BOOL b) -{ - mAgentAccess.setAdminOverride(b); -} - -void LLAgent::setGodLevel(U8 god_level) -{ - mAgentAccess.setGodLevel(god_level); -} - -void LLAgent::setAOTransition() -{ - mAgentAccess.setTransition(); -} - -const LLAgentAccess& LLAgent::getAgentAccess() -{ - return mAgentAccess; -} - - -void LLAgent::buildFullname(std::string& name) const -{ - if (mAvatarObject.notNull()) - { - name = mAvatarObject->getFullname(); - } -} - -void LLAgent::buildFullnameAndTitle(std::string& name) const -{ - if (isGroupMember()) - { - name = mGroupTitle; - name += ' '; - } - else - { - name.erase(0, name.length()); - } - - if (mAvatarObject.notNull()) - { - name += mAvatarObject->getFullname(); - } -} - -BOOL LLAgent::isInGroup(const LLUUID& group_id) const -{ - if (isGodlike()) - return true; - - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - return TRUE; - } - } - return FALSE; -} - -// This implementation should mirror LLAgentInfo::hasPowerInGroup -BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const -{ - if (isGodlike()) - return true; - - // GP_NO_POWERS can also mean no power is enough to grant an ability. - if (GP_NO_POWERS == power) return FALSE; - - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - return (BOOL)((mGroups.get(i).mPowers & power) > 0); - } - } - return FALSE; -} - -BOOL LLAgent::hasPowerInActiveGroup(U64 power) const -{ - return (mGroupID.notNull() && (hasPowerInGroup(mGroupID, power))); -} - -U64 LLAgent::getPowerInGroup(const LLUUID& group_id) const -{ - if (isGodlike()) - return GP_ALL_POWERS; - - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - return (mGroups.get(i).mPowers); - } - } - - return GP_NO_POWERS; -} - -BOOL LLAgent::getGroupData(const LLUUID& group_id, LLGroupData& data) const -{ - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - data = mGroups.get(i); - return TRUE; - } - } - return FALSE; -} - -S32 LLAgent::getGroupContribution(const LLUUID& group_id) const -{ - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - S32 contribution = mGroups.get(i).mContribution; - return contribution; - } - } - return 0; -} - -BOOL LLAgent::setGroupContribution(const LLUUID& group_id, S32 contribution) -{ - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - mGroups.get(i).mContribution = contribution; - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("SetGroupContribution"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgentID); - msg->addUUID("SessionID", gAgentSessionID); - msg->nextBlock("Data"); - msg->addUUID("GroupID", group_id); - msg->addS32("Contribution", contribution); - sendReliableMessage(); - return TRUE; - } - } - return FALSE; -} - -BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile) -{ - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) - { - if(mGroups.get(i).mID == group_id) - { - mGroups.get(i).mAcceptNotices = accept_notices; - mGroups.get(i).mListInProfile = list_in_profile; - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("SetGroupAcceptNotices"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgentID); - msg->addUUID("SessionID", gAgentSessionID); - msg->nextBlock("Data"); - msg->addUUID("GroupID", group_id); - msg->addBOOL("AcceptNotices", accept_notices); - msg->nextBlock("NewData"); - msg->addBOOL("ListInProfile", list_in_profile); - sendReliableMessage(); - return TRUE; - } - } - return FALSE; -} - -// utility to build a location string -void LLAgent::buildLocationString(std::string& str) -{ - const LLVector3& agent_pos_region = getPositionAgent(); - S32 pos_x = S32(agent_pos_region.mV[VX]); - S32 pos_y = S32(agent_pos_region.mV[VY]); - S32 pos_z = S32(agent_pos_region.mV[VZ]); - - // Round the numbers based on the velocity - LLVector3 agent_velocity = getVelocity(); - F32 velocity_mag_sq = agent_velocity.magVecSquared(); - - const F32 FLY_CUTOFF = 6.f; // meters/sec - const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; - const F32 WALK_CUTOFF = 1.5f; // meters/sec - const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; - - if (velocity_mag_sq > FLY_CUTOFF_SQ) - { - pos_x -= pos_x % 4; - pos_y -= pos_y % 4; - } - else if (velocity_mag_sq > WALK_CUTOFF_SQ) - { - pos_x -= pos_x % 2; - pos_y -= pos_y % 2; - } - - // create a defult name and description for the landmark - std::string buffer; - if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() ) - { - // the parcel doesn't have a name - buffer = llformat("%.32s (%d, %d, %d)", - getRegion()->getName().c_str(), - pos_x, pos_y, pos_z); - } - else - { - // the parcel has a name, so include it in the landmark name - buffer = llformat("%.32s, %.32s (%d, %d, %d)", - LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(), - getRegion()->getName().c_str(), - pos_x, pos_y, pos_z); - } - str = buffer; -} - -LLQuaternion LLAgent::getHeadRotation() -{ - if (mAvatarObject.isNull() || !mAvatarObject->mPelvisp || !mAvatarObject->mHeadp) - { - return LLQuaternion::DEFAULT; - } - - if (!gAgent.cameraMouselook()) - { - return mAvatarObject->getRotation(); - } - - // We must be in mouselook - LLVector3 look_dir( LLViewerCamera::getInstance()->getAtAxis() ); - LLVector3 up = look_dir % mFrameAgent.getLeftAxis(); - LLVector3 left = up % look_dir; - - LLQuaternion rot(look_dir, left, up); - if (mAvatarObject->getParent()) - { - rot = rot * ~mAvatarObject->getParent()->getRotation(); - } - - return rot; -} - -void LLAgent::sendAnimationRequests(LLDynamicArray &anim_ids, EAnimRequest request) -{ - if (gAgentID.isNull()) - { - return; - } - - S32 num_valid_anims = 0; - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentAnimation); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - - for (S32 i = 0; i < anim_ids.count(); i++) - { - if (anim_ids[i].isNull()) - { - continue; - } - msg->nextBlockFast(_PREHASH_AnimationList); - msg->addUUIDFast(_PREHASH_AnimID, (anim_ids[i]) ); - msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); - num_valid_anims++; - } - - msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); - msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); - if (num_valid_anims) - { - sendReliableMessage(); - } -} - -void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request) -{ - if (gAgentID.isNull() || anim_id.isNull() || !mRegionp) - { - return; - } - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentAnimation); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - - msg->nextBlockFast(_PREHASH_AnimationList); - msg->addUUIDFast(_PREHASH_AnimID, (anim_id) ); - msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); - - msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); - msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); - sendReliableMessage(); -} - -void LLAgent::sendWalkRun(bool running) -{ - LLMessageSystem* msgsys = gMessageSystem; - if (msgsys) - { - msgsys->newMessageFast(_PREHASH_SetAlwaysRun); - msgsys->nextBlockFast(_PREHASH_AgentData); - msgsys->addUUIDFast(_PREHASH_AgentID, getID()); - msgsys->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(running) ); - sendReliableMessage(); - } -} - -void LLAgent::friendsChanged() -{ - LLCollectProxyBuddies collector; - LLAvatarTracker::instance().applyFunctor(collector); - mProxyForAgents = collector.mProxy; -} - -BOOL LLAgent::isGrantedProxy(const LLPermissions& perm) -{ - return (mProxyForAgents.count(perm.getOwner()) > 0); -} - -BOOL LLAgent::allowOperation(PermissionBit op, - const LLPermissions& perm, - U64 group_proxy_power, - U8 god_minimum) -{ - // Check god level. - if (getGodLevel() >= god_minimum) return TRUE; - - if (!perm.isOwned()) return FALSE; - - // A group member with group_proxy_power can act as owner. - BOOL is_group_owned; - LLUUID owner_id; - perm.getOwnership(owner_id, is_group_owned); - LLUUID group_id(perm.getGroup()); - LLUUID agent_proxy(getID()); - - if (is_group_owned) - { - if (hasPowerInGroup(group_id, group_proxy_power)) - { - // Let the member assume the group's id for permission requests. - agent_proxy = owner_id; - } - } - else - { - // Check for granted mod permissions. - if ((PERM_OWNER != op) && isGrantedProxy(perm)) - { - agent_proxy = owner_id; - } - } - - // This is the group id to use for permission requests. - // Only group members may use this field. - LLUUID group_proxy = LLUUID::null; - if (group_id.notNull() && isInGroup(group_id)) - { - group_proxy = group_id; - } - - // We now have max ownership information. - if (PERM_OWNER == op) - { - // This this was just a check for ownership, we can now return the answer. - return (agent_proxy == owner_id); - } - - return perm.allowOperationBy(op, agent_proxy, group_proxy); -} - - -void LLAgent::getName(std::string& name) -{ - name.clear(); - - if (mAvatarObject.notNull()) - { - LLNameValue *first_nv = mAvatarObject->getNVPair("FirstName"); - LLNameValue *last_nv = mAvatarObject->getNVPair("LastName"); - if (first_nv && last_nv) - { - name = first_nv->printData() + " " + last_nv->printData(); - } - else - { - llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl; - } - } - else - { - name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName"); - } -} - -const LLColor4 &LLAgent::getEffectColor() -{ - return mEffectColor; -} - -void LLAgent::setEffectColor(const LLColor4 &color) -{ - mEffectColor = color; -} - -void LLAgent::initOriginGlobal(const LLVector3d &origin_global) -{ - mAgentOriginGlobal = origin_global; -} - -void update_group_floaters(const LLUUID& group_id) -{ - LLFloaterGroupInfo::refreshGroup(group_id); - - // update avatar info - LLFloaterAvatarInfo* fa = LLFloaterAvatarInfo::getInstance(gAgent.getID()); - if(fa) - { - fa->resetGroupList(); - } - - if (gIMMgr) - { - // update the talk view - gIMMgr->refresh(); - } - - gAgent.fireEvent(new LLEvent(&gAgent, "new group"), ""); -} - -// static -void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **) -{ - LLUUID agent_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - - if (agent_id != gAgentID) - { - llwarns << "processAgentDropGroup for agent other than me" << llendl; - return; - } - - LLUUID group_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id ); - - // Remove the group if it already exists remove it and add the new data to pick up changes. - LLGroupData gd; - gd.mID = group_id; - S32 index = gAgent.mGroups.find(gd); - if (index != -1) - { - gAgent.mGroups.remove(index); - if (gAgent.getGroupID() == group_id) - { - gAgent.mGroupID.setNull(); - gAgent.mGroupPowers = 0; - gAgent.mGroupName.clear(); - gAgent.mGroupTitle.clear(); - } - - // refresh all group information - gAgent.sendAgentDataUpdateRequest(); - - LLGroupMgr::getInstance()->clearGroupData(group_id); - // close the floater for this group, if any. - LLFloaterGroupInfo::closeGroup(group_id); - // refresh the group panel of the search window, if necessary. - LLFloaterDirectory::refreshGroup(group_id); - } - else - { - llwarns << "processAgentDropGroup, agent is not part of group " << group_id << llendl; - } -} - -class LLAgentDropGroupViewerNode : public LLHTTPNode -{ - virtual void post( - LLHTTPNode::ResponsePtr response, - const LLSD& context, - const LLSD& input) const - { - - if ( - !input.isMap() || - !input.has("body") ) - { - //what to do with badly formed message? - response->status(400); - response->result(LLSD("Invalid message parameters")); - } - - LLSD body = input["body"]; - if ( body.has("body") ) - { - //stupid message system doubles up the "body"s - body = body["body"]; - } - - if ( - body.has("AgentData") && - body["AgentData"].isArray() && - body["AgentData"][0].isMap() ) - { - llinfos << "VALID DROP GROUP" << llendl; - - //there is only one set of data in the AgentData block - LLSD agent_data = body["AgentData"][0]; - LLUUID agent_id; - LLUUID group_id; - - agent_id = agent_data["AgentID"].asUUID(); - group_id = agent_data["GroupID"].asUUID(); - - if (agent_id != gAgentID) - { - llwarns - << "AgentDropGroup for agent other than me" << llendl; - - response->notFound(); - return; - } - - // Remove the group if it already exists remove it - // and add the new data to pick up changes. - LLGroupData gd; - gd.mID = group_id; - S32 index = gAgent.mGroups.find(gd); - if (index != -1) - { - gAgent.mGroups.remove(index); - if (gAgent.getGroupID() == group_id) - { - gAgent.mGroupID.setNull(); - gAgent.mGroupPowers = 0; - gAgent.mGroupName.clear(); - gAgent.mGroupTitle.clear(); - } - - // refresh all group information - gAgent.sendAgentDataUpdateRequest(); - - LLGroupMgr::getInstance()->clearGroupData(group_id); - // close the floater for this group, if any. - LLFloaterGroupInfo::closeGroup(group_id); - // refresh the group panel of the search window, - //if necessary. - LLFloaterDirectory::refreshGroup(group_id); - } - else - { - llwarns - << "AgentDropGroup, agent is not part of group " - << group_id << llendl; - } - - response->result(LLSD()); - } - else - { - //what to do with badly formed message? - response->status(400); - response->result(LLSD("Invalid message parameters")); - } - } -}; - -LLHTTPRegistration - gHTTPRegistrationAgentDropGroupViewerNode( - "/message/AgentDropGroup"); - -// static -void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) -{ - LLUUID agent_id; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - - if (agent_id != gAgentID) - { - llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl; - return; - } - - S32 count = msg->getNumberOfBlocksFast(_PREHASH_GroupData); - LLGroupData group; - S32 index = -1; - bool need_floater_update = false; - for(S32 i = 0; i < count; ++i) - { - msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group.mID, i); - msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupInsigniaID, group.mInsigniaID, i); - msg->getU64(_PREHASH_GroupData, "GroupPowers", group.mPowers, i); - msg->getBOOL(_PREHASH_GroupData, "AcceptNotices", group.mAcceptNotices, i); - msg->getS32(_PREHASH_GroupData, "Contribution", group.mContribution, i); - msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group.mName, i); - - if(group.mID.notNull()) - { - need_floater_update = true; - // Remove the group if it already exists remove it and add the new data to pick up changes. - index = gAgent.mGroups.find(group); - if (index != -1) - { - gAgent.mGroups.remove(index); - } - gAgent.mGroups.put(group); - } - if (need_floater_update) - { - update_group_floaters(group.mID); - } - } - -} - -class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode -{ - virtual void post( - LLHTTPNode::ResponsePtr response, - const LLSD& context, - const LLSD& input) const - { - LLSD body = input["body"]; - if(body.has("body")) - body = body["body"]; - LLUUID agent_id = body["AgentData"][0]["AgentID"].asUUID(); - - if (agent_id != gAgentID) - { - llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl; - return; - } - - LLSD group_data = body["GroupData"]; - - LLSD::array_iterator iter_group = - group_data.beginArray(); - LLSD::array_iterator end_group = - group_data.endArray(); - int group_index = 0; - for(; iter_group != end_group; ++iter_group) - { - - LLGroupData group; - S32 index = -1; - bool need_floater_update = false; - - group.mID = (*iter_group)["GroupID"].asUUID(); - group.mPowers = ll_U64_from_sd((*iter_group)["GroupPowers"]); - group.mAcceptNotices = (*iter_group)["AcceptNotices"].asBoolean(); - group.mListInProfile = body["NewGroupData"][group_index]["ListInProfile"].asBoolean(); - group.mInsigniaID = (*iter_group)["GroupInsigniaID"].asUUID(); - group.mName = (*iter_group)["GroupName"].asString(); - group.mContribution = (*iter_group)["Contribution"].asInteger(); - - group_index++; - - if(group.mID.notNull()) - { - need_floater_update = true; - // Remove the group if it already exists remove it and add the new data to pick up changes. - index = gAgent.mGroups.find(group); - if (index != -1) - { - gAgent.mGroups.remove(index); - } - gAgent.mGroups.put(group); - } - if (need_floater_update) - { - update_group_floaters(group.mID); - } - } - } -}; - -LLHTTPRegistration - gHTTPRegistrationAgentGroupDataUpdateViewerNode ("/message/AgentGroupDataUpdate"); - -// static -void LLAgent::processAgentDataUpdate(LLMessageSystem *msg, void **) -{ - LLUUID agent_id; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - - if (agent_id != gAgentID) - { - llwarns << "processAgentDataUpdate for agent other than me" << llendl; - return; - } - - msg->getStringFast(_PREHASH_AgentData, _PREHASH_GroupTitle, gAgent.mGroupTitle); - LLUUID active_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_ActiveGroupID, active_id); - - - if(active_id.notNull()) - { - gAgent.mGroupID = active_id; - msg->getU64(_PREHASH_AgentData, "GroupPowers", gAgent.mGroupPowers); - msg->getString(_PREHASH_AgentData, _PREHASH_GroupName, gAgent.mGroupName); - } - else - { - gAgent.mGroupID.setNull(); - gAgent.mGroupPowers = 0; - gAgent.mGroupName.clear(); - } - - update_group_floaters(active_id); -} - -// static -void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **) -{ - S32 block_count = msg->getNumberOfBlocks("Data"); - for (S32 block_index = 0; block_index < block_count; block_index++) - { - BOOL take_controls; - U32 controls; - BOOL passon; - U32 i; - msg->getBOOL("Data", "TakeControls", take_controls, block_index); - if (take_controls) - { - // take controls - msg->getU32("Data", "Controls", controls, block_index ); - msg->getBOOL("Data", "PassToAgent", passon, block_index ); - U32 total_count = 0; - for (i = 0; i < TOTAL_CONTROLS; i++) - { - if (controls & ( 1 << i)) - { - if (passon) - { - gAgent.mControlsTakenPassedOnCount[i]++; - } - else - { - gAgent.mControlsTakenCount[i]++; - } - total_count++; - } - } - - // Any control taken? If so, might be first time. - if (total_count > 0) - { - LLFirstUse::useOverrideKeys(); - } - } - else - { - // release controls - msg->getU32("Data", "Controls", controls, block_index ); - msg->getBOOL("Data", "PassToAgent", passon, block_index ); - for (i = 0; i < TOTAL_CONTROLS; i++) - { - if (controls & ( 1 << i)) - { - if (passon) - { - gAgent.mControlsTakenPassedOnCount[i]--; - if (gAgent.mControlsTakenPassedOnCount[i] < 0) - { - gAgent.mControlsTakenPassedOnCount[i] = 0; - } - } - else - { - gAgent.mControlsTakenCount[i]--; - if (gAgent.mControlsTakenCount[i] < 0) - { - gAgent.mControlsTakenCount[i] = 0; - } - } - } - } - } - } -} - -/* -// static -void LLAgent::processControlTake(LLMessageSystem *msg, void **) -{ - U32 controls; - msg->getU32("Data", "Controls", controls ); - U32 passon; - msg->getBOOL("Data", "PassToAgent", passon ); - - S32 i; - S32 total_count = 0; - for (i = 0; i < TOTAL_CONTROLS; i++) - { - if (controls & ( 1 << i)) - { - if (passon) - { - gAgent.mControlsTakenPassedOnCount[i]++; - } - else - { - gAgent.mControlsTakenCount[i]++; - } - total_count++; - } - } - - // Any control taken? If so, might be first time. - if (total_count > 0) - { - LLFirstUse::useOverrideKeys(); - } -} - -// static -void LLAgent::processControlRelease(LLMessageSystem *msg, void **) -{ - U32 controls; - msg->getU32("Data", "Controls", controls ); - U32 passon; - msg->getBOOL("Data", "PassToAgent", passon ); - - S32 i; - for (i = 0; i < TOTAL_CONTROLS; i++) - { - if (controls & ( 1 << i)) - { - if (passon) - { - gAgent.mControlsTakenPassedOnCount[i]--; - if (gAgent.mControlsTakenPassedOnCount[i] < 0) - { - gAgent.mControlsTakenPassedOnCount[i] = 0; - } - } - else - { - gAgent.mControlsTakenCount[i]--; - if (gAgent.mControlsTakenCount[i] < 0) - { - gAgent.mControlsTakenCount[i] = 0; - } - } - } - } -} -*/ - -//static -void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data) -{ - gAgent.mNumPendingQueries--; - - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (!avatarp || avatarp->isDead()) - { - llwarns << "No avatar for user in cached texture update!" << llendl; - return; - } - - if (gAgent.cameraCustomizeAvatar()) - { - // ignore baked textures when in customize mode - return; - } - - S32 query_id; - mesgsys->getS32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, query_id); - - S32 num_texture_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_WearableData); - - - S32 num_results = 0; - for (S32 texture_block = 0; texture_block < num_texture_blocks; texture_block++) - { - LLUUID texture_id; - U8 texture_index; - - mesgsys->getUUIDFast(_PREHASH_WearableData, _PREHASH_TextureID, texture_id, texture_block); - mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block); - - if (texture_id.notNull() - && (S32)texture_index < BAKED_NUM_INDICES - && gAgent.mActiveCacheQueries[ texture_index ] == query_id) - { - //llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl; - avatarp->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id); - //avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id ); - gAgent.mActiveCacheQueries[ texture_index ] = 0; - num_results++; - } - } - - llinfos << "Received cached texture response for " << num_results << " textures." << llendl; - - avatarp->updateMeshTextures(); - - if (gAgent.mNumPendingQueries == 0) - { - // RN: not sure why composites are disabled at this point - avatarp->setCompositeUpdatesEnabled(TRUE); - gAgent.sendAgentSetAppearance(); - } -} - -BOOL LLAgent::anyControlGrabbed() const -{ - U32 i; - for (i = 0; i < TOTAL_CONTROLS; i++) - { - if (gAgent.mControlsTakenCount[i] > 0) - return TRUE; - if (gAgent.mControlsTakenPassedOnCount[i] > 0) - return TRUE; - } - return FALSE; -} - -BOOL LLAgent::isControlGrabbed(S32 control_index) const -{ - return mControlsTakenCount[control_index] > 0; -} - -void LLAgent::forceReleaseControls() -{ - gMessageSystem->newMessage("ForceScriptControlRelease"); - gMessageSystem->nextBlock("AgentData"); - gMessageSystem->addUUID("AgentID", getID()); - gMessageSystem->addUUID("SessionID", getSessionID()); - sendReliableMessage(); -} - -void LLAgent::setHomePosRegion( const U64& region_handle, const LLVector3& pos_region) -{ - mHaveHomePosition = TRUE; - mHomeRegionHandle = region_handle; - mHomePosRegion = pos_region; -} - -BOOL LLAgent::getHomePosGlobal( LLVector3d* pos_global ) -{ - if(!mHaveHomePosition) - { - return FALSE; - } - F32 x = 0; - F32 y = 0; - from_region_handle( mHomeRegionHandle, &x, &y); - pos_global->setVec( x + mHomePosRegion.mV[VX], y + mHomePosRegion.mV[VY], mHomePosRegion.mV[VZ] ); - return TRUE; -} - -void LLAgent::clearVisualParams(void *data) -{ - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp) - { - avatarp->clearVisualParamWeights(); - avatarp->updateVisualParams(); - } -} - -//--------------------------------------------------------------------------- -// Teleport -//--------------------------------------------------------------------------- - -// teleportCore() - stuff to do on any teleport -// protected -bool LLAgent::teleportCore(bool is_local) -{ - if(TELEPORT_NONE != mTeleportState) - { - llwarns << "Attempt to teleport when already teleporting." << llendl; - // - //return false; - teleportCancel(); - // - } - -#if 0 - // This should not exist. It has been added, removed, added, and now removed again. - // This change needs to come from the simulator. Otherwise, the agent ends up out of - // sync with other viewers. Discuss in DEV-14145/VWR-6744 before reenabling. - - // Stop all animation before actual teleporting - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp) - { - for ( LLVOAvatar::AnimIterator anim_it= avatarp->mPlayingAnimations.begin(); - anim_it != avatarp->mPlayingAnimations.end(); - ++anim_it) - { - avatarp->stopMotion(anim_it->first); - } - avatarp->processAnimationStateChanges(); - } -#endif - - // Don't call LLFirstUse::useTeleport because we don't know - // yet if the teleport will succeed. Look in - // process_teleport_location_reply - - // close the map and find panels so we can see our destination - LLFloaterWorldMap::hide(NULL); - LLFloaterDirectory::hide(NULL); - - // hide land floater too - it'll be out of date - LLFloaterLand::hideInstance(); - - LLViewerParcelMgr::getInstance()->deselectLand(); - LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL); - - // Close all pie menus, deselect land, etc. - // Don't change the camera until we know teleport succeeded. JC - // - if(gAgent.getFocusOnAvatar()) - // - resetView(FALSE); - - // local logic - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TELEPORT_COUNT); - if (is_local) - { - gAgent.setTeleportState( LLAgent::TELEPORT_LOCAL ); - } - else - { - gTeleportDisplay = TRUE; - gAgent.setTeleportState( LLAgent::TELEPORT_START ); - - //release geometry from old location - gPipeline.resetVertexBuffers(); - - if (gSavedSettings.getBOOL("SpeedRez")) - { - F32 draw_distance = gSavedSettings.getF32("RenderFarClip"); - if (gSavedDrawDistance < draw_distance) - { - gSavedDrawDistance = draw_distance; - } - gSavedSettings.setF32("SavedRenderFarClip", gSavedDrawDistance); - gSavedSettings.setF32("RenderFarClip", 32.0f); - } - make_ui_sound("UISndTeleportOut"); - } - - // MBW -- Let the voice client know a teleport has begun so it can leave the existing channel. - // This was breaking the case of teleporting within a single sim. Backing it out for now. -// gVoiceClient->leaveChannel(); - - return true; -} - -void LLAgent::teleportRequest( - const U64& region_handle, - const LLVector3& pos_local, - bool look_at_from_camera) -{ - LLViewerRegion* regionp = getRegion(); - bool is_local = (region_handle == to_region_handle(getPositionGlobal())); - if(regionp && teleportCore(is_local)) - { - llinfos << "TeleportLocationRequest: '" << region_handle << "':" << pos_local - << llendl; - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TeleportLocationRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msg->nextBlockFast(_PREHASH_Info); - msg->addU64("RegionHandle", region_handle); - msg->addVector3("Position", pos_local); - // - //LLVector3 look_at(0,1,0); - LLVector3 look_at = LLViewerCamera::getInstance()->getAtAxis(); - /*if (look_at_from_camera) - { - look_at = LLViewerCamera::getInstance()->getAtAxis(); - }*/ - // - msg->addVector3("LookAt", look_at); - sendReliableMessage(); - } -} - -// Landmark ID = LLUUID::null means teleport home -void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) -{ - LLViewerRegion *regionp = getRegion(); - if(regionp && teleportCore()) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_TeleportLandmarkRequest); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msg->addUUIDFast(_PREHASH_LandmarkID, landmark_asset_id); - sendReliableMessage(); - } -} - -void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) -{ - LLViewerRegion* regionp = getRegion(); - if(regionp && teleportCore()) - { - U32 teleport_flags = 0x0; - if (godlike) - { - teleport_flags |= TELEPORT_FLAGS_VIA_GODLIKE_LURE; - teleport_flags |= TELEPORT_FLAGS_DISABLE_CANCEL; - } - else - { - teleport_flags |= TELEPORT_FLAGS_VIA_LURE; - } - - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_TeleportLureRequest); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msg->addUUIDFast(_PREHASH_LureID, lure_id); - // teleport_flags is a legacy field, now derived sim-side: - msg->addU32("TeleportFlags", teleport_flags); - sendReliableMessage(); - } -} - - -// James Cook, July 28, 2005 -void LLAgent::teleportCancel() -{ - LLViewerRegion* regionp = getRegion(); - if(regionp) - { - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TeleportCancel"); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - sendReliableMessage(); - } - gTeleportDisplay = FALSE; - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); -} - - -void LLAgent::teleportViaLocation(const LLVector3d& pos_global) -{ - LLViewerRegion* regionp = getRegion(); - U64 handle = to_region_handle(pos_global); - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if(regionp && info) - { - LLVector3d region_origin = info->getGlobalOrigin(); - LLVector3 pos_local( - (F32)(pos_global.mdV[VX] - region_origin.mdV[VX]), - (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]), - (F32)(pos_global.mdV[VZ])); - teleportRequest(handle, pos_local); - } - else if(regionp && - teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) - { - llwarns << "Using deprecated teleportlocationrequest." << llendl; - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_TeleportLocationRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - - msg->nextBlockFast(_PREHASH_Info); - F32 width = regionp->getWidth(); - LLVector3 pos(fmod((F32)pos_global.mdV[VX], width), - fmod((F32)pos_global.mdV[VY], width), - (F32)pos_global.mdV[VZ]); - F32 region_x = (F32)(pos_global.mdV[VX]); - F32 region_y = (F32)(pos_global.mdV[VY]); - U64 region_handle = to_region_handle_global(region_x, region_y); - msg->addU64Fast(_PREHASH_RegionHandle, region_handle); - msg->addVector3Fast(_PREHASH_Position, pos); - pos.mV[VX] += 1; - // - LLVector3 lookat = LLViewerCamera::getInstance()->getAtAxis(); - //msg->addVector3Fast(_PREHASH_LookAt, pos); - msg->addVector3Fast(_PREHASH_LookAt, lookat); - // - sendReliableMessage(); - } -} - -// Teleport to global position, but keep facing in the same direction -void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) -{ - mbTeleportKeepsLookAt = true; - setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction - U64 region_handle = to_region_handle(pos_global); - LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); - teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); -} - -void LLAgent::setTeleportState(ETeleportState state) -{ - mTeleportState = state; - if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime")) - { - LLFloaterSnapshot::hide(0); - } - if (mTeleportState == TELEPORT_NONE) - { - mbTeleportKeepsLookAt = false; - } - // OGPX : Only compute a 'slurl' in non-OGP mode. In OGP, set it to regionuri in floaterteleport. - if ((mTeleportState == TELEPORT_MOVING)&& (!gSavedSettings.getBOOL("OpenGridProtocol"))) - { - // We're outa here. Save "back" slurl. - mTeleportSourceSLURL = getSLURL(); - } -} - -void LLAgent::stopCurrentAnimations() -{ - // This function stops all current overriding animations on this - // avatar, propagating this change back to the server. - - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp) - { - for ( LLVOAvatar::AnimIterator anim_it = - avatarp->mPlayingAnimations.begin(); - anim_it != avatarp->mPlayingAnimations.end(); - anim_it++) - { - if (anim_it->first == - ANIM_AGENT_SIT_GROUND_CONSTRAINED) - { - // don't cancel a ground-sit anim, as viewers - // use this animation's status in - // determining whether we're sitting. ick. - } - else - { - // stop this animation locally - avatarp->stopMotion(anim_it->first, TRUE); - // ...and tell the server to tell everyone. - sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP); - } - } - - // re-assert at least the default standing animation, because - // viewers get confused by avs with no associated anims. - sendAnimationRequest(ANIM_AGENT_STAND, - ANIM_REQUEST_START); - } -} - -void LLAgent::fidget() -{ - if (!getAFK()) - { - F32 curTime = mFidgetTimer.getElapsedTimeF32(); - if (curTime > mNextFidgetTime) - { - // pick a random fidget anim here - S32 oldFidget = mCurrentFidget; - - mCurrentFidget = ll_rand(NUM_AGENT_STAND_ANIMS); - - if (mCurrentFidget != oldFidget) - { - //LLAgent::stopFidget(); - // - // for the sack of smaller packets, make this cancel the last one only - if(oldFidget != 0) - sendAnimationRequest(AGENT_STAND_ANIMS[oldFidget],ANIM_REQUEST_STOP); - // - - switch(mCurrentFidget) - { - case 0: - mCurrentFidget = 0; - break; - case 1: - sendAnimationRequest(ANIM_AGENT_STAND_1, ANIM_REQUEST_START); - mCurrentFidget = 1; - break; - case 2: - sendAnimationRequest(ANIM_AGENT_STAND_2, ANIM_REQUEST_START); - mCurrentFidget = 2; - break; - case 3: - sendAnimationRequest(ANIM_AGENT_STAND_3, ANIM_REQUEST_START); - mCurrentFidget = 3; - break; - case 4: - sendAnimationRequest(ANIM_AGENT_STAND_4, ANIM_REQUEST_START); - mCurrentFidget = 4; - break; - } - } - - // calculate next fidget time - mNextFidgetTime = curTime + ll_frand(MAX_FIDGET_TIME - MIN_FIDGET_TIME) + MIN_FIDGET_TIME; - } - } -} - -void LLAgent::stopFidget() -{ - LLDynamicArray anims; - anims.put(ANIM_AGENT_STAND_1); - anims.put(ANIM_AGENT_STAND_2); - anims.put(ANIM_AGENT_STAND_3); - anims.put(ANIM_AGENT_STAND_4); - - gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); -} - - -void LLAgent::requestEnterGodMode() -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestGodlikePowers); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_RequestBlock); - msg->addBOOLFast(_PREHASH_Godlike, TRUE); - msg->addUUIDFast(_PREHASH_Token, LLUUID::null); - - // simulators need to know about your request - sendReliableMessage(); -} - -void LLAgent::requestLeaveGodMode() -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestGodlikePowers); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_RequestBlock); - msg->addBOOLFast(_PREHASH_Godlike, FALSE); - msg->addUUIDFast(_PREHASH_Token, LLUUID::null); - - // simulator needs to know about your request - sendReliableMessage(); -} - -// wearables -LLAgent::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback() -{ - gAgent.createStandardWearablesAllDone(); -} - -LLAgent::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback() -{ - gAgent.sendAgentWearablesUpdate(); -} - -LLAgent::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback( - LLPointer cb, S32 index, LLWearable* wearable, U32 todo) : - mIndex(index), - mWearable(wearable), - mTodo(todo), - mCB(cb) -{ -} - -void LLAgent::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item) -{ - if (inv_item.isNull()) - return; - - gAgent.addWearabletoAgentInventoryDone(mIndex, inv_item, mWearable); - - if (mTodo & CALL_UPDATE) - { - gAgent.sendAgentWearablesUpdate(); - } - if (mTodo & CALL_RECOVERDONE) - { - gAgent.recoverMissingWearableDone(); - } - /* - * Do this for every one in the loop - */ - if (mTodo & CALL_CREATESTANDARDDONE) - { - gAgent.createStandardWearablesDone(mIndex); - } - if (mTodo & CALL_MAKENEWOUTFITDONE) - { - gAgent.makeNewOutfitDone(mIndex); - } -} - -void LLAgent::addWearabletoAgentInventoryDone( - S32 index, - const LLUUID& item_id, - LLWearable* wearable) -{ - if (item_id.isNull()) - return; - - LLUUID old_item_id = mWearableEntry[index].mItemID; - mWearableEntry[index].mItemID = item_id; - mWearableEntry[index].mWearable = wearable; - if (old_item_id.notNull()) - gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if(item && wearable) - { - // We're changing the asset id, so we both need to set it - // locally via setAssetUUID() and via setTransactionID() which - // will be decoded on the server. JC - item->setAssetUUID(wearable->getID()); - item->setTransactionID(wearable->getTransactionID()); - gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id); - item->updateServer(FALSE); - } - gInventory.notifyObservers(); -} - -void LLAgent::sendAgentWearablesUpdate() -{ - // First make sure that we have inventory items for each wearable - S32 i; - for(i=0; i < WT_COUNT; ++i) - { - LLWearable* wearable = mWearableEntry[ i ].mWearable; - if (wearable) - { - if( mWearableEntry[ i ].mItemID.isNull() ) - { - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - i, - wearable, - addWearableToAgentInventoryCallback::CALL_NONE); - addWearableToAgentInventory(cb, wearable); - } - else - { - gInventory.addChangedMask( LLInventoryObserver::LABEL, - mWearableEntry[i].mItemID ); - } - } - } - - // Then make sure the inventory is in sync with the avatar. - gInventory.notifyObservers(); - - // Send the AgentIsNowWearing - gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing); - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); - - LL_DEBUGS("Wearables") << "sendAgentWearablesUpdate()" << LL_ENDL; - for(i=0; i < WT_COUNT; ++i) - { - gMessageSystem->nextBlockFast(_PREHASH_WearableData); - - U8 type_u8 = (U8)i; - gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8 ); - - LLWearable* wearable = mWearableEntry[ i ].mWearable; - if( wearable ) - { - LL_DEBUGS("Wearables") << "Sending wearable " << wearable->getName() << " mItemID = " << mWearableEntry[ i ].mItemID << LL_ENDL; - gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID ); - } - else - { - LL_DEBUGS("Wearables") << "Not wearing wearable type " << LLWearable::typeToTypeName((EWearableType)i) << LL_ENDL; - gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null ); - } - - LL_DEBUGS("Wearables") << " " << LLWearable::typeToTypeLabel((EWearableType)i) << " : " << (wearable ? wearable->getID() : LLUUID::null) << LL_ENDL; - } - gAgent.sendReliableMessage(); -} - -void LLAgent::saveWearable( EWearableType type, BOOL send_update ) -{ - LLWearable* old_wearable = mWearableEntry[(S32)type].mWearable; - if( old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()) ) - { - LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable ); - mWearableEntry[(S32)type].mWearable = new_wearable; - - LLInventoryItem* item = gInventory.getItem(mWearableEntry[(S32)type].mItemID); - if( item ) - { - // Update existing inventory item - LLPointer template_item = - new LLViewerInventoryItem(item->getUUID(), - item->getParentUUID(), - item->getPermissions(), - new_wearable->getID(), - new_wearable->getAssetType(), - item->getInventoryType(), - item->getName(), - item->getDescription(), - item->getSaleInfo(), - item->getFlags(), - item->getCreationDate()); - template_item->setTransactionID(new_wearable->getTransactionID()); - template_item->updateServer(FALSE); - gInventory.updateItem(template_item); - } - else - { - // Add a new inventory item (shouldn't ever happen here) - U32 todo = addWearableToAgentInventoryCallback::CALL_NONE; - if (send_update) - { - todo |= addWearableToAgentInventoryCallback::CALL_UPDATE; - } - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - (S32)type, - new_wearable, - todo); - addWearableToAgentInventory(cb, new_wearable); - return; - } - - getAvatarObject()->wearableUpdated( type ); - - if( send_update ) - { - sendAgentWearablesUpdate(); - } - } -} - -void LLAgent::saveWearableAs( - EWearableType type, - const std::string& new_name, - BOOL save_in_lost_and_found) -{ - if(!isWearableCopyable(type)) - { - llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; - return; - } - LLWearable* old_wearable = getWearable(type); - if(!old_wearable) - { - llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; - return; - } - LLInventoryItem* item = gInventory.getItem(mWearableEntry[type].mItemID); - if(!item) - { - llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl; - return; - } - std::string trunc_name(new_name); - LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); - LLWearable* new_wearable = gWearableList.createCopyFromAvatar( - old_wearable, - trunc_name); - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - type, - new_wearable, - addWearableToAgentInventoryCallback::CALL_UPDATE); - LLUUID category_id; - if (save_in_lost_and_found) - { - category_id = gInventory.findCategoryUUIDForType( - LLAssetType::AT_LOST_AND_FOUND); - } - else - { - // put in same folder as original - category_id = item->getParentUUID(); - } - - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - category_id, - new_name, - cb); - -/* - LLWearable* old_wearable = getWearable( type ); - if( old_wearable ) - { - std::string old_name = old_wearable->getName(); - old_wearable->setName( new_name ); - LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable ); - old_wearable->setName( old_name ); - - LLUUID category_id; - LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID ); - if( item ) - { - new_wearable->setPermissions(item->getPermissions()); - if (save_in_lost_and_found) - { - category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); - } - else - { - // put in same folder as original - category_id = item->getParentUUID(); - } - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) - { - view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); - } - } - - mWearableEntry[ type ].mWearable = new_wearable; - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - type, - addWearableToAgentInventoryCallback::CALL_UPDATE); - addWearableToAgentInventory(cb, new_wearable, category_id); - } -*/ -} - -void LLAgent::revertWearable( EWearableType type ) -{ - LLWearable* wearable = mWearableEntry[(S32)type].mWearable; - if( wearable ) - { - wearable->writeToAvatar( TRUE ); - } - sendAgentSetAppearance(); -} - -void LLAgent::revertAllWearables() -{ - for( S32 i=0; i < WT_COUNT; i++ ) - { - revertWearable( (EWearableType)i ); - } -} - -void LLAgent::saveAllWearables() -{ - //if(!gInventory.isLoaded()) - //{ - // return; - //} - - for( S32 i=0; i < WT_COUNT; i++ ) - { - saveWearable( (EWearableType)i, FALSE ); - } - sendAgentWearablesUpdate(); -} - -// Called when the user changes the name of a wearable inventory item that is currenlty being worn. -void LLAgent::setWearableName( const LLUUID& item_id, const std::string& new_name ) -{ - for( S32 i=0; i < WT_COUNT; i++ ) - { - if( mWearableEntry[i].mItemID == item_id ) - { - LLWearable* old_wearable = mWearableEntry[i].mWearable; - llassert( old_wearable ); - - std::string old_name = old_wearable->getName(); - old_wearable->setName( new_name ); - LLWearable* new_wearable = gWearableList.createCopy( old_wearable ); - LLInventoryItem* item = gInventory.getItem(item_id); - if(item) - { - new_wearable->setPermissions(item->getPermissions()); - } - old_wearable->setName( old_name ); - - mWearableEntry[i].mWearable = new_wearable; - sendAgentWearablesUpdate(); - break; - } - } -} - - -BOOL LLAgent::isWearableModifiable(EWearableType type) -{ - LLUUID item_id = getWearableItem(type); - if(!item_id.isNull()) - { - LLInventoryItem* item = gInventory.getItem(item_id); - if(item && item->getPermissions().allowModifyBy(gAgent.getID(), - gAgent.getGroupID())) - { - return TRUE; - } - } - return FALSE; -} - -BOOL LLAgent::isWearableCopyable(EWearableType type) -{ - LLUUID item_id = getWearableItem(type); - if(!item_id.isNull()) - { - LLInventoryItem* item = gInventory.getItem(item_id); - if(item && item->getPermissions().allowCopyBy(gAgent.getID(), - gAgent.getGroupID())) - { - return TRUE; - } - } - return FALSE; -} - -U32 LLAgent::getWearablePermMask(EWearableType type) -{ - LLUUID item_id = getWearableItem(type); - if(!item_id.isNull()) - { - LLInventoryItem* item = gInventory.getItem(item_id); - if(item) - { - return item->getPermissions().getMaskOwner(); - } - } - return PERM_NONE; -} - -LLInventoryItem* LLAgent::getWearableInventoryItem(EWearableType type) -{ - LLUUID item_id = getWearableItem(type); - LLInventoryItem* item = NULL; - if(item_id.notNull()) - { - item = gInventory.getItem(item_id); - } - return item; -} - -LLWearable* LLAgent::getWearableFromWearableItem( const LLUUID& item_id ) -{ - for( S32 i=0; i < WT_COUNT; i++ ) - { - if( mWearableEntry[i].mItemID == item_id ) - { - return mWearableEntry[i].mWearable; - } - } - return NULL; -} - - -void LLAgent::sendAgentWearablesRequest() -{ - gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - sendReliableMessage(); -} - -// Used to enable/disable menu items. -// static -BOOL LLAgent::selfHasWearable( void* userdata ) -{ - EWearableType type = (EWearableType)(intptr_t)userdata; - return gAgent.getWearable( type ) != NULL; -} - -BOOL LLAgent::isWearingItem( const LLUUID& item_id ) -{ - return (getWearableFromWearableItem( item_id ) != NULL); -} - -// static -void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void** user_data ) -{ - // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates - // that may result from AgentWearablesRequest having been sent more than once. - static bool first = true; - if (!first) return; - first = false; - - LLUUID agent_id; - gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( avatar && (agent_id == avatar->getID()) ) - { - gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgent.mAgentWearablesUpdateSerialNum ); - - S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); - if( num_wearables < 4 ) - { - // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin). - // The fact that they don't have any here (only a dummy is sent) implies that this account existed - // before we had wearables, or that the database has gotten messed up. - return; - } - //else - //{ - // // OGPX HACK: OGP authentication does not pass back login-flags, - // // thus doesn't check for "gendered" flag - // // so this isn't an ideal place for this because the check in idle_startup in STATE_WEARABLES_WAIT - // // is happening *before* this call. That causes the welcomechoosesex dialog to be displayed - // // but I'm torn on removing this commented out code because I'm unsure how the initial wearables - // // code will work out. - // gAgent.setGenderChosen(TRUE); - //} - - //lldebugs << "processAgentInitialWearablesUpdate()" << llendl; - // Add wearables - LLUUID asset_id_array[ WT_COUNT ]; - S32 i; - for( i=0; i < num_wearables; i++ ) - { - U8 type_u8 = 0; - gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i ); - if( type_u8 >= WT_COUNT ) - { - continue; - } - EWearableType type = (EWearableType) type_u8; - - LLUUID item_id; - gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i ); - - LLUUID asset_id; - gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i ); - if( asset_id.isNull() ) - { - LLWearable::removeFromAvatar( type, FALSE ); - } - else - { - LLAssetType::EType asset_type = LLWearable::typeToAssetType( type ); - if( asset_type == LLAssetType::AT_NONE ) - { - continue; - } - - gAgent.mWearableEntry[type].mItemID = item_id; - asset_id_array[type] = asset_id; - } - - LL_DEBUGS("Wearables") << " " << LLWearable::typeToTypeLabel(type) << " " << asset_id << " item id " << gAgent.mWearableEntry[type].mItemID.asString() << LL_ENDL; - } - - // now that we have the asset ids...request the wearable assets - for( i = 0; i < WT_COUNT; i++ ) - { - LL_DEBUGS("Wearables") << " fetching " << asset_id_array[i] << LL_ENDL; - if( !gAgent.mWearableEntry[i].mItemID.isNull() ) - { - gWearableList.getAsset( - asset_id_array[i], - LLStringUtil::null, - LLWearable::typeToAssetType( (EWearableType) i ), - LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); - } - } - } -} - -// A single wearable that the avatar was wearing on start-up has arrived from the database. -// static -void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdata ) -{ - EWearableType type = (EWearableType)(intptr_t)userdata; - - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( !avatar ) - { - return; - } - - if( wearable ) - { - llassert( type == wearable->getType() ); - gAgent.mWearableEntry[ type ].mWearable = wearable; - - // disable composites if initial textures are baked - avatar->setupComposites(); - gAgent.queryWearableCache(); - - wearable->writeToAvatar( FALSE ); - avatar->setCompositeUpdatesEnabled(TRUE); - gInventory.addChangedMask( LLInventoryObserver::LABEL, gAgent.mWearableEntry[type].mItemID ); - } - else - { - // Somehow the asset doesn't exist in the database. - gAgent.recoverMissingWearable( type ); - } - - gInventory.notifyObservers(); - - // Have all the wearables that the avatar was wearing at log-in arrived? - if( !gAgent.mWearablesLoaded ) - { - gAgent.mWearablesLoaded = TRUE; - for( S32 i = 0; i < WT_COUNT; i++ ) - { - if( !gAgent.mWearableEntry[i].mItemID.isNull() && !gAgent.mWearableEntry[i].mWearable ) - { - gAgent.mWearablesLoaded = FALSE; - break; - } - } - } - - if( gAgent.mWearablesLoaded ) - { - // Make sure that the server's idea of the avatar's wearables actually match the wearables. - gAgent.sendAgentSetAppearance(); - - // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time. - // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive. - if( !gAgent.cameraCustomizeAvatar() ) - { - avatar->requestLayerSetUploads(); - } - } -} - -// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the -// database. If for some reason, we can't load one of those assets, we can try to reconstruct it so that -// the user isn't left without a shape, for example. (We can do that only after the inventory has loaded.) -void LLAgent::recoverMissingWearable( EWearableType type ) -{ - // Try to recover by replacing missing wearable with a new one. - LLNotifications::instance().add("ReplacedMissingWearable"); - lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; - LLWearable* new_wearable = gWearableList.createNewWearable(type); - - S32 type_s32 = (S32) type; - mWearableEntry[type_s32].mWearable = new_wearable; - new_wearable->writeToAvatar( TRUE ); - - // Add a new one in the lost and found folder. - // (We used to overwrite the "not found" one, but that could potentially - // destory content.) JC - LLUUID lost_and_found_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - type_s32, - new_wearable, - addWearableToAgentInventoryCallback::CALL_RECOVERDONE); - addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE); -} - -void LLAgent::recoverMissingWearableDone() -{ - // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated? - mWearablesLoaded = TRUE; - for( S32 i = 0; i < WT_COUNT; i++ ) - { - if( !mWearableEntry[i].mItemID.isNull() && !mWearableEntry[i].mWearable ) - { - mWearablesLoaded = FALSE; - break; - } - } - - if( mWearablesLoaded ) - { - // Make sure that the server's idea of the avatar's wearables actually match the wearables. - sendAgentSetAppearance(); - } - else - { - gInventory.addChangedMask( LLInventoryObserver::LABEL, LLUUID::null ); - gInventory.notifyObservers(); - } -} - -void LLAgent::createStandardWearables(BOOL female) -{ - llwarns << "Creating Standard " << (female ? "female" : "male" ) - << " Wearables" << llendl; - - if (mAvatarObject.isNull()) - { - return; - } - - if(female) mAvatarObject->setSex(SEX_FEMALE); - else mAvatarObject->setSex(SEX_MALE); - - BOOL create[WT_COUNT] = - { - TRUE, //WT_SHAPE - TRUE, //WT_SKIN - TRUE, //WT_HAIR - TRUE, //WT_EYES - TRUE, //WT_SHIRT - TRUE, //WT_PANTS - TRUE, //WT_SHOES - TRUE, //WT_SOCKS - FALSE, //WT_JACKET - FALSE, //WT_GLOVES - TRUE, //WT_UNDERSHIRT - TRUE, //WT_UNDERPANTS - FALSE, //WT_SKIRT - FALSE, //WT_ALPHA - FALSE //WT_TATTOO - }; - - for( S32 i=0; i < WT_COUNT; i++ ) - { - bool once = false; - LLPointer donecb = NULL; - if( create[i] ) - { - if (!once) - { - once = true; - donecb = new createStandardWearablesAllDoneCallback; - } - llassert( mWearableEntry[i].mWearable == NULL ); - LLWearable* wearable = gWearableList.createNewWearable((EWearableType)i); - mWearableEntry[i].mWearable = wearable; - // no need to update here... - LLPointer cb = - new addWearableToAgentInventoryCallback( - donecb, - i, - wearable, - addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE); - addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE); - } - } -} -void LLAgent::createStandardWearablesDone(S32 index) -{ - LLWearable* wearable = mWearableEntry[index].mWearable; - - if (wearable) - { - wearable->writeToAvatar(TRUE); - } -} - -void LLAgent::createStandardWearablesAllDone() -{ - // ... because sendAgentWearablesUpdate will notify inventory - // observers. - mWearablesLoaded = TRUE; - sendAgentWearablesUpdate(); - sendAgentSetAppearance(); - - // Treat this as the first texture entry message, if none received yet - mAvatarObject->onFirstTEMessageReceived(); -} - -void LLAgent::makeNewOutfit( - const std::string& new_folder_name, - const LLDynamicArray& wearables_to_include, - const LLDynamicArray& attachments_to_include, - BOOL rename_clothing) -{ - if (mAvatarObject.isNull()) - { - return; - } - - // First, make a folder in the Clothes directory. - LLUUID folder_id = gInventory.createNewCategory( - gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING), - LLAssetType::AT_NONE, - new_folder_name); - - bool found_first_item = false; - - /////////////////// - // Wearables - - if( wearables_to_include.count() ) - { - // Then, iterate though each of the wearables and save copies of them in the folder. - S32 i; - S32 count = wearables_to_include.count(); - LLDynamicArray delete_items; - LLPointer cbdone = NULL; - for( i = 0; i < count; ++i ) - { - S32 index = wearables_to_include[i]; - LLWearable* old_wearable = mWearableEntry[ index ].mWearable; - if( old_wearable ) - { - std::string new_name; - LLWearable* new_wearable; - new_wearable = gWearableList.createCopy(old_wearable); - if (rename_clothing) - { - new_name = new_folder_name; - new_name.append(" "); - new_name.append(old_wearable->getTypeLabel()); - LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); - new_wearable->setName(new_name); - } - - LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID); - S32 todo = addWearableToAgentInventoryCallback::CALL_NONE; - if (!found_first_item) - { - found_first_item = true; - /* set the focus to the first item */ - todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE; - /* send the agent wearables update when done */ - cbdone = new sendAgentWearablesUpdateCallback; - } - LLPointer cb = - new addWearableToAgentInventoryCallback( - cbdone, - index, - new_wearable, - todo); - if (isWearableCopyable((EWearableType)index)) - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - folder_id, - new_name, - cb); - } - else - { - move_inventory_item( - gAgent.getID(), - gAgent.getSessionID(), - item->getUUID(), - folder_id, - new_name, - cb); - } - } - } - gInventory.notifyObservers(); - } - - - /////////////////// - // Attachments - - if( attachments_to_include.count() ) - { - BOOL msg_started = FALSE; - LLMessageSystem* msg = gMessageSystem; - for( S32 i = 0; i < attachments_to_include.count(); i++ ) - { - S32 attachment_pt = attachments_to_include[i]; - LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL ); - if(!attachment) continue; - LLViewerObject* attached_object = attachment->getObject(); - if(!attached_object) continue; - const LLUUID& item_id = attachment->getItemID(); - if(item_id.isNull()) continue; - LLInventoryItem* item = gInventory.getItem(item_id); - if(!item) continue; - if(!msg_started) - { - msg_started = TRUE; - msg->newMessage("CreateNewOutfitAttachments"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", getID()); - msg->addUUID("SessionID", getSessionID()); - msg->nextBlock("HeaderData"); - msg->addUUID("NewFolderID", folder_id); - } - msg->nextBlock("ObjectData"); - msg->addUUID("OldItemID", item_id); - msg->addUUID("OldFolderID", item->getParentUUID()); - } - - if( msg_started ) - { - sendReliableMessage(); - } - - } -} - -void LLAgent::makeNewOutfitDone(S32 index) -{ - LLUUID first_item_id = mWearableEntry[index].mItemID; - // Open the inventory and select the first item we added. - if( first_item_id.notNull() ) - { - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) - { - view->getPanel()->setSelection(first_item_id, TAKE_FOCUS_NO); - } - } -} - - -void LLAgent::addWearableToAgentInventory( - LLPointer cb, - LLWearable* wearable, - const LLUUID& category_id, - BOOL notify) -{ - create_inventory_item( - gAgent.getID(), - gAgent.getSessionID(), - category_id, - wearable->getTransactionID(), - wearable->getName(), - wearable->getDescription(), - wearable->getAssetType(), - LLInventoryType::IT_WEARABLE, - wearable->getType(), - wearable->getPermissions().getMaskNextOwner(), - cb); -} - -//----------------------------------------------------------------------------- -// sendAgentSetAppearance() -//----------------------------------------------------------------------------- -void LLAgent::sendAgentSetAppearance() -{ - if (mAvatarObject.isNull()) return; - - if (mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar()) - { - return; - } - - - llinfos << "TAT: Sent AgentSetAppearance: " << mAvatarObject->getBakedStatusForPrintout() << llendl; - //dumpAvatarTEs( "sendAgentSetAppearance()" ); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentSetAppearance); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - - // correct for the collision tolerance (to make it look like the - // agent is actually walking on the ground/object) - // NOTE -- when we start correcting all of the other Havok geometry - // to compensate for the COLLISION_TOLERANCE ugliness we will have - // to tweak this number again - const LLVector3 body_size = mAvatarObject->mBodySize; - msg->addVector3Fast(_PREHASH_Size, body_size); - - // To guard against out of order packets - // Note: always start by sending 1. This resets the server's count. 0 on the server means "uninitialized" - mAppearanceSerialNum++; - msg->addU32Fast(_PREHASH_SerialNum, mAppearanceSerialNum ); - - // is texture data current relative to wearables? - // KLW - TAT this will probably need to check the local queue. - BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded; - - for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) - { - const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); - - // if we're not wearing a skirt, we don't need the texture to be baked - if (texture_index == TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT)) - { - continue; - } - - // IMG_DEFAULT_AVATAR means not baked - if (!mAvatarObject->isTextureDefined(texture_index)) - { - textures_current = FALSE; - break; - } - } - - // only update cache entries if we have all our baked textures - if (textures_current) - { - llinfos << "TAT: Sending cached texture data" << llendl; - for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) - { - const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); - LLUUID hash; - for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) - { - // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; - const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; - const LLWearable* wearable = getWearable(wearable_type); - if (wearable) - { - hash ^= wearable->getID(); - } - } - if (hash.notNull()) - { - hash ^= wearable_dict->mHashID; - } - - const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); - - msg->nextBlockFast(_PREHASH_WearableData); - msg->addUUIDFast(_PREHASH_CacheID, hash); - msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); - } - msg->nextBlockFast(_PREHASH_ObjectData); - mAvatarObject->packTEMessage( gMessageSystem ); - } - else - { - // If the textures aren't baked, send NULL for texture IDs - // This means the baked texture IDs on the server will be untouched. - // Once all textures are baked, another AvatarAppearance message will be sent to update the TEs - msg->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0); - } - - - S32 transmitted_params = 0; - for (LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarObject->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*)mAvatarObject->getNextVisualParam()) - { - if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) - { - msg->nextBlockFast(_PREHASH_VisualParam ); - - // We don't send the param ids. Instead, we assume that the receiver has the same params in the same sequence. - const F32 param_value = param->getWeight(); - const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight()); - msg->addU8Fast(_PREHASH_ParamValue, new_weight ); - transmitted_params++; - } - } - -// llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; - sendReliableMessage(); -} - -void LLAgent::sendAgentDataUpdateRequest() -{ - gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - sendReliableMessage(); -} - -void LLAgent::removeWearable( EWearableType type ) -{ - LLWearable* old_wearable = mWearableEntry[ type ].mWearable; - - if ( (gAgent.isTeen()) - && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) - { - // Can't take off underclothing in simple UI mode or on PG accounts - return; - } - - if( old_wearable ) - { - if( old_wearable->isDirty() ) - { - LLSD payload; - payload["wearable_type"] = (S32)type; - // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("WearableSave", LLSD(), payload, &LLAgent::onRemoveWearableDialog); - return; - } - else - { - removeWearableFinal( type ); - } - } -} - -// static -bool LLAgent::onRemoveWearableDialog(const LLSD& notification, const LLSD& response ) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger(); - switch( option ) - { - case 0: // "Save" - gAgent.saveWearable( type ); - gAgent.removeWearableFinal( type ); - break; - - case 1: // "Don't Save" - gAgent.removeWearableFinal( type ); - break; - - case 2: // "Cancel" - break; - - default: - llassert(0); - break; - } - return false; -} - -// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal. -void LLAgent::removeWearableFinal( EWearableType type ) -{ - LLWearable* old_wearable = mWearableEntry[ type ].mWearable; - - gInventory.addChangedMask( LLInventoryObserver::LABEL, mWearableEntry[type].mItemID ); - - mWearableEntry[ type ].mWearable = NULL; - mWearableEntry[ type ].mItemID.setNull(); - - queryWearableCache(); - - if( old_wearable ) - { - old_wearable->removeFromAvatar( TRUE ); - } - - // Update the server - sendAgentWearablesUpdate(); - sendAgentSetAppearance(); - gInventory.notifyObservers(); -} - -void LLAgent::copyWearableToInventory( EWearableType type ) -{ - LLWearable* wearable = mWearableEntry[ type ].mWearable; - if( wearable ) - { - // Save the old wearable if it has changed. - if( wearable->isDirty() ) - { - wearable = gWearableList.createCopyFromAvatar( wearable ); - mWearableEntry[ type ].mWearable = wearable; - } - - // Make a new entry in the inventory. (Put it in the same folder as the original item if possible.) - LLUUID category_id; - LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID ); - if( item ) - { - category_id = item->getParentUUID(); - wearable->setPermissions(item->getPermissions()); - } - LLPointer cb = - new addWearableToAgentInventoryCallback( - LLPointer(NULL), - type, - wearable); - addWearableToAgentInventory(cb, wearable, category_id); - } -} - - -// A little struct to let setWearable() communicate more than one value with onSetWearableDialog(). -struct LLSetWearableData -{ - LLSetWearableData( const LLUUID& new_item_id, LLWearable* new_wearable ) : - mNewItemID( new_item_id ), mNewWearable( new_wearable ) {} - LLUUID mNewItemID; - LLWearable* mNewWearable; -}; - -BOOL LLAgent::needsReplacement(EWearableType wearableType, S32 remove) -{ - return TRUE; - /*if (remove) return TRUE; - - return getWearable(wearableType) ? TRUE : FALSE;*/ -} - -// Assumes existing wearables are not dirty. -void LLAgent::setWearableOutfit( - const LLInventoryItem::item_array_t& items, - const LLDynamicArray< LLWearable* >& wearables, - BOOL remove ) -{ - lldebugs << "setWearableOutfit() start" << llendl; - - BOOL wearables_to_remove[WT_COUNT]; - wearables_to_remove[WT_SHAPE] = FALSE; - wearables_to_remove[WT_SKIN] = FALSE; - wearables_to_remove[WT_HAIR] = FALSE; - wearables_to_remove[WT_EYES] = FALSE; - wearables_to_remove[WT_SHIRT] = remove; - wearables_to_remove[WT_PANTS] = remove; - wearables_to_remove[WT_SHOES] = remove; - wearables_to_remove[WT_SOCKS] = remove; - wearables_to_remove[WT_JACKET] = remove; - wearables_to_remove[WT_GLOVES] = remove; - wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove; - wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove; - wearables_to_remove[WT_SKIRT] = remove; - wearables_to_remove[WT_ALPHA] = remove; - wearables_to_remove[WT_TATTOO] = remove; - - S32 count = wearables.count(); - llassert( items.count() == count ); - - S32 i; - for( i = 0; i < count; i++ ) - { - LLWearable* new_wearable = wearables[i]; - LLPointer new_item = items[i]; - - EWearableType type = new_wearable->getType(); - wearables_to_remove[type] = FALSE; - - LLWearable* old_wearable = mWearableEntry[ type ].mWearable; - if( old_wearable ) - { - const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; - if( (old_wearable->getID() == new_wearable->getID()) && - (old_item_id == new_item->getUUID()) ) - { - lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl; - continue; - } - - gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); - - // Assumes existing wearables are not dirty. - if( old_wearable->isDirty() ) - { - llassert(0); - continue; - } - } - - mWearableEntry[ type ].mItemID = new_item->getUUID(); - mWearableEntry[ type ].mWearable = new_wearable; - } - - std::vector wearables_being_removed; - - for( i = 0; i < WT_COUNT; i++ ) - { - if( wearables_to_remove[i] ) - { - wearables_being_removed.push_back(mWearableEntry[ i ].mWearable); - mWearableEntry[ i ].mWearable = NULL; - - gInventory.addChangedMask(LLInventoryObserver::LABEL, mWearableEntry[ i ].mItemID); - mWearableEntry[ i ].mItemID.setNull(); - } - } - - gInventory.notifyObservers(); - - queryWearableCache(); - - std::vector::iterator wearable_iter; - - for( wearable_iter = wearables_being_removed.begin(); - wearable_iter != wearables_being_removed.end(); - ++wearable_iter) - { - LLWearable* wearablep = *wearable_iter; - if (wearablep) - { - wearablep->removeFromAvatar( TRUE ); - } - } - - for( i = 0; i < count; i++ ) - { - wearables[i]->writeToAvatar( TRUE ); - } - - // Start rendering & update the server - mWearablesLoaded = TRUE; - sendAgentWearablesUpdate(); - sendAgentSetAppearance(); - - lldebugs << "setWearableOutfit() end" << llendl; -} - - -// User has picked "wear on avatar" from a menu. -void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable ) -{ - EWearableType type = new_wearable->getType(); - - LLWearable* old_wearable = mWearableEntry[ type ].mWearable; - if( old_wearable ) - { - const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; - if( (old_wearable->getID() == new_wearable->getID()) && - (old_item_id == new_item->getUUID()) ) - { - lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl; - return; - } - - if( old_wearable->isDirty() ) - { - // Bring up modal dialog: Save changes? Yes, No, Cancel - LLSD payload; - payload["item_id"] = new_item->getUUID(); - LLNotifications::instance().add( "WearableSave", LLSD(), payload, boost::bind(LLAgent::onSetWearableDialog, _1, _2, new_wearable)); - return; - } - } - - setWearableFinal( new_item, new_wearable ); -} - -// static -bool LLAgent::onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable ) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID()); - if( !new_item ) - { - delete wearable; - return false; - } - - switch( option ) - { - case 0: // "Save" - gAgent.saveWearable( wearable->getType() ); - gAgent.setWearableFinal( new_item, wearable ); - break; - - case 1: // "Don't Save" - gAgent.setWearableFinal( new_item, wearable ); - break; - - case 2: // "Cancel" - break; - - default: - llassert(0); - break; - } - - delete wearable; - return false; -} - -// Called from setWearable() and onSetWearableDialog() to actually set the wearable. -void LLAgent::setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable ) -{ - EWearableType type = new_wearable->getType(); - - // Replace the old wearable with a new one. - llassert( new_item->getAssetUUID() == new_wearable->getID() ); - LLUUID old_item_id = mWearableEntry[ type ].mItemID; - mWearableEntry[ type ].mItemID = new_item->getUUID(); - mWearableEntry[ type ].mWearable = new_wearable; - - if (old_item_id.notNull()) - { - gInventory.addChangedMask( LLInventoryObserver::LABEL, old_item_id ); - gInventory.notifyObservers(); - } - - //llinfos << "LLVOAvatar::setWearable()" << llendl; - queryWearableCache(); - new_wearable->writeToAvatar( TRUE ); - - // Update the server - sendAgentWearablesUpdate(); - sendAgentSetAppearance(); -} - -void LLAgent::queryWearableCache() -{ - if (!mWearablesLoaded) - { - return; - } - - // Look up affected baked textures. - // If they exist: - // disallow updates for affected layersets (until dataserver responds with cache request.) - // If cache miss, turn updates back on and invalidate composite. - // If cache hit, modify baked texture entries. - // - // Cache requests contain list of hashes for each baked texture entry. - // Response is list of valid baked texture assets. (same message) - - gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); - gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID); - - S32 num_queries = 0; - for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) - { - const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); - LLUUID hash; - for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) - { - // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; - const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; - const LLWearable* wearable = getWearable(wearable_type); - if (wearable) - { - hash ^= wearable->getID(); - } - } - if (hash.notNull()) - { - hash ^= wearable_dict->mHashID; - num_queries++; - // *NOTE: make sure at least one request gets packed - - //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl; - gMessageSystem->nextBlockFast(_PREHASH_WearableData); - gMessageSystem->addUUIDFast(_PREHASH_ID, hash); - gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index); - } - - mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID; - } - - llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; - gMessageSystem->sendReliable(getRegion()->getHost()); - mNumPendingQueries++; - mTextureCacheQueryID++; -} - -// User has picked "remove from avatar" from a menu. -// static -void LLAgent::userRemoveWearable( void* userdata ) -{ - EWearableType type = (EWearableType)(intptr_t)userdata; - - if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES) ) //&& - //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) - { - gAgent.removeWearable( type ); - } -} - -void LLAgent::userRemoveAllClothes( void* userdata ) -{ - // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty. - if( gFloaterCustomize ) - { - gFloaterCustomize->askToSaveIfDirty( LLAgent::userRemoveAllClothesStep2, NULL ); - } - else - { - LLAgent::userRemoveAllClothesStep2( TRUE, NULL ); - } -} - -void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata ) -{ - if( proceed ) - { - gAgent.removeWearable( WT_SHIRT ); - gAgent.removeWearable( WT_PANTS ); - gAgent.removeWearable( WT_SHOES ); - gAgent.removeWearable( WT_SOCKS ); - gAgent.removeWearable( WT_JACKET ); - gAgent.removeWearable( WT_GLOVES ); - gAgent.removeWearable( WT_UNDERSHIRT ); - gAgent.removeWearable( WT_UNDERPANTS ); - gAgent.removeWearable( WT_SKIRT ); - gAgent.removeWearable( WT_ALPHA ); - gAgent.removeWearable( WT_TATTOO ); - } -} - -void LLAgent::userRemoveAllAttachments( void* userdata ) -{ - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if(!avatarp) - { - llwarns << "No avatar found." << llendl; - return; - } - - gMessageSystem->newMessage("ObjectDetach"); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLViewerObject* objectp = attachment->getObject(); - if (objectp) - { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); - } - } - gMessageSystem->sendReliable( gAgent.getRegionHost() ); -} - -void LLAgent::observeFriends() -{ - if(!mFriendObserver) - { - mFriendObserver = new LLAgentFriendObserver; - LLAvatarTracker::instance().addObserver(mFriendObserver); - friendsChanged(); - } -} - -void LLAgent::parseTeleportMessages(const std::string& xml_filename) -{ - LLXMLNodePtr root; - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); - - if (!success || !root || !root->hasName( "teleport_messages" )) - { - llerrs << "Problem reading teleport string XML file: " - << xml_filename << llendl; - return; - } - - for (LLXMLNode* message_set = root->getFirstChild(); - message_set != NULL; - message_set = message_set->getNextSibling()) - { - if ( !message_set->hasName("message_set") ) continue; - - std::map *teleport_msg_map = NULL; - std::string message_set_name; - - if ( message_set->getAttributeString("name", message_set_name) ) - { - //now we loop over all the string in the set and add them - //to the appropriate set - if ( message_set_name == "errors" ) - { - teleport_msg_map = &sTeleportErrorMessages; - } - else if ( message_set_name == "progress" ) - { - teleport_msg_map = &sTeleportProgressMessages; - } - } - - if ( !teleport_msg_map ) continue; - - std::string message_name; - for (LLXMLNode* message_node = message_set->getFirstChild(); - message_node != NULL; - message_node = message_node->getNextSibling()) - { - if ( message_node->hasName("message") && - message_node->getAttributeString("name", message_name) ) - { - (*teleport_msg_map)[message_name] = - message_node->getTextContents(); - } //end if ( message exists and has a name) - } //end for (all message in set) - }//end for (all message sets in xml file) -} - -// OGPX - This code will change when capabilities get refactored. -// Right now this is used for capabilities that we get from OGP agent domain -void LLAgent::setCapability(const std::string& name, const std::string& url) -{ -#if 0 // OGPX : I think (hope?) we don't need this - // but I'm leaving it here commented out because I'm not quite - // sure why the region capabilities code had it wedged in setCap call - // Maybe the agent domain capabilities will need something like this as well - - if (name == "EventQueueGet") - { - delete mEventPoll; - mEventPoll = NULL; - mEventPoll = new LLEventPoll(url, getHost()); - } - else if (name == "UntrustedSimulatorMessage") - { - LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url)); - } - else -#endif - { - mCapabilities[name] = url; - } -} - -//OGPX : Agent Domain capabilities... this needs to be refactored -std::string LLAgent::getCapability(const std::string& name) const -{ - CapabilityMap::const_iterator iter = mCapabilities.find(name); - if (iter == mCapabilities.end()) - { - return ""; - } - return iter->second; -} -// - -void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity) -{ - const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0)); - LLSimInfo* siminfo; - siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal); - if(siminfo) - { - llinfos << fromname << "'s teleport lure is to " << siminfo->getName() << " (" << maturity << ")" << llendl; - std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(x), S32(y), S32(z)); - std::string msg; - msg = llformat("%s's teleport lure is to %s", fromname.c_str(), url.c_str()); - if(maturity != "") - msg.append(llformat(" (%s)", maturity.c_str())); - LLChat chat(msg); - LLFloaterChat::addChat(chat); - } - else - { - LLAgent::lure_show = TRUE; - LLAgent::lure_name = fromname; - LLAgent::lure_posglobal = posglobal; - LLAgent::lure_global_x = U16(global_x / 256); - LLAgent::lure_global_y = U16(global_y / 256); - LLAgent::lure_x = x; - LLAgent::lure_y = y; - LLAgent::lure_z = z; - LLAgent::lure_maturity = maturity; - LLWorldMapMessage::getInstance()->sendMapBlockRequest(lure_global_x, lure_global_y, lure_global_x, lure_global_y, true); - } -} - -void LLAgent::onFoundLureDestination() -{ - LLAgent::lure_show = FALSE; - LLSimInfo* siminfo; - siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(LLAgent::lure_posglobal); - if(siminfo) - { - llinfos << LLAgent::lure_name << "'s teleport lure is to " << siminfo->getName() << " (" << LLAgent::lure_maturity << ")" << llendl; - std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(LLAgent::lure_x), S32(LLAgent::lure_y), S32(LLAgent::lure_z)); - std::string msg; - msg = llformat("%s's teleport lure is to %s", LLAgent::lure_name.c_str(), url.c_str()); - if(LLAgent::lure_maturity != "") - msg.append(llformat(" (%s)", LLAgent::lure_maturity.c_str())); - LLChat chat(msg); - LLFloaterChat::addChat(chat); - } - else - llwarns << "Grand scheme failed" << llendl; -} - -// - -// EOF - +/** + * @file llagent.cpp + * @brief LLAgent class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "stdtypes.h" +#include "stdenums.h" + +#include "llagent.h" + +#include "llcamera.h" +#include "llcoordframe.h" +#include "indra_constants.h" +#include "llmath.h" +#include "llcriticaldamp.h" +#include "llfocusmgr.h" +#include "llglheaders.h" +#include "llparcel.h" +#include "llpermissions.h" +#include "llregionhandle.h" +#include "m3math.h" +#include "m4math.h" +#include "message.h" +#include "llquaternion.h" +#include "v3math.h" +#include "v4math.h" +#include "llsmoothstep.h" +#include "llsdutil.h" +//#include "vmath.h" + +#include "imageids.h" +#include "llbox.h" +#include "llbutton.h" +#include "llcallingcard.h" +#include "llchatbar.h" +#include "llconsole.h" +#include "lldrawable.h" +#include "llface.h" +#include "llfirstuse.h" +#include "llfloater.h" +#include "llfloateractivespeakers.h" +#include "llfloateravatarinfo.h" +#include "llfloaterbuildoptions.h" +#include "llfloatercamera.h" +#include "llfloaterchat.h" +#include "llfloatercustomize.h" +#include "llfloaterdirectory.h" +#include "llfloatergroupinfo.h" +#include "llfloatergroups.h" +#include "llfloaterland.h" +#include "llfloatermap.h" +#include "llfloatermute.h" +#include "llfloatersnapshot.h" +#include "llfloatertools.h" +#include "llfloaterworldmap.h" +#include "llgroupmgr.h" +#include "llhomelocationresponder.h" +#include "llhudeffectlookat.h" +#include "llhudmanager.h" +#include "llinventorymodel.h" +#include "llinventoryview.h" +#include "lljoystickbutton.h" +#include "llmenugl.h" +#include "llmorphview.h" +#include "llmoveview.h" +#include "llnotify.h" +#include "llquantize.h" +#include "llsdutil.h" +#include "llselectmgr.h" +#include "llsky.h" +#include "llrendersphere.h" +#include "llstatusbar.h" +#include "llstartup.h" +#include "llimview.h" +#include "lltexturestats.h" +#include "lltool.h" +#include "lltoolcomp.h" +#include "lltoolfocus.h" +#include "lltoolgrab.h" +#include "lltoolmgr.h" +#include "lltoolpie.h" +#include "lltoolview.h" +#include "llui.h" // for make_ui_sound +#include "llurldispatcher.h" +#include "llviewercamera.h" +#include "llviewerinventory.h" +#include "llviewermediafocus.h" +#include "llviewermenu.h" +#include "llviewernetwork.h" +#include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" +#include "llviewerparceloverlay.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewerwindow.h" +#include "llviewerdisplay.h" +#include "llvoavatar.h" +#include "llvoground.h" +#include "llvosky.h" +#include "llwearable.h" +#include "llwearablelist.h" +#include "llworld.h" +#include "llworldmap.h" +#include "pipeline.h" +#include "roles_constants.h" +#include "llviewercontrol.h" +#include "llappviewer.h" +#include "llviewerjoystick.h" +#include "llfollowcam.h" +// +#include "llao.h" +#include "llworldmapmessage.h" +// +using namespace LLVOAvatarDefines; + +extern LLMenuBarGL* gMenuBarView; + +//drone wandering constants +const F32 MAX_WANDER_TIME = 20.f; // seconds +const F32 MAX_HEADING_HALF_ERROR = 0.2f; // radians +const F32 WANDER_MAX_SLEW_RATE = 2.f * DEG_TO_RAD; // radians / frame +const F32 WANDER_TARGET_MIN_DISTANCE = 10.f; // meters + +// Autopilot constants +const F32 AUTOPILOT_HEADING_HALF_ERROR = 10.f * DEG_TO_RAD; // radians +const F32 AUTOPILOT_MAX_SLEW_RATE = 1.f * DEG_TO_RAD; // radians / frame +const F32 AUTOPILOT_STOP_DISTANCE = 2.f; // meters +const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f; // meters +const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters +const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f; // seconds + +// face editing constants +const LLVector3d FACE_EDIT_CAMERA_OFFSET(0.4f, -0.05f, 0.07f); +const LLVector3d FACE_EDIT_TARGET_OFFSET(0.f, 0.f, 0.05f); + +// Mousewheel camera zoom +const F32 MIN_ZOOM_FRACTION = 0.25f; +const F32 INITIAL_ZOOM_FRACTION = 1.f; +const F32 MAX_ZOOM_FRACTION = 8.f; +const F32 METERS_PER_WHEEL_CLICK = 1.f; + +const F32 MAX_TIME_DELTA = 1.f; + +const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds +const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds + +const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f; +const F32 CAMERA_LAG_HALF_LIFE = 0.25f; +const F32 MIN_CAMERA_LAG = 0.5f; +const F32 MAX_CAMERA_LAG = 5.f; + +const F32 CAMERA_COLLIDE_EPSILON = 0.0f; +const F32 MIN_CAMERA_DISTANCE = 0.0f; +const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.0f; +const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.0f; +const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 0.0f; + +const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f; + +const F32 MAX_CAMERA_SMOOTH_DISTANCE = 50.0f; + +const F32 HEAD_BUFFER_SIZE = 0.3f; +const F32 CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP = 0.2f; + +const F32 LAND_MIN_ZOOM = 0.15f; +const F32 AVATAR_MIN_ZOOM = 0.5f; +const F32 OBJECT_MIN_ZOOM = 0.02f; + +const F32 APPEARANCE_MIN_ZOOM = 0.39f; +const F32 APPEARANCE_MAX_ZOOM = 8.f; + +// fidget constants +const F32 MIN_FIDGET_TIME = 8.f; // seconds +const F32 MAX_FIDGET_TIME = 20.f; // seconds + +const S32 MAX_NUM_CHAT_POSITIONS = 10; +const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f; +const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f; + +const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f; + +const F32 MAX_FOCUS_OFFSET = 20.f; + +const F32 OBJECT_EXTENTS_PADDING = 0.5f; + +const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f; + +const F64 CHAT_AGE_FAST_RATE = 3.0; + +// The agent instance. +LLAgent gAgent; +// +LLUUID gReSitTargetID; +LLVector3 gReSitOffset; +// +// +// Statics +// + +// +// For MapBlockReply funk 'cause I dunno what I'm doing +BOOL LLAgent::lure_show = FALSE; +std::string LLAgent::lure_name; +LLVector3d LLAgent::lure_posglobal; +U16 LLAgent::lure_global_x; +U16 LLAgent::lure_global_y; +int LLAgent::lure_x; +int LLAgent::lure_y; +int LLAgent::lure_z; +std::string LLAgent::lure_maturity; + +// + +BOOL LLAgent::exlPhantom = 0; +LLVector3 LLAgent::exlStartMeasurePoint = LLVector3::zero; +LLVector3 LLAgent::exlEndMeasurePoint = LLVector3::zero; + +const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; + +std::map LLAgent::sTeleportErrorMessages; +std::map LLAgent::sTeleportProgressMessages; + +class LLAgentFriendObserver : public LLFriendObserver +{ +public: + LLAgentFriendObserver() {} + virtual ~LLAgentFriendObserver() {} + virtual void changed(U32 mask); +}; + +void LLAgentFriendObserver::changed(U32 mask) +{ + // if there's a change we're interested in. + if((mask & (LLFriendObserver::POWERS)) != 0) + { + gAgent.friendsChanged(); + } +} + +// ************************************************************ +// Enabled this definition to compile a 'hacked' viewer that +// locally believes the end user has godlike powers. +// #define HACKED_GODLIKE_VIEWER +// For a toggled version, see viewer.h for the +// TOGGLE_HACKED_GODLIKE_VIEWER define, instead. +// ************************************************************ + +// Constructors and Destructors + +// JC - Please try to make this order match the order in the header +// file. Otherwise it's hard to find variables that aren't initialized. +//----------------------------------------------------------------------------- +// LLAgent() +//----------------------------------------------------------------------------- +LLAgent::LLAgent() : + mDrawDistance( DEFAULT_FAR_PLANE ), + + mGroupPowers(0), + mHideGroupTitle(FALSE), + mGroupID(), + + mMapOriginX(0.F), + mMapOriginY(0.F), + mMapWidth(0), + mMapHeight(0), + + mLookAt(NULL), + mPointAt(NULL), + + mHUDTargetZoom(1.f), + mHUDCurZoom(1.f), + mInitialized(FALSE), + mNumPendingQueries(0), + mActiveCacheQueries(NULL), + mForceMouselook(FALSE), + + mDoubleTapRunTimer(), + mDoubleTapRunMode(DOUBLETAP_NONE), + + mbAlwaysRun(false), + mbRunning(false), + + mAgentAccess(gSavedSettings), + mTeleportState( TELEPORT_NONE ), + mRegionp(NULL), + + mAgentOriginGlobal(), + mPositionGlobal(), + + mDistanceTraveled(0.F), + mLastPositionGlobal(LLVector3d::zero), + + mAvatarObject(NULL), + + mRenderState(0), + mTypingTimer(), + + mCameraMode( CAMERA_MODE_THIRD_PERSON ), + mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), + mViewsPushed(FALSE), + + mCustomAnim(FALSE), + mShowAvatar(TRUE), + mCameraAnimating( FALSE ), + mAnimationCameraStartGlobal(), + mAnimationFocusStartGlobal(), + mAnimationTimer(), + mAnimationDuration(0.33f), + + mCameraFOVZoomFactor(0.f), + mCameraCurrentFOVZoomFactor(0.f), + mCameraFocusOffset(), + mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW), + + mCameraOffsetDefault(), + mCameraCollidePlane(), + + mCurrentCameraDistance(2.f), // meters, set in init() + mTargetCameraDistance(2.f), + mCameraZoomFraction(1.f), // deprecated + mThirdPersonHeadOffset(0.f, 0.f, 1.f), + mSitCameraEnabled(FALSE), + mCameraSmoothingLastPositionGlobal(), + mCameraSmoothingLastPositionAgent(), + mCameraSmoothingStop(FALSE), + + mCameraUpVector(LLVector3::z_axis), // default is straight up + + mFocusOnAvatar(TRUE), + mFocusGlobal(), + mFocusTargetGlobal(), + mFocusObject(NULL), + mFocusObjectDist(0.f), + mFocusObjectOffset(), + mFocusDotRadius( 0.1f ), // meters + mTrackFocusObject(TRUE), + mUIOffset(0.f), + + mFrameAgent(), + + mIsBusy(FALSE), + + mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed + mWalkKey(0), // like AtKey, but causes less forward thrust + mLeftKey(0), + mUpKey(0), + mYawKey(0.f), + mPitchKey(0), + + mOrbitLeftKey(0.f), + mOrbitRightKey(0.f), + mOrbitUpKey(0.f), + mOrbitDownKey(0.f), + mOrbitInKey(0.f), + mOrbitOutKey(0.f), + + mPanUpKey(0.f), + mPanDownKey(0.f), + mPanLeftKey(0.f), + mPanRightKey(0.f), + mPanInKey(0.f), + mPanOutKey(0.f), + + mControlFlags(0x00000000), + mbFlagsDirty(FALSE), + mbFlagsNeedReset(FALSE), + + mbJump(FALSE), + + mAutoPilot(FALSE), + mAutoPilotFlyOnStop(FALSE), + mAutoPilotTargetGlobal(), + mAutoPilotStopDistance(1.f), + mAutoPilotUseRotation(FALSE), + mAutoPilotTargetFacing(LLVector3::zero), + mAutoPilotTargetDist(0.f), + mAutoPilotNoProgressFrameCount(0), + mAutoPilotRotationThreshold(0.f), + mAutoPilotFinishedCallback(NULL), + mAutoPilotCallbackData(NULL), + + mCapabilities(), + + mEffectColor(0.f, 1.f, 1.f, 1.f), + + mHaveHomePosition(FALSE), + mHomeRegionHandle( 0 ), + mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f), + + mNextFidgetTime(0.f), + mCurrentFidget(0), + mFirstLogin(FALSE), + mGenderChosen(FALSE), + + mAgentWearablesUpdateSerialNum(0), + mWearablesLoaded(FALSE), + mTextureCacheQueryID(0), + mAppearanceSerialNum(0), + mbTeleportKeepsLookAt(false) +{ + U32 i; + for (i = 0; i < TOTAL_CONTROLS; i++) + { + mControlsTakenCount[i] = 0; + mControlsTakenPassedOnCount[i] = 0; + } + + mActiveCacheQueries = new S32[BAKED_NUM_INDICES]; + for (i = 0; i < (U32)BAKED_NUM_INDICES; i++) + { + mActiveCacheQueries[i] = 0; + } + + mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); +} + +// Requires gSavedSettings to be initialized. +//----------------------------------------------------------------------------- +// init() +//----------------------------------------------------------------------------- +void LLAgent::init() +{ + mDrawDistance = gSavedSettings.getF32("RenderFarClip"); + + // *Note: this is where LLViewerCamera::getInstance() used to be constructed. + + LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); + // Leave at 0.1 meters until we have real near clip management + LLViewerCamera::getInstance()->setNear(0.1f); + LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h + LLViewerCamera::getInstance()->setAspect( gViewerWindow->getDisplayAspectRatio() ); // default, overridden in LLViewerWindow::reshape + LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape + + setFlying( gSavedSettings.getBOOL("FlyingAtExit") ); + + mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); + mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault"); + mCameraCollidePlane.clearVec(); + mCurrentCameraDistance = mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"); + mTargetCameraDistance = mCurrentCameraDistance; + mCameraZoomFraction = 1.f; + mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + +// LLDebugVarMessageBox::show("Camera Lag", &CAMERA_FOCUS_HALF_LIFE, 0.5f, 0.01f); + + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + llinfos << "Using client effect color." << llendl; + mEffectColor = gSavedSettings.getColor4("EffectColor"); + } + else + { + llinfos << "Using account effect color." << llendl; + mEffectColor = gSavedPerAccountSettings.getColor4("EffectColor"); + } + + mInitialized = TRUE; +} + +//----------------------------------------------------------------------------- +// cleanup() +//----------------------------------------------------------------------------- +void LLAgent::cleanup() +{ + setSitCamera(LLUUID::null); + mAvatarObject = NULL; + if(mLookAt) + { + mLookAt->markDead() ; + mLookAt = NULL; + } + if(mPointAt) + { + mPointAt->markDead() ; + mPointAt = NULL; + } + mRegionp = NULL; + setFocusObject(NULL); +} + +//----------------------------------------------------------------------------- +// LLAgent() +//----------------------------------------------------------------------------- +LLAgent::~LLAgent() +{ + cleanup(); + + delete [] mActiveCacheQueries; + mActiveCacheQueries = NULL; + + // *Note: this is where LLViewerCamera::getInstance() used to be deleted. +} + +// Change camera back to third person, stop the autopilot, +// deselect stuff, etc. +//----------------------------------------------------------------------------- +// resetView() +//----------------------------------------------------------------------------- +void LLAgent::resetView(BOOL reset_camera, BOOL change_camera) +{ + if (mAutoPilot) + { + stopAutoPilot(TRUE); + } + + if (!gNoRender) + { + LLSelectMgr::getInstance()->unhighlightAll(); + + // By popular request, keep land selection while walking around. JC + // LLViewerParcelMgr::getInstance()->deselectLand(); + + // force deselect when walking and attachment is selected + // this is so people don't wig out when their avatar moves without animating + if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) + { + LLSelectMgr::getInstance()->deselectAll(); + } + + // Hide all popup menus + gMenuHolder->hideMenus(); + } + + if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) + { + changeCameraToDefault(); + + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + handle_toggle_flycam(); + } + + // reset avatar mode from eventual residual motion + if (LLToolMgr::getInstance()->inBuildMode()) + { + LLViewerJoystick::getInstance()->moveAvatar(true); + } + + gFloaterTools->close(); + + gViewerWindow->showCursor(); + + // Switch back to basic toolset + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + + if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) + { + if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) + { + // leaving mouse-steer mode + LLVector3 agent_at_axis = getAtAxis(); + agent_at_axis -= projected_vec(agent_at_axis, getReferenceUpVector()); + agent_at_axis.normalize(); + gAgent.resetAxes(lerp(getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f))); + } + + setFocusOnAvatar(TRUE, ANIMATE); + } + + mHUDTargetZoom = 1.f; +} + +// Handle any actions that need to be performed when the main app gains focus +// (such as through alt-tab). +//----------------------------------------------------------------------------- +// onAppFocusGained() +//----------------------------------------------------------------------------- +void LLAgent::onAppFocusGained() +{ + if (CAMERA_MODE_MOUSELOOK == mCameraMode) + { + changeCameraToDefault(); + LLToolMgr::getInstance()->clearSavedTool(); + } +} + + +void LLAgent::ageChat() +{ + if (mAvatarObject.notNull()) + { + // get amount of time since I last chatted + F64 elapsed_time = (F64)mAvatarObject->mChatTimer.getElapsedTimeF32(); + // add in frame time * 3 (so it ages 4x) + mAvatarObject->mChatTimer.setAge(elapsed_time + (F64)gFrameDTClamped * (CHAT_AGE_FAST_RATE - 1.0)); + } +} + +// Allow camera to be moved somewhere other than behind avatar. +//----------------------------------------------------------------------------- +// unlockView() +//----------------------------------------------------------------------------- +void LLAgent::unlockView() +{ + if (getFocusOnAvatar()) + { + if (mAvatarObject.notNull()) + { + setFocusGlobal( LLVector3d::zero, mAvatarObject->mID ); + } + setFocusOnAvatar(FALSE, FALSE); // no animation + } +} + + +//----------------------------------------------------------------------------- +// moveAt() +//----------------------------------------------------------------------------- +void LLAgent::moveAt(S32 direction, bool reset) +{ + // age chat timer so it fades more quickly when you are intentionally moving + ageChat(); + + setKey(direction, mAtKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT); + } + + if (reset) + { + resetView(); + } +} + +//----------------------------------------------------------------------------- +// moveAtNudge() +//----------------------------------------------------------------------------- +void LLAgent::moveAtNudge(S32 direction) +{ + // age chat timer so it fades more quickly when you are intentionally moving + ageChat(); + + setKey(direction, mWalkKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_NUDGE_AT_POS); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG); + } + + resetView(); +} + +//----------------------------------------------------------------------------- +// moveLeft() +//----------------------------------------------------------------------------- +void LLAgent::moveLeft(S32 direction) +{ + // age chat timer so it fades more quickly when you are intentionally moving + ageChat(); + + setKey(direction, mLeftKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT); + } + + resetView(); +} + +//----------------------------------------------------------------------------- +// moveLeftNudge() +//----------------------------------------------------------------------------- +void LLAgent::moveLeftNudge(S32 direction) +{ + // age chat timer so it fades more quickly when you are intentionally moving + ageChat(); + + setKey(direction, mLeftKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_NUDGE_LEFT_POS); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG); + } + + resetView(); +} + +//----------------------------------------------------------------------------- +// moveUp() +//----------------------------------------------------------------------------- +void LLAgent::moveUp(S32 direction) +{ + // age chat timer so it fades more quickly when you are intentionally moving + ageChat(); + + setKey(direction, mUpKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP); + } + + resetView(); +} + +//----------------------------------------------------------------------------- +// moveYaw() +//----------------------------------------------------------------------------- +void LLAgent::moveYaw(F32 mag, bool reset_view) +{ + mYawKey = mag; + + if (mag > 0) + { + setControlFlags(AGENT_CONTROL_YAW_POS); + } + else if (mag < 0) + { + setControlFlags(AGENT_CONTROL_YAW_NEG); + } + + if (reset_view) + { + resetView(); + } +} + +//----------------------------------------------------------------------------- +// movePitch() +//----------------------------------------------------------------------------- +void LLAgent::movePitch(S32 direction) +{ + setKey(direction, mPitchKey); + + if (direction > 0) + { + setControlFlags(AGENT_CONTROL_PITCH_POS ); + } + else if (direction < 0) + { + setControlFlags(AGENT_CONTROL_PITCH_NEG); + } +} + + +// Does this parcel allow you to fly? +BOOL LLAgent::canFly() +{ + if (isGodlike()) return TRUE; + + // + if(gSavedSettings.getBOOL("AlwaysAllowFly")) return TRUE; + // + + LLViewerRegion* regionp = getRegion(); + if (regionp && regionp->getBlockFly()) return FALSE; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return FALSE; + + // Allow owners to fly on their own land. + if (LLViewerParcelMgr::isParcelOwnedByAgent(parcel, GP_LAND_ALLOW_FLY)) + { + return TRUE; + } + + return parcel->getAllowFly(); +} + +// Better Set Phantom options ~Charbl +void LLAgent::setPhantom(BOOL phantom) +{ + exlPhantom = phantom; +} + +BOOL LLAgent::getPhantom() +{ + return exlPhantom; +} +// + +//----------------------------------------------------------------------------- +// setFlying() +//----------------------------------------------------------------------------- +void LLAgent::setFlying(BOOL fly) +{ + if (mAvatarObject.notNull()) + { + if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) + { + return; + } + + // don't allow taking off while sitting + if (fly && mAvatarObject->mIsSitting) + { + return; + } + } + + if (fly) + { + BOOL was_flying = getFlying(); + if (!canFly() && !was_flying) + { + // parcel doesn't let you start fly + // gods can always fly + // and it's OK if you're already flying + make_ui_sound("UISndBadKeystroke"); + return; + } + if( !was_flying ) + { + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT); + } + setControlFlags(AGENT_CONTROL_FLY); + gSavedSettings.setBOOL("FlyBtnState", TRUE); + } + else + { + clearControlFlags(AGENT_CONTROL_FLY); + gSavedSettings.setBOOL("FlyBtnState", FALSE); + } + mbFlagsDirty = TRUE; +} + + +// UI based mechanism of setting fly state +//----------------------------------------------------------------------------- +// toggleFlying() +//----------------------------------------------------------------------------- +void LLAgent::toggleFlying() +{ + BOOL fly = !(mControlFlags & AGENT_CONTROL_FLY); + + setFlying( fly ); + resetView(); +} + +void LLAgent::togglePhantom() +{ + BOOL phan = !(exlPhantom); + + setPhantom( phan ); +} + + +//----------------------------------------------------------------------------- +// setRegion() +//----------------------------------------------------------------------------- +void LLAgent::setRegion(LLViewerRegion *regionp) +{ + llassert(regionp); + if (mRegionp != regionp) + { + // std::string host_name; + // host_name = regionp->getHost().getHostName(); + + std::string ip = regionp->getHost().getString(); + llinfos << "Moving agent into region: " << regionp->getName() + << " located at " << ip << llendl; + if (mRegionp) + { + // We've changed regions, we're now going to change our agent coordinate frame. + mAgentOriginGlobal = regionp->getOriginGlobal(); + LLVector3d agent_offset_global = mRegionp->getOriginGlobal(); + + LLVector3 delta; + delta.setVec(regionp->getOriginGlobal() - mRegionp->getOriginGlobal()); + + setPositionAgent(getPositionAgent() - delta); + + LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin(); + LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta); + + // Update all of the regions. + LLWorld::getInstance()->updateAgentOffset(agent_offset_global); + + // Hack to keep sky in the agent's region, otherwise it may get deleted - DJS 08/02/02 + // *TODO: possibly refactor into gSky->setAgentRegion(regionp)? -Brad + if (gSky.mVOSkyp) + { + gSky.mVOSkyp->setRegion(regionp); + } + if (gSky.mVOGroundp) + { + gSky.mVOGroundp->setRegion(regionp); + } + + } + else + { + // First time initialization. + // We've changed regions, we're now going to change our agent coordinate frame. + mAgentOriginGlobal = regionp->getOriginGlobal(); + + LLVector3 delta; + delta.setVec(regionp->getOriginGlobal()); + + setPositionAgent(getPositionAgent() - delta); + LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin(); + LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta); + + // Update all of the regions. + LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal); + } + } + mRegionp = regionp; + + // Must shift hole-covering water object locations because local + // coordinate frame changed. + LLWorld::getInstance()->updateWaterObjects(); + + // keep a list of regions we've been too + // this is just an interesting stat, logged at the dataserver + // we could trake this at the dataserver side, but that's harder + U64 handle = regionp->getHandle(); + mRegionsVisited.insert(handle); + + LLSelectMgr::getInstance()->updateSelectionCenter(); +} + + +//----------------------------------------------------------------------------- +// getRegion() +//----------------------------------------------------------------------------- +LLViewerRegion *LLAgent::getRegion() const +{ + return mRegionp; +} + + +const LLHost& LLAgent::getRegionHost() const +{ + if (mRegionp) + { + return mRegionp->getHost(); + } + else + { + return LLHost::invalid; + } +} + +//----------------------------------------------------------------------------- +// getSLURL() +// returns empty() if getRegion() == NULL +//----------------------------------------------------------------------------- +std::string LLAgent::getSLURL() const +{ + std::string slurl; + LLViewerRegion *regionp = getRegion(); + if (regionp) + { + LLVector3d agentPos = getPositionGlobal(); + S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) ); + S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); + S32 z = llround( (F32)agentPos.mdV[VZ] ); + slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z); + } + return slurl; +} + +//----------------------------------------------------------------------------- +// inPrelude() +//----------------------------------------------------------------------------- +BOOL LLAgent::inPrelude() +{ + return mRegionp && mRegionp->isPrelude(); +} + + +//----------------------------------------------------------------------------- +// canManageEstate() +//----------------------------------------------------------------------------- + +BOOL LLAgent::canManageEstate() const +{ + return mRegionp && mRegionp->canManageEstate(); +} + +//----------------------------------------------------------------------------- +// sendMessage() +//----------------------------------------------------------------------------- +void LLAgent::sendMessage() +{ + if (gDisconnected) + { + llwarns << "Trying to send message when disconnected!" << llendl; + return; + } + if (!mRegionp) + { + llerrs << "No region for agent yet!" << llendl; + } + gMessageSystem->sendMessage(mRegionp->getHost()); +} + + +//----------------------------------------------------------------------------- +// sendReliableMessage() +//----------------------------------------------------------------------------- +void LLAgent::sendReliableMessage() +{ + if (gDisconnected) + { + lldebugs << "Trying to send message when disconnected!" << llendl; + return; + } + if (!mRegionp) + { + lldebugs << "LLAgent::sendReliableMessage No region for agent yet, not sending message!" << llendl; + return; + } + gMessageSystem->sendReliable(mRegionp->getHost()); +} + +//----------------------------------------------------------------------------- +// getVelocity() +//----------------------------------------------------------------------------- +LLVector3 LLAgent::getVelocity() const +{ + if (mAvatarObject.notNull()) + { + return mAvatarObject->getVelocity(); + } + else + { + return LLVector3::zero; + } +} + + +//----------------------------------------------------------------------------- +// setPositionAgent() +//----------------------------------------------------------------------------- +void LLAgent::setPositionAgent(const LLVector3 &pos_agent) +{ + if (!pos_agent.isFinite()) + { + llerrs << "setPositionAgent is not a number" << llendl; + } + + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLVector3 pos_agent_sitting; + LLVector3d pos_agent_d; + LLViewerObject *parent = (LLViewerObject*)mAvatarObject->getParent(); + + pos_agent_sitting = mAvatarObject->getPosition() * parent->getRotation() + parent->getPositionAgent(); + pos_agent_d.setVec(pos_agent_sitting); + + mFrameAgent.setOrigin(pos_agent_sitting); + mPositionGlobal = pos_agent_d + mAgentOriginGlobal; + } + else + { + mFrameAgent.setOrigin(pos_agent); + + LLVector3d pos_agent_d; + pos_agent_d.setVec(pos_agent); + mPositionGlobal = pos_agent_d + mAgentOriginGlobal; + } +} + +//----------------------------------------------------------------------------- +// slamLookAt() +//----------------------------------------------------------------------------- +void LLAgent::slamLookAt(const LLVector3 &look_at) +{ + LLVector3 look_at_norm = look_at; + look_at_norm.mV[VZ] = 0.f; + look_at_norm.normalize(); + resetAxes(look_at_norm); +} + +//----------------------------------------------------------------------------- +// getPositionGlobal() +//----------------------------------------------------------------------------- +const LLVector3d &LLAgent::getPositionGlobal() const +{ + if (mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull()) + { + mPositionGlobal = getPosGlobalFromAgent(mAvatarObject->getRenderPosition()); + } + else + { + mPositionGlobal = getPosGlobalFromAgent(mFrameAgent.getOrigin()); + } + + return mPositionGlobal; +} + +//----------------------------------------------------------------------------- +// getPositionAgent() +//----------------------------------------------------------------------------- +const LLVector3 &LLAgent::getPositionAgent() +{ + if(mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull()) + { + mFrameAgent.setOrigin(mAvatarObject->getRenderPosition()); + } + + return mFrameAgent.getOrigin(); +} + +//----------------------------------------------------------------------------- +// getRegionsVisited() +//----------------------------------------------------------------------------- +S32 LLAgent::getRegionsVisited() const +{ + return mRegionsVisited.size(); +} + +//----------------------------------------------------------------------------- +// getDistanceTraveled() +//----------------------------------------------------------------------------- +F64 LLAgent::getDistanceTraveled() const +{ + return mDistanceTraveled; +} + + +//----------------------------------------------------------------------------- +// getPosAgentFromGlobal() +//----------------------------------------------------------------------------- +LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const +{ + LLVector3 pos_agent; + pos_agent.setVec(pos_global - mAgentOriginGlobal); + return pos_agent; +} + + +//----------------------------------------------------------------------------- +// getPosGlobalFromAgent() +//----------------------------------------------------------------------------- +LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const +{ + LLVector3d pos_agent_d; + pos_agent_d.setVec(pos_agent); + return pos_agent_d + mAgentOriginGlobal; +} + + +//----------------------------------------------------------------------------- +// resetAxes() +//----------------------------------------------------------------------------- +void LLAgent::resetAxes() +{ + mFrameAgent.resetAxes(); +} + + +// Copied from LLCamera::setOriginAndLookAt +// Look_at must be unit vector +//----------------------------------------------------------------------------- +// resetAxes() +//----------------------------------------------------------------------------- +void LLAgent::resetAxes(const LLVector3 &look_at) +{ + LLVector3 skyward = getReferenceUpVector(); + + // if look_at has zero length, fail + // if look_at and skyward are parallel, fail + // + // Test both of these conditions with a cross product. + LLVector3 cross(look_at % skyward); + if (cross.isNull()) + { + llinfos << "LLAgent::resetAxes cross-product is zero" << llendl; + return; + } + + // Make sure look_at and skyward are not parallel + // and neither are zero length + LLVector3 left(skyward % look_at); + LLVector3 up(look_at % left); + + mFrameAgent.setAxes(look_at, left, up); +} + + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLAgent::rotate(F32 angle, const LLVector3 &axis) +{ + mFrameAgent.rotate(angle, axis); +} + + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z) +{ + mFrameAgent.rotate(angle, x, y, z); +} + + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLAgent::rotate(const LLMatrix3 &matrix) +{ + mFrameAgent.rotate(matrix); +} + + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLAgent::rotate(const LLQuaternion &quaternion) +{ + mFrameAgent.rotate(quaternion); +} + + +//----------------------------------------------------------------------------- +// getReferenceUpVector() +//----------------------------------------------------------------------------- +LLVector3 LLAgent::getReferenceUpVector() +{ + // this vector is in the coordinate frame of the avatar's parent object, or the world if none + LLVector3 up_vector = LLVector3::z_axis; + if (mAvatarObject.notNull() && + mAvatarObject->getParent() && + mAvatarObject->mDrawable.notNull()) + { + U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + // and in third person... + if (camera_mode == CAMERA_MODE_THIRD_PERSON) + { + // make the up vector point to the absolute +z axis + up_vector = up_vector * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); + } + else if (camera_mode == CAMERA_MODE_MOUSELOOK) + { + // make the up vector point to the avatar's +z axis + up_vector = up_vector * mAvatarObject->mDrawable->getRotation(); + } + } + + return up_vector; +} + + +// Radians, positive is forward into ground +//----------------------------------------------------------------------------- +// pitch() +//----------------------------------------------------------------------------- +void LLAgent::pitch(F32 angle) +{ + // don't let user pitch if pointed almost all the way down or up + mFrameAgent.pitch(clampPitchToLimits(angle)); +} + + +// Radians, positive is forward into ground +//----------------------------------------------------------------------------- +// clampPitchToLimits() +//----------------------------------------------------------------------------- +F32 LLAgent::clampPitchToLimits(F32 angle) +{ + // A dot B = mag(A) * mag(B) * cos(angle between A and B) + // so... cos(angle between A and B) = A dot B / mag(A) / mag(B) + // = A dot B for unit vectors + + LLVector3 skyward = getReferenceUpVector(); + + F32 look_down_limit; + F32 look_up_limit = 10.f * DEG_TO_RAD; + + F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward ); + + if (mAvatarObject.notNull() && mAvatarObject->mIsSitting) + { + look_down_limit = 130.f * DEG_TO_RAD; + } + else + { + look_down_limit = 170.f * DEG_TO_RAD; + } + + // clamp pitch to limits + if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit)) + { + angle = look_down_limit - angle_from_skyward; + } + else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit)) + { + angle = look_up_limit - angle_from_skyward; + } + + return angle; +} + + +//----------------------------------------------------------------------------- +// roll() +//----------------------------------------------------------------------------- +void LLAgent::roll(F32 angle) +{ + mFrameAgent.roll(angle); +} + + +//----------------------------------------------------------------------------- +// yaw() +//----------------------------------------------------------------------------- +void LLAgent::yaw(F32 angle) +{ + if (!rotateGrabbed()) + { + mFrameAgent.rotate(angle, getReferenceUpVector()); + } +} + + +// Returns a quat that represents the rotation of the agent in the absolute frame +//----------------------------------------------------------------------------- +// getQuat() +//----------------------------------------------------------------------------- +LLQuaternion LLAgent::getQuat() const +{ + return mFrameAgent.getQuaternion(); +} + + +//----------------------------------------------------------------------------- +// calcFocusOffset() +//----------------------------------------------------------------------------- +LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y) +{ + LLMatrix4 obj_matrix = object->getRenderMatrix(); + LLQuaternion obj_rot = object->getRenderRotation(); + LLVector3 obj_pos = object->getRenderPosition(); + + BOOL is_avatar = object->isAvatar(); + // if is avatar - don't do any funk heuristics to position the focal point + // see DEV-30589 + if (is_avatar) + { + return original_focus_point - obj_pos; + } + + + LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation + LLVector3 object_extents = object->getScale(); + // make sure they object extents are non-zero + object_extents.clamp(0.001f, F32_MAX); + + // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object + LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); + obj_to_cam_ray.rotVec(inv_obj_rot); + obj_to_cam_ray.normalize(); + + // obj_to_cam_ray_proportions are the (positive) ratios of + // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. + LLVector3 obj_to_cam_ray_proportions; + obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); + obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); + obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); + + // find the largest ratio stored in obj_to_cam_ray_proportions + // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera + LLVector3 longest_object_axis; + // is x-axis longest? + if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY] + && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) + { + // then grab it + longest_object_axis.setVec(obj_matrix.getFwdRow4()); + } + // is y-axis longest? + else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) + { + // then grab it + longest_object_axis.setVec(obj_matrix.getLeftRow4()); + } + // otherwise, use z axis + else + { + longest_object_axis.setVec(obj_matrix.getUpRow4()); + } + + // Use this axis as the normal to project mouse click on to plane with that normal, at the object center. + // This generates a point behind the mouse cursor that is approximately in the middle of the object in + // terms of depth. + // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. + // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable + // eccentricity to the object orientation + LLVector3 focus_plane_normal(longest_object_axis); + focus_plane_normal.normalize(); + + LLVector3d focus_pt_global; + gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); + LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); + + // find vector from camera to focus point in object space + LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); + camera_to_focus_vec.rotVec(inv_obj_rot); + + // find vector from object origin to focus point in object coordinates + LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; + // convert to object-local space + focus_offset_from_object_center.rotVec(inv_obj_rot); + + // We need to project the focus point back into the bounding box of the focused object. + // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis + LLVector3 clip_fraction; + + // for each axis... + for (U32 axis = VX; axis <= VZ; axis++) + { + //...calculate distance that focus offset sits outside of bounding box along that axis... + //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center + F32 dist_out_of_bounds; + if (focus_offset_from_object_center.mV[axis] > 0.f) + { + dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); + } + else + { + dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); + } + + //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis + if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) + { + // don't divide by very small number + clip_fraction.mV[axis] = 0.f; + } + else + { + clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; + } + } + + LLVector3 abs_clip_fraction = clip_fraction; + abs_clip_fraction.abs(); + + // find axis of focus offset that is *most* outside the bounding box and use that to + // rescale focus offset to inside object extents + if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] + && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) + { + focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; + } + else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) + { + focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; + } + else + { + focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; + } + + // convert back to world space + focus_offset_from_object_center.rotVec(obj_rot); + + // now, based on distance of camera from object relative to object size + // push the focus point towards the near surface of the object when (relatively) close to the objcet + // or keep the focus point in the object middle when (relatively) far + // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars + // is almost always "tumble about middle" and not "spin around surface point" + if (!is_avatar) + { + LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); + + //now that we have the object relative position, we should bias toward the center of the object + //based on the distance of the camera to the focus point vs. the distance of the camera to the focus + + F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); + F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); + + + LLBBox obj_bbox = object->getBoundingBoxAgent(); + F32 bias = 0.f; + + // virtual_camera_pos is the camera position we are simulating by backing the camera off + // and adjusting the FOV + LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); + + // if the camera is inside the object (large, hollow objects, for example) + // leave focus point all the way to destination depth, away from object center + if(!obj_bbox.containsPointAgent(virtual_camera_pos)) + { + // perform magic number biasing of focus point towards surface vs. planar center + bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); + obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); + } + + focus_offset_from_object_center = obj_rel; + } + + return focus_offset_from_object_center; +} + +//----------------------------------------------------------------------------- +// calcCameraMinDistance() +//----------------------------------------------------------------------------- +BOOL LLAgent::calcCameraMinDistance(F32 &obj_min_distance) +{ + BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) + + if (!mFocusObject || mFocusObject->isDead()) + { + obj_min_distance = 0.f; + return TRUE; + } + + if (mFocusObject->mDrawable.isNull()) + { +#ifdef LL_RELEASE_FOR_DOWNLOAD + llwarns << "Focus object with no drawable!" << llendl; +#else + mFocusObject->dump(); + llerrs << "Focus object with no drawable!" << llendl; +#endif + obj_min_distance = 0.f; + return TRUE; + } + + LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); + LLVector3 target_offset_origin = mFocusObjectOffset; + LLVector3 camera_offset_target(getCameraPositionAgent() - getPosAgentFromGlobal(mFocusTargetGlobal)); + + // convert offsets into object local space + camera_offset_target.rotVec(inv_object_rot); + target_offset_origin.rotVec(inv_object_rot); + + // push around object extents based on target offset + LLVector3 object_extents = mFocusObject->getScale(); + if (mFocusObject->isAvatar()) + { + // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) + object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; + object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; + object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; + soft_limit = TRUE; + } + LLVector3 abs_target_offset = target_offset_origin; + abs_target_offset.abs(); + + LLVector3 target_offset_dir = target_offset_origin; + F32 object_radius = mFocusObject->getVObjRadius(); + + BOOL target_outside_object_extents = FALSE; + + for (U32 i = VX; i <= VZ; i++) + { + if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) + { + target_outside_object_extents = TRUE; + } + if (camera_offset_target.mV[i] > 0.f) + { + object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; + } + else + { + object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; + } + } + + // don't shrink the object extents so far that the object inverts + object_extents.clamp(0.001f, F32_MAX); + + // move into first octant + LLVector3 camera_offset_target_abs_norm = camera_offset_target; + camera_offset_target_abs_norm.abs(); + // make sure offset is non-zero + camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); + camera_offset_target_abs_norm.normalize(); + + // find camera position relative to normalized object extents + LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; + camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; + camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; + camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; + + if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && + camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) + { + if (camera_offset_target_abs_norm.mV[VX] < 0.001f) + { + obj_min_distance = object_extents.mV[VX] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; + } + } + else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) + { + if (camera_offset_target_abs_norm.mV[VY] < 0.001f) + { + obj_min_distance = object_extents.mV[VY] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; + } + } + else + { + if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) + { + obj_min_distance = object_extents.mV[VZ] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; + } + } + + LLVector3 object_split_axis; + LLVector3 target_offset_scaled = target_offset_origin; + target_offset_scaled.abs(); + target_offset_scaled.normalize(); + target_offset_scaled.mV[VX] /= object_extents.mV[VX]; + target_offset_scaled.mV[VY] /= object_extents.mV[VY]; + target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; + + if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && + target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) + { + object_split_axis = LLVector3::x_axis; + } + else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) + { + object_split_axis = LLVector3::y_axis; + } + else + { + object_split_axis = LLVector3::z_axis; + } + + LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); + + // length projected orthogonal to target offset + F32 camera_offset_dist = (camera_offset_object - target_offset_dir * (camera_offset_object * target_offset_dir)).magVec(); + + // calculate whether the target point would be "visible" if it were outside the bounding box + // on the opposite of the splitting plane defined by object_split_axis; + BOOL exterior_target_visible = FALSE; + if (camera_offset_dist > object_radius) + { + // target is visible from camera, so turn off fov zoom + exterior_target_visible = TRUE; + } + + F32 camera_offset_clip = camera_offset_object * object_split_axis; + F32 target_offset_clip = target_offset_dir * object_split_axis; + + // target has moved outside of object extents + // check to see if camera and target are on same side + if (target_outside_object_extents) + { + if (camera_offset_clip > 0.f && target_offset_clip > 0.f) + { + return FALSE; + } + else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) + { + return FALSE; + } + } + + // clamp obj distance to diagonal of 10 by 10 cube + obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); + + obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); + + return TRUE; +} + +F32 LLAgent::getCameraZoomFraction() +{ + // 0.f -> camera zoomed all the way out + // 1.f -> camera zoomed all the way in + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // already [0,1] + return mHUDTargetZoom; + } + else if (mFocusOnAvatar && cameraThirdPerson()) + { + return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); + } + else if (cameraCustomizeAvatar()) + { + F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); + return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); + } + else + { + F32 min_zoom; + const F32 DIST_FUDGE = 16.f; // meters + F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, + LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, + MAX_CAMERA_DISTANCE_FROM_AGENT); + + F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + else + { + min_zoom = LAND_MIN_ZOOM; + } + + return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f); + } +} + +void LLAgent::setCameraZoomFraction(F32 fraction) +{ + // 0.f -> camera zoomed all the way out + // 1.f -> camera zoomed all the way in + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + mHUDTargetZoom = fraction; + } + else if (mFocusOnAvatar && cameraThirdPerson()) + { + mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); + } + else if (cameraCustomizeAvatar()) + { + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; + camera_offset_dir.normalize(); + mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); + } + else + { + F32 min_zoom = LAND_MIN_ZOOM; + const F32 DIST_FUDGE = 16.f; // meters + F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, + LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, + MAX_CAMERA_DISTANCE_FROM_AGENT); + + if (mFocusObject.notNull()) + { + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + } + + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; + camera_offset_dir.normalize(); + mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); + } + startCameraAnimation(); +} + + +//----------------------------------------------------------------------------- +// cameraOrbitAround() +//----------------------------------------------------------------------------- +void LLAgent::cameraOrbitAround(const F32 radians) +{ + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // do nothing for hud selection + } + else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) + { + mFrameAgent.rotate(radians, getReferenceUpVector()); + } + else + { + mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); + + cameraZoomIn(1.f); + } +} + + +//----------------------------------------------------------------------------- +// cameraOrbitOver() +//----------------------------------------------------------------------------- +void LLAgent::cameraOrbitOver(const F32 angle) +{ + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // do nothing for hud selection + } + else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + pitch(angle); + } + else + { + LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); + camera_offset_unit.normalize(); + + F32 angle_from_up = acos( camera_offset_unit * getReferenceUpVector() ); + + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); + mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); + + cameraZoomIn(1.f); + } +} + +//----------------------------------------------------------------------------- +// cameraZoomIn() +//----------------------------------------------------------------------------- +void LLAgent::cameraZoomIn(const F32 fraction) +{ + if (gDisconnected) + { + return; + } + + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // just update hud zoom level + mHUDTargetZoom /= fraction; + return; + } + + + LLVector3d camera_offset(mCameraFocusOffsetTarget); + LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); + F32 min_zoom = LAND_MIN_ZOOM; + F32 current_distance = (F32)camera_offset_unit.normalize(); + F32 new_distance = current_distance * fraction; + + // Don't move through focus point + if (mFocusObject) + { + LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); + + if (mFocusObject->isAvatar()) + { + calcCameraMinDistance(min_zoom); + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + + new_distance = llmax(new_distance, min_zoom); + + // Don't zoom too far back + const F32 DIST_FUDGE = 16.f; // meters + F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, + LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); + + if (new_distance > max_distance) + { + // screw cam constraints + //new_distance = max_distance; + // + + /* + // Unless camera is unlocked + if (!LLViewerCamera::sDisableCameraConstraints) + { + return; + } + */ + } + + if( cameraCustomizeAvatar() ) + { + new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM ); + } + + mCameraFocusOffsetTarget = new_distance * camera_offset_unit; +} + +//----------------------------------------------------------------------------- +// cameraOrbitIn() +//----------------------------------------------------------------------------- +void LLAgent::cameraOrbitIn(const F32 meters) +{ + if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + F32 camera_offset_dist = llmax(0.001f, mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); + + mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; + + if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) + { + // No need to animate, camera is already there. + changeCameraToMouselook(FALSE); + } + + mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); + } + else + { + LLVector3d camera_offset(mCameraFocusOffsetTarget); + LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); + F32 current_distance = (F32)camera_offset_unit.normalize(); + F32 new_distance = current_distance - meters; + F32 min_zoom = LAND_MIN_ZOOM; + + // Don't move through focus point + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + + new_distance = llmax(new_distance, min_zoom); + + // Don't zoom too far back + const F32 DIST_FUDGE = 16.f; // meters + F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, + LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); + + if (new_distance > max_distance) + { + // Unless camera is unlocked + if (!gSavedSettings.getBOOL("DisableCameraConstraints")) + { + return; + } + } + + if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() ) + { + new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM ); + } + + // Compute new camera offset + mCameraFocusOffsetTarget = new_distance * camera_offset_unit; + cameraZoomIn(1.f); + } +} + + +//----------------------------------------------------------------------------- +// cameraPanIn() +//----------------------------------------------------------------------------- +void LLAgent::cameraPanIn(F32 meters) +{ + LLVector3d at_axis; + at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); + + mFocusTargetGlobal += meters * at_axis; + mFocusGlobal = mFocusTargetGlobal; + // don't enforce zoom constraints as this is the only way for users to get past them easily + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +} + +//----------------------------------------------------------------------------- +// cameraPanLeft() +//----------------------------------------------------------------------------- +void LLAgent::cameraPanLeft(F32 meters) +{ + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + + mFocusTargetGlobal += meters * left_axis; + mFocusGlobal = mFocusTargetGlobal; + + // disable smoothing for camera pan, which causes some residents unhappiness + mCameraSmoothingStop = TRUE; + + cameraZoomIn(1.f); + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +} + +//----------------------------------------------------------------------------- +// cameraPanUp() +//----------------------------------------------------------------------------- +void LLAgent::cameraPanUp(F32 meters) +{ + LLVector3d up_axis; + up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); + + mFocusTargetGlobal += meters * up_axis; + mFocusGlobal = mFocusTargetGlobal; + + // disable smoothing for camera pan, which causes some residents unhappiness + mCameraSmoothingStop = TRUE; + + cameraZoomIn(1.f); + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +} + +//----------------------------------------------------------------------------- +// setKey() +//----------------------------------------------------------------------------- +void LLAgent::setKey(const S32 direction, S32 &key) +{ + if (direction > 0) + { + key = 1; + } + else if (direction < 0) + { + key = -1; + } + else + { + key = 0; + } +} + + +//----------------------------------------------------------------------------- +// getControlFlags() +//----------------------------------------------------------------------------- +U32 LLAgent::getControlFlags() +{ +/* + // HACK -- avoids maintenance of control flags when camera mode is turned on or off, + // only worries about it when the flags are measured + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + if ( !(mControlFlags & AGENT_CONTROL_MOUSELOOK) ) + { + mControlFlags |= AGENT_CONTROL_MOUSELOOK; + } + } +*/ + return mControlFlags; +} + +//----------------------------------------------------------------------------- +// setControlFlags() +//----------------------------------------------------------------------------- +void LLAgent::setControlFlags(U32 mask) +{ + mControlFlags |= mask; + mbFlagsDirty = TRUE; +} + + +//----------------------------------------------------------------------------- +// clearControlFlags() +//----------------------------------------------------------------------------- +void LLAgent::clearControlFlags(U32 mask) +{ + U32 old_flags = mControlFlags; + mControlFlags &= ~mask; + if (old_flags != mControlFlags) + { + mbFlagsDirty = TRUE; + } +} + +//----------------------------------------------------------------------------- +// controlFlagsDirty() +//----------------------------------------------------------------------------- +BOOL LLAgent::controlFlagsDirty() const +{ + return mbFlagsDirty; +} + +//----------------------------------------------------------------------------- +// enableControlFlagReset() +//----------------------------------------------------------------------------- +void LLAgent::enableControlFlagReset() +{ + mbFlagsNeedReset = TRUE; +} + +//----------------------------------------------------------------------------- +// resetControlFlags() +//----------------------------------------------------------------------------- +void LLAgent::resetControlFlags() +{ + if (mbFlagsNeedReset) + { + mbFlagsNeedReset = FALSE; + mbFlagsDirty = FALSE; + // reset all of the ephemeral flags + // some flags are managed elsewhere + mControlFlags &= AGENT_CONTROL_AWAY | AGENT_CONTROL_FLY | AGENT_CONTROL_MOUSELOOK; + } +} + +//----------------------------------------------------------------------------- +// setAFK() +//----------------------------------------------------------------------------- +void LLAgent::setAFK() +{ + // Drones can't go AFK + if (gNoRender) + { + return; + } + + if (!gAgent.getRegion()) + { + // Don't set AFK if we're not talking to a region yet. + return; + } + + if (!(mControlFlags & AGENT_CONTROL_AWAY)) + { + sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); + setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP); + gAwayTimer.start(); + if (gAFKMenu) + { + //*TODO:Translate + gAFKMenu->setLabel(std::string("Set Not Away")); + } + } +} + +//----------------------------------------------------------------------------- +// clearAFK() +//----------------------------------------------------------------------------- +void LLAgent::clearAFK() +{ + gAwayTriggerTimer.reset(); + if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); + if (gSavedSettings.getBOOL("FakeAway") == TRUE) return; + + // Gods can sometimes get into away state (via gestures) + // without setting the appropriate control flag. JC + LLVOAvatar* av = mAvatarObject; + if (mControlFlags & AGENT_CONTROL_AWAY + || (av + && (av->mSignaledAnimations.find(ANIM_AGENT_AWAY) != av->mSignaledAnimations.end()))) + { + sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); + clearControlFlags(AGENT_CONTROL_AWAY); + if (gAFKMenu) + { + //*TODO:Translate + gAFKMenu->setLabel(std::string("Set Away")); + } + } +} + +//----------------------------------------------------------------------------- +// getAFK() +//----------------------------------------------------------------------------- +BOOL LLAgent::getAFK() const +{ + return (mControlFlags & AGENT_CONTROL_AWAY) != 0; +} + +//----------------------------------------------------------------------------- +// setBusy() +//----------------------------------------------------------------------------- +void LLAgent::setBusy() +{ + sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START); + mIsBusy = TRUE; + if (gBusyMenu) + { + //*TODO:Translate + gBusyMenu->setLabel(std::string("Set Not Busy")); + } + LLFloaterMute::getInstance()->updateButtons(); +} + +//----------------------------------------------------------------------------- +// clearBusy() +//----------------------------------------------------------------------------- +void LLAgent::clearBusy() +{ + mIsBusy = FALSE; + sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP); + if (gBusyMenu) + { + //*TODO:Translate + gBusyMenu->setLabel(std::string("Set Busy")); + } + LLFloaterMute::getInstance()->updateButtons(); +} + +//----------------------------------------------------------------------------- +// getBusy() +//----------------------------------------------------------------------------- +BOOL LLAgent::getBusy() const +{ + return mIsBusy; +} + + +//----------------------------------------------------------------------------- +// startAutoPilotGlobal() +//----------------------------------------------------------------------------- +void LLAgent::startAutoPilotGlobal(const LLVector3d &target_global, const std::string& behavior_name, const LLQuaternion *target_rotation, void (*finish_callback)(BOOL, void *), void *callback_data, F32 stop_distance, F32 rot_threshold) +{ + if (!gAgent.getAvatarObject()) + { + return; + } + + mAutoPilotFinishedCallback = finish_callback; + mAutoPilotCallbackData = callback_data; + mAutoPilotRotationThreshold = rot_threshold; + mAutoPilotBehaviorName = behavior_name; + + LLVector3d delta_pos( target_global ); + delta_pos -= getPositionGlobal(); + F64 distance = delta_pos.magVec(); + LLVector3d trace_target = target_global; + + trace_target.mdV[VZ] -= 10.f; + + LLVector3d intersection; + LLVector3 normal; + LLViewerObject *hit_obj; + F32 heightDelta = LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, trace_target, intersection, normal, &hit_obj); + + if (stop_distance > 0.f) + { + mAutoPilotStopDistance = stop_distance; + } + else + { + // Guess at a reasonable stop distance. + mAutoPilotStopDistance = fsqrtf( distance ); + if (mAutoPilotStopDistance < 0.5f) + { + mAutoPilotStopDistance = 0.5f; + } + } + + mAutoPilotFlyOnStop = getFlying(); + + if (distance > 30.0) + { + setFlying(TRUE); + } + + if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f)) + { + setFlying(TRUE); + mAutoPilotFlyOnStop = TRUE; + } + + mAutoPilot = TRUE; + mAutoPilotTargetGlobal = target_global; + + // trace ray down to find height of destination from ground + LLVector3d traceEndPt = target_global; + traceEndPt.mdV[VZ] -= 20.f; + + LLVector3d targetOnGround; + LLVector3 groundNorm; + LLViewerObject *obj; + + LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj); + F64 target_height = llmax((F64)gAgent.getAvatarObject()->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]); + + // clamp z value of target to minimum height above ground + mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height; + mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal); + if (target_rotation) + { + mAutoPilotUseRotation = TRUE; + mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation; + mAutoPilotTargetFacing.mV[VZ] = 0.f; + mAutoPilotTargetFacing.normalize(); + } + else + { + mAutoPilotUseRotation = FALSE; + } + + mAutoPilotNoProgressFrameCount = 0; +} + + +//----------------------------------------------------------------------------- +// startFollowPilot() +//----------------------------------------------------------------------------- +void LLAgent::startFollowPilot(const LLUUID &leader_id) +{ + if (!mAutoPilot) return; + + mLeaderID = leader_id; + if ( mLeaderID.isNull() ) return; + + LLViewerObject* object = gObjectList.findObject(mLeaderID); + if (!object) + { + mLeaderID = LLUUID::null; + return; + } + + startAutoPilotGlobal(object->getPositionGlobal()); +} + + +//----------------------------------------------------------------------------- +// stopAutoPilot() +//----------------------------------------------------------------------------- +void LLAgent::stopAutoPilot(BOOL user_cancel) +{ + if (mAutoPilot) + { + mAutoPilot = FALSE; + if (mAutoPilotUseRotation && !user_cancel) + { + resetAxes(mAutoPilotTargetFacing); + } + //NB: auto pilot can terminate for a reason other than reaching the destination + if (mAutoPilotFinishedCallback) + { + mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData); + } + mLeaderID = LLUUID::null; + + // If the user cancelled, don't change the fly state + if (!user_cancel) + { + setFlying(mAutoPilotFlyOnStop); + } + setControlFlags(AGENT_CONTROL_STOP); + + if (user_cancel && !mAutoPilotBehaviorName.empty()) + { + if (mAutoPilotBehaviorName == "Sit") + LLNotifications::instance().add("CancelledSit"); + else if (mAutoPilotBehaviorName == "Attach") + LLNotifications::instance().add("CancelledAttach"); + else + LLNotifications::instance().add("Cancelled"); + } + } +} + + +// Returns necessary agent pitch and yaw changes, radians. +//----------------------------------------------------------------------------- +// autoPilot() +//----------------------------------------------------------------------------- +void LLAgent::autoPilot(F32 *delta_yaw) +{ + if (mAutoPilot) + { + if (!mLeaderID.isNull()) + { + LLViewerObject* object = gObjectList.findObject(mLeaderID); + if (!object) + { + stopAutoPilot(); + return; + } + mAutoPilotTargetGlobal = object->getPositionGlobal(); + } + + if (mAvatarObject.isNull()) + { + return; + } + + if (mAvatarObject->mInAir) + { + setFlying(TRUE); + } + + LLVector3 at; + at.setVec(mFrameAgent.getAtAxis()); + LLVector3 target_agent = getPosAgentFromGlobal(mAutoPilotTargetGlobal); + LLVector3 direction = target_agent - getPositionAgent(); + + F32 target_dist = direction.magVec(); + + if (target_dist >= mAutoPilotTargetDist) + { + mAutoPilotNoProgressFrameCount++; + if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped) + { + stopAutoPilot(); + return; + } + } + + mAutoPilotTargetDist = target_dist; + + // Make this a two-dimensional solution + at.mV[VZ] = 0.f; + direction.mV[VZ] = 0.f; + + at.normalize(); + F32 xy_distance = direction.normalize(); + + F32 yaw = 0.f; + if (mAutoPilotTargetDist > mAutoPilotStopDistance) + { + yaw = angle_between(mFrameAgent.getAtAxis(), direction); + } + else if (mAutoPilotUseRotation) + { + // we're close now just aim at target facing + yaw = angle_between(at, mAutoPilotTargetFacing); + direction = mAutoPilotTargetFacing; + } + + yaw = 4.f * yaw / gFPSClamped; + + // figure out which direction to turn + LLVector3 scratch(at % direction); + + if (scratch.mV[VZ] > 0.f) + { + setControlFlags(AGENT_CONTROL_YAW_POS); + } + else + { + yaw = -yaw; + setControlFlags(AGENT_CONTROL_YAW_NEG); + } + + *delta_yaw = yaw; + + // Compute when to start slowing down and when to stop + F32 stop_distance = mAutoPilotStopDistance; + F32 slow_distance; + if (getFlying()) + { + slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f); + stop_distance = llmax(2.f, mAutoPilotStopDistance); + } + else + { + slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f); + } + + // If we're flying, handle autopilot points above or below you. + if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE) + { + if (mAvatarObject.notNull()) + { + F64 current_height = mAvatarObject->getPositionGlobal().mdV[VZ]; + F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height); + F32 slope = delta_z / xy_distance; + if (slope > 0.45f && delta_z > 6.f) + { + setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS); + } + else if (slope > 0.002f && delta_z > 0.5f) + { + setControlFlags(AGENT_CONTROL_UP_POS); + } + else if (slope < -0.45f && delta_z < -6.f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND) + { + setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG); + } + else if (slope < -0.002f && delta_z < -0.5f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND) + { + setControlFlags(AGENT_CONTROL_UP_NEG); + } + } + } + + // calculate delta rotation to target heading + F32 delta_target_heading = angle_between(mFrameAgent.getAtAxis(), mAutoPilotTargetFacing); + + if (xy_distance > slow_distance && yaw < (F_PI / 10.f)) + { + // walking/flying fast + setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS); + } + else if (mAutoPilotTargetDist > mAutoPilotStopDistance) + { + // walking/flying slow + if (at * direction > 0.9f) + { + setControlFlags(AGENT_CONTROL_AT_POS); + } + else if (at * direction < -0.9f) + { + setControlFlags(AGENT_CONTROL_AT_NEG); + } + } + + // check to see if we need to keep rotating to target orientation + if (mAutoPilotTargetDist < mAutoPilotStopDistance) + { + setControlFlags(AGENT_CONTROL_STOP); + if(!mAutoPilotUseRotation || (delta_target_heading < mAutoPilotRotationThreshold)) + { + stopAutoPilot(); + } + } + } +} + + +//----------------------------------------------------------------------------- +// propagate() +//----------------------------------------------------------------------------- +void LLAgent::propagate(const F32 dt) +{ + // Update UI based on agent motion + LLFloaterMove *floater_move = LLFloaterMove::getInstance(); + if (floater_move) + { + floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 ); + floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 ); + floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 ); + floater_move->mSlideRightButton->setToggleState( mLeftKey < 0 ); + floater_move->mTurnLeftButton ->setToggleState( mYawKey > 0.f ); + floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f ); + floater_move->mMoveUpButton ->setToggleState( mUpKey > 0 ); + floater_move->mMoveDownButton ->setToggleState( mUpKey < 0 ); + } + + // handle rotation based on keyboard levels + const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second + yaw( YAW_RATE * mYawKey * dt ); + + const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second + pitch(PITCH_RATE * (F32) mPitchKey * dt); + + // handle auto-land behavior + if (mAvatarObject.notNull()) + { + BOOL in_air = mAvatarObject->mInAir; + LLVector3 land_vel = getVelocity(); + land_vel.mV[VZ] = 0.f; + + if (!in_air + && mUpKey < 0 + && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED + && gSavedSettings.getBOOL("AutomaticFly")) + { + // land automatically + setFlying(FALSE); + } + } + + // clear keys + mAtKey = 0; + mWalkKey = 0; + mLeftKey = 0; + mUpKey = 0; + mYawKey = 0.f; + mPitchKey = 0; +} + +//----------------------------------------------------------------------------- +// updateAgentPosition() +//----------------------------------------------------------------------------- +void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y) +{ + propagate(dt); + + // static S32 cameraUpdateCount = 0; + + rotate(yaw_radians, 0, 0, 1); + + // + // Check for water and land collision, set underwater flag + // + + updateLookAt(mouse_x, mouse_y); +} + +//----------------------------------------------------------------------------- +// updateLookAt() +//----------------------------------------------------------------------------- +void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y) +{ + static LLVector3 last_at_axis; + + + if (mAvatarObject.isNull()) + { + return; + } + + LLQuaternion av_inv_rot = ~mAvatarObject->mRoot.getWorldRotation(); + LLVector3 root_at = LLVector3::x_axis * mAvatarObject->mRoot.getWorldRotation(); + + if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && + (root_at * last_at_axis > 0.95f )) + { + LLVector3 vel = mAvatarObject->getVelocity(); + if (vel.magVecSquared() > 4.f) + { + setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, vel * av_inv_rot); + } + else + { + // *FIX: rotate mframeagent by sit object's rotation? + LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation + LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; + setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset); + } + last_at_axis = root_at; + return; + } + + last_at_axis = root_at; + + if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) + { + setLookAt(LOOKAT_TARGET_NONE, mAvatarObject, LLVector3(-2.f, 0.f, 0.f)); + } + else + { + // Move head based on cursor position + ELookAtType lookAtType = LOOKAT_TARGET_NONE; + LLVector3 headLookAxis; + LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); + + if (cameraMouselook()) + { + lookAtType = LOOKAT_TARGET_MOUSELOOK; + } + else if (cameraThirdPerson()) + { + // range from -.5 to .5 + F32 x_from_center = + ((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f; + F32 y_from_center = + ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f; + + frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); + frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); + lookAtType = LOOKAT_TARGET_FREELOOK; + } + + headLookAxis = frameCamera.getAtAxis(); + // RN: we use world-space offset for mouselook and freelook + //headLookAxis = headLookAxis * av_inv_rot; + setLookAt(lookAtType, mAvatarObject, headLookAxis); + } +} + +// friends and operators + +std::ostream& operator<<(std::ostream &s, const LLAgent &agent) +{ + // This is unfinished, but might never be used. + // We'll just leave it for now; we can always delete it. + s << " { " + << " Frame = " << agent.mFrameAgent << "\n" + << " }"; + return s; +} + + +// ------------------- Beginning of legacy LLCamera hack ---------------------- +// This section is included for legacy LLCamera support until +// it is no longer needed. Some legacy code must exist in +// non-legacy functions, and is labeled with "// legacy" comments. + +//----------------------------------------------------------------------------- +// setAvatarObject() +//----------------------------------------------------------------------------- +void LLAgent::setAvatarObject(LLVOAvatar *avatar) +{ + mAvatarObject = avatar; + + if (!avatar) + { + llinfos << "Setting LLAgent::mAvatarObject to NULL" << llendl; + return; + } + + if (!mLookAt) + { + mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); + } + if (!mPointAt) + { + mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); + } + + if (!mLookAt.isNull()) + { + mLookAt->setSourceObject(avatar); + } + if (!mPointAt.isNull()) + { + mPointAt->setSourceObject(avatar); + } + + sendAgentWearablesRequest(); +} + +// TRUE if your own avatar needs to be rendered. Usually only +// in third person and build. +//----------------------------------------------------------------------------- +// needsRenderAvatar() +//----------------------------------------------------------------------------- +BOOL LLAgent::needsRenderAvatar() +{ + if (cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson) + { + return FALSE; + } + + return mShowAvatar && mGenderChosen; +} + +// TRUE if we need to render your own avatar's head. +BOOL LLAgent::needsRenderHead() +{ + return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook()); +} + +//----------------------------------------------------------------------------- +// startTyping() +//----------------------------------------------------------------------------- +void LLAgent::startTyping() +{ + if (gSavedSettings.getBOOL("FakeAway")) + return; + mTypingTimer.reset(); + + if (getRenderState() & AGENT_STATE_TYPING) + { + // already typing, don't trigger a different animation + return; + } + setRenderState(AGENT_STATE_TYPING); + + if (mChatTimer.getElapsedTimeF32() < 2.f) + { + LLViewerObject* chatter = gObjectList.findObject(mLastChatterID); + if (chatter && chatter->isAvatar()) + { + gAgent.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero); + } + } + + if (gSavedSettings.getBOOL("PlayTypingAnim")) + { + sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); + } + gChatBar->sendChatFromViewer("", CHAT_TYPE_START, FALSE); +} + +//----------------------------------------------------------------------------- +// stopTyping() +//----------------------------------------------------------------------------- +void LLAgent::stopTyping() +{ + if (mRenderState & AGENT_STATE_TYPING) + { + clearRenderState(AGENT_STATE_TYPING); + sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); + gChatBar->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + } +} + +//----------------------------------------------------------------------------- +// setRenderState() +//----------------------------------------------------------------------------- +void LLAgent::setRenderState(U8 newstate) +{ + mRenderState |= newstate; +} + +//----------------------------------------------------------------------------- +// clearRenderState() +//----------------------------------------------------------------------------- +void LLAgent::clearRenderState(U8 clearstate) +{ + mRenderState &= ~clearstate; +} + + +//----------------------------------------------------------------------------- +// getRenderState() +//----------------------------------------------------------------------------- +U8 LLAgent::getRenderState() +{ + if (gNoRender || gKeyboard == NULL) + { + return 0; + } + + // *FIX: don't do stuff in a getter! This is infinite loop city! + if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS) + && (mRenderState & AGENT_STATE_TYPING)) + { + stopTyping(); + } + + if ((!LLSelectMgr::getInstance()->getSelection()->isEmpty() && LLSelectMgr::getInstance()->shouldShowSelection()) + || LLToolMgr::getInstance()->getCurrentTool()->isEditing() ) + { + setRenderState(AGENT_STATE_EDITING); + } + else + { + clearRenderState(AGENT_STATE_EDITING); + } + + return mRenderState; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +static const LLFloaterView::skip_list_t& get_skip_list() +{ + static LLFloaterView::skip_list_t skip_list; + skip_list.insert(LLFloaterMap::getInstance()); + return skip_list; +} + +//----------------------------------------------------------------------------- +// endAnimationUpdateUI() +//----------------------------------------------------------------------------- +void LLAgent::endAnimationUpdateUI() +{ + if (mCameraMode == mLastCameraMode) + { + // We're already done endAnimationUpdateUI for this transition. + return; + } + + // clean up UI from mode we're leaving + if ( mLastCameraMode == CAMERA_MODE_MOUSELOOK ) + { + // show mouse cursor + gViewerWindow->showCursor(); + // show menus + gMenuBarView->setVisible(TRUE); + gStatusBar->setVisibleForMouselook(true); + + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + + // Only pop if we have pushed... + if (TRUE == mViewsPushed) + { + mViewsPushed = FALSE; + gFloaterView->popVisibleAll(get_skip_list()); + } + + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + if( gMorphView ) + { + gMorphView->setVisible( FALSE ); + } + + // Disable mouselook-specific animations + if (mAvatarObject.notNull()) + { + if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) ) + { + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_RIFLE_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BOW_L) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_START); + } + } + } + } + else + if( mLastCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR ) + { + // make sure we ask to save changes + + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + + // HACK: If we're quitting, and we were in customize avatar, don't + // let the mini-map go visible again. JC + if (!LLAppViewer::instance()->quitRequested()) + { + LLFloaterMap::getInstance()->popVisible(); + } + + if( gMorphView ) + { + gMorphView->setVisible( FALSE ); + } + + if (mAvatarObject.notNull()) + { + if(mCustomAnim) + { + sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_CUSTOMIZE_DONE, ANIM_REQUEST_START); + + mCustomAnim = FALSE ; + } + + } + setLookAt(LOOKAT_TARGET_CLEAR); + } + + //--------------------------------------------------------------------- + // Set up UI for mode we're entering + //--------------------------------------------------------------------- + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + // hide menus + gMenuBarView->setVisible(FALSE); + gStatusBar->setVisibleForMouselook(false); + + // clear out camera lag effect + mCameraLag.clearVec(); + + // JC - Added for always chat in third person option + gFocusMgr.setKeyboardFocus(NULL); + + LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); + + mViewsPushed = TRUE; + + gFloaterView->pushVisibleAll(FALSE, get_skip_list()); + + if( gMorphView ) + { + gMorphView->setVisible(FALSE); + } + + gConsole->setVisible( TRUE ); + + if (mAvatarObject.notNull()) + { + // Trigger mouselook-specific animations + if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) ) + { + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_RIFLE_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_START); + } + if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BOW_L) != mAvatarObject->mSignaledAnimations.end()) + { + sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_STOP); + sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_START); + } + } + if (mAvatarObject->getParent()) + { + LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); + LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot(); + if (root_object->flagCameraDecoupled()) + { + resetAxes(at_axis); + } + else + { + resetAxes(at_axis * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation()); + } + } + } + + } + else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) + { + LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); + + LLFloaterMap::getInstance()->pushVisible(FALSE); + /* + LLView *view; + for (view = gFloaterView->getFirstChild(); view; view = gFloaterView->getNextChild()) + { + view->pushVisible(FALSE); + } + */ + + if( gMorphView ) + { + gMorphView->setVisible( TRUE ); + } + + // freeze avatar + if (mAvatarObject.notNull()) + { + // + //mPauseRequest = mAvatarObject->requestPause(); + // + } + } + + if (getAvatarObject()) + { + getAvatarObject()->updateAttachmentVisibility(mCameraMode); + } + + gFloaterTools->dirty(); + + // Don't let this be called more than once if the camera + // mode hasn't changed. --JC + mLastCameraMode = mCameraMode; + +} + + +//----------------------------------------------------------------------------- +// updateCamera() +//----------------------------------------------------------------------------- +void LLAgent::updateCamera() +{ + //Ventrella - changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = LLVector3::z_axis; + //LLVector3 camera_skyward(0.f, 0.f, 1.f); + //end Ventrella + + U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + + validateFocusObject(); + + if (mAvatarObject.notNull() && + mAvatarObject->mIsSitting && + camera_mode == CAMERA_MODE_MOUSELOOK) + { + //Ventrella + //changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = mCameraUpVector * mAvatarObject->getRenderRotation(); + //end Ventrella + } + + if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) + { + changeCameraToFollow(); + } + + //Ventrella + //NOTE - this needs to be integrated into a general upVector system here within llAgent. + if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) + { + mCameraUpVector = mFollowCam.getUpVector(); + } + //end Ventrella + + if (mSitCameraEnabled) + { + if (mSitCameraReferenceObject->isDead()) + { + setSitCamera(LLUUID::null); + } + } + + // Update UI with our camera inputs + LLFloaterCamera::getInstance()->mRotate->setToggleState( + mOrbitRightKey > 0.f, // left + mOrbitUpKey > 0.f, // top + mOrbitLeftKey > 0.f, // right + mOrbitDownKey > 0.f); // bottom + + LLFloaterCamera::getInstance()->mZoom->setToggleState( + mOrbitInKey > 0.f, // top + mOrbitOutKey > 0.f); // bottom + + LLFloaterCamera::getInstance()->mTrack->setToggleState( + mPanLeftKey > 0.f, // left + mPanUpKey > 0.f, // top + mPanRightKey > 0.f, // right + mPanDownKey > 0.f); // bottom + + // Handle camera movement based on keyboard. + const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second + const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second + const F32 PAN_RATE = 5.f; // meters per second + + if( mOrbitUpKey || mOrbitDownKey ) + { + F32 input_rate = mOrbitUpKey - mOrbitDownKey; + cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); + } + + if( mOrbitLeftKey || mOrbitRightKey) + { + F32 input_rate = mOrbitLeftKey - mOrbitRightKey; + cameraOrbitAround( input_rate * ORBIT_AROUND_RATE / gFPSClamped ); + } + + if( mOrbitInKey || mOrbitOutKey ) + { + F32 input_rate = mOrbitInKey - mOrbitOutKey; + + LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); + F32 distance_to_focus = (F32)to_focus.magVec(); + // Move at distance (in meters) meters per second + cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); + } + + if( mPanInKey || mPanOutKey ) + { + F32 input_rate = mPanInKey - mPanOutKey; + cameraPanIn( input_rate * PAN_RATE / gFPSClamped ); + } + + if( mPanRightKey || mPanLeftKey ) + { + F32 input_rate = mPanRightKey - mPanLeftKey; + cameraPanLeft( input_rate * -PAN_RATE / gFPSClamped ); + } + + if( mPanUpKey || mPanDownKey ) + { + F32 input_rate = mPanUpKey - mPanDownKey; + cameraPanUp( input_rate * PAN_RATE / gFPSClamped ); + } + + // Clear camera keyboard keys. + mOrbitLeftKey = 0.f; + mOrbitRightKey = 0.f; + mOrbitUpKey = 0.f; + mOrbitDownKey = 0.f; + mOrbitInKey = 0.f; + mOrbitOutKey = 0.f; + + mPanRightKey = 0.f; + mPanLeftKey = 0.f; + mPanUpKey = 0.f; + mPanDownKey = 0.f; + mPanInKey = 0.f; + mPanOutKey = 0.f; + + // lerp camera focus offset + mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + + //Ventrella + if ( mCameraMode == CAMERA_MODE_FOLLOW ) + { + if ( mAvatarObject.notNull() ) + { + //-------------------------------------------------------------------------------- + // this is where the avatar's position and rotation are given to followCam, and + // where it is updated. All three of its attributes are updated: (1) position, + // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. + //-------------------------------------------------------------------------------- + // *TODO: use combined rotation of frameagent and sit object + LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); + + LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams(); + if (current_cam) + { + mFollowCam.copyParams(*current_cam); + mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam ); + mFollowCam.update(); + } + else + { + changeCameraToThirdPerson(TRUE); + } + } + } + // end Ventrella + + BOOL hit_limit; + LLVector3d camera_pos_global; + LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); + mCameraVirtualPositionAgent = getPosAgentFromGlobal(camera_target_global); + LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); + + // perform field of view correction + mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); + camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); + + mShowAvatar = TRUE; // can see avatar by default + + // Adjust position for animation + if (mCameraAnimating) + { + F32 time = mAnimationTimer.getElapsedTimeF32(); + + // yet another instance of critically damped motion, hooray! + // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); + + // linear interpolation + F32 fraction_of_animation = time / mAnimationDuration; + + BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; + BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; + F32 fraction_animation_to_skip; + + if (mAnimationCameraStartGlobal == camera_target_global) + { + fraction_animation_to_skip = 0.f; + } + else + { + LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; + fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); + } + F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; + F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; + + if (fraction_of_animation < animation_finish_fraction) + { + if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) + { + mShowAvatar = FALSE; + } + + // ...adjust position for animation + F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); + camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); + mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); + } + else + { + // ...animation complete + mCameraAnimating = FALSE; + + camera_pos_global = camera_target_global; + mFocusGlobal = focus_target_global; + + endAnimationUpdateUI(); + mShowAvatar = TRUE; + } + + if (getAvatarObject() && mCameraMode != CAMERA_MODE_MOUSELOOK) + { + getAvatarObject()->updateAttachmentVisibility(mCameraMode); + } + } + else + { + camera_pos_global = camera_target_global; + mFocusGlobal = focus_target_global; + mShowAvatar = TRUE; + } + + // smoothing + if (TRUE) + { + LLVector3d agent_pos = getPositionGlobal(); + LLVector3d camera_pos_agent = camera_pos_global - agent_pos; + // Sitting on what you're manipulating can cause camera jitter with smoothing. + // This turns off smoothing while editing. -MG + mCameraSmoothingStop |= (BOOL)LLToolMgr::getInstance()->inBuildMode(); + + if (cameraThirdPerson() && !mCameraSmoothingStop) + { + const F32 SMOOTHING_HALF_LIFE = 0.02f; + + F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); + + if (!mFocusObject) // we differentiate on avatar mode + { + // for avatar-relative focus, we smooth in avatar space - + // the avatar moves too jerkily w/r/t global space to smooth there. + + LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); + camera_pos_global = camera_pos_agent + agent_pos; + } + } + else + { + LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); + } + } + } + + mCameraSmoothingLastPositionGlobal = camera_pos_global; + mCameraSmoothingLastPositionAgent = camera_pos_agent; + mCameraSmoothingStop = FALSE; + } + + + mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); + +// llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl; + + F32 ui_offset = 0.f; + if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) + { + ui_offset = calcCustomizeAvatarUIOffset( camera_pos_global ); + } + + + LLVector3 focus_agent = getPosAgentFromGlobal(mFocusGlobal); + + mCameraPositionAgent = getPosAgentFromGlobal(camera_pos_global); + + // Move the camera + + //Ventrella + LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); + //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); + //end Ventrella + + //RN: translate UI offset after camera is oriented properly + LLViewerCamera::getInstance()->translate(LLViewerCamera::getInstance()->getLeftAxis() * ui_offset); + + // Change FOV + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); + + // follow camera when in customize mode + if (cameraCustomizeAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); + } + + // update the travel distance stat + // this isn't directly related to the camera + // but this seemed like the best place to do this + LLVector3d global_pos = getPositionGlobal(); + if (! mLastPositionGlobal.isExactlyZero()) + { + LLVector3d delta = global_pos - mLastPositionGlobal; + mDistanceTraveled += delta.magVec(); + } + mLastPositionGlobal = global_pos; + + if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook()) + { + LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + + LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + + LLVector3(0.1f, 0.f, 0.f) * mAvatarObject->mPelvisp->getWorldRotation(); + LLVector3 diff = mCameraPositionAgent - head_pos; + diff = diff * ~mAvatarObject->mRoot.getWorldRotation(); + + LLJoint* torso_joint = mAvatarObject->mTorsop; + LLJoint* chest_joint = mAvatarObject->mChestp; + LLVector3 torso_scale = torso_joint->getScale(); + LLVector3 chest_scale = chest_joint->getScale(); + + // shorten avatar skeleton to avoid foot interpenetration + if (!mAvatarObject->mInAir) + { + LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); + F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); + F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); + torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + + LLJoint* neck_joint = mAvatarObject->mNeckp; + LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); + scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); + chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + diff.mV[VZ] = 0.f; + } + + mAvatarObject->mPelvisp->setPosition(mAvatarObject->mPelvisp->getPosition() + diff); + + mAvatarObject->mRoot.updateWorldMatrixChildren(); + + for (LLVOAvatar::attachment_map_t::iterator iter = mAvatarObject->mAttachmentPoints.begin(); + iter != mAvatarObject->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLViewerObject *attached_object = attachment->getObject(); + if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) + { + // clear any existing "early" movements of attachment + attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); + gPipeline.updateMoveNormalAsync(attached_object->mDrawable); + attached_object->updateText(); + } + } + + torso_joint->setScale(torso_scale); + chest_joint->setScale(chest_scale); + } +} + +void LLAgent::updateFocusOffset() +{ + validateFocusObject(); + if (mFocusObject.notNull()) + { + LLVector3d obj_pos = getPosGlobalFromAgent(mFocusObject->getRenderPosition()); + mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); + } +} + +void LLAgent::validateFocusObject() +{ + if (mFocusObject.notNull() && + (mFocusObject->isDead())) + { + mFocusObjectOffset.clearVec(); + clearFocusObject(); + mCameraFOVZoomFactor = 0.f; + } +} + +//----------------------------------------------------------------------------- +// calcCustomizeAvatarUIOffset() +//----------------------------------------------------------------------------- +F32 LLAgent::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ) +{ + F32 ui_offset = 0.f; + + if( gFloaterCustomize ) + { + const LLRect& rect = gFloaterCustomize->getRect(); + + // Move the camera so that the avatar isn't covered up by this floater. + F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth())))); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); // radians + F32 offset = tan(apparent_angle); + + if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) ) + { + // Move the avatar to the right (camera to the left) + ui_offset = offset; + } + else + { + // Move the avatar to the left (camera to the right) + ui_offset = -offset; + } + } + F32 range = (F32)dist_vec(camera_pos_global, gAgent.getFocusGlobal()); + mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f)); + return mUIOffset * range; +} + +//----------------------------------------------------------------------------- +// calcFocusPositionTargetGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgent::calcFocusPositionTargetGlobal() +{ + if (mFocusObject.notNull() && mFocusObject->isDead()) + { + clearFocusObject(); + } + + // Ventrella + if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); + return mFocusTargetGlobal; + }// End Ventrella + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + LLVector3d at_axis(1.0, 0.0, 0.0); + LLQuaternion agent_rot = mFrameAgent.getQuaternion(); + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot(); + if (!root_object->flagCameraDecoupled()) + { + agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); + } + } + at_axis = at_axis * agent_rot; + mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; + return mFocusTargetGlobal; + } + else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) + { + return mFocusTargetGlobal; + } + else if (!mFocusOnAvatar) + { + if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) + { + LLDrawable* drawablep = mFocusObject->mDrawable; + + if (mTrackFocusObject && + drawablep && + drawablep->isActive()) + { + if (!mFocusObject->isAvatar()) + { + if (mFocusObject->isSelected()) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + gPipeline.updateMoveDampedAsync(drawablep); + } + } + } + } + // if not tracking object, update offset based on new object position + else + { + updateFocusOffset(); + } + LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; + mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent)); + } + return mFocusTargetGlobal; + } + else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); + return getPosGlobalFromAgent(target_pos); + } + else + { + return getPositionGlobal() + calcThirdPersonFocusOffset(); + } +} + +LLVector3d LLAgent::calcThirdPersonFocusOffset() +{ + // ...offset from avatar + LLVector3d focus_offset; + focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault")); + + LLQuaternion agent_rot = mFrameAgent.getQuaternion(); + if (!mAvatarObject.isNull() && mAvatarObject->getParent()) + { + agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); + } + + focus_offset = focus_offset * agent_rot; + return focus_offset; +} + +void LLAgent::setupSitCamera() +{ + // agent frame entering this function is in world coordinates + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = mFrameAgent.getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis * ~parent_rot); + } +} + +//----------------------------------------------------------------------------- +// getCameraPositionAgent() +//----------------------------------------------------------------------------- +const LLVector3 &LLAgent::getCameraPositionAgent() const +{ + return LLViewerCamera::getInstance()->getOrigin(); +} + +//----------------------------------------------------------------------------- +// getCameraPositionGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgent::getCameraPositionGlobal() const +{ + return getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); +} + +//----------------------------------------------------------------------------- +// calcCameraFOVZoomFactor() +//----------------------------------------------------------------------------- +F32 LLAgent::calcCameraFOVZoomFactor() +{ + LLVector3 camera_offset_dir; + camera_offset_dir.setVec(mCameraFocusOffset); + + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } + else if (mFocusObject.notNull() && !mFocusObject->isAvatar()) + { + // don't FOV zoom on mostly transparent objects + LLVector3 focus_offset = mFocusObjectOffset; + F32 obj_min_dist = 0.f; + calcCameraMinDistance(obj_min_dist); + F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); + + mFocusObjectDist = obj_min_dist - current_distance; + + F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); + return new_fov_zoom; + } + else // focusing on land or avatar + { + // keep old field of view until user changes focus explicitly + return mCameraFOVZoomFactor; + //return 0.f; + } +} + +//----------------------------------------------------------------------------- +// calcCameraPositionTargetGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) +{ + // Compute base camera position and look-at points. + F32 camera_land_height; + LLVector3d frame_center_global = mAvatarObject.isNull() ? getPositionGlobal() + : getPosGlobalFromAgent(mAvatarObject->mRoot.getWorldPosition()); + + LLVector3 upAxis = getUpAxis(); + BOOL isConstrained = FALSE; + LLVector3d head_offset; + head_offset.setVec(mThirdPersonHeadOffset); + + LLVector3d camera_position_global; + + // Ventrella + if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) + { + camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); + }// End Ventrella + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + if (mAvatarObject.isNull() || mAvatarObject->mDrawable.isNull()) + { + llwarns << "Null avatar drawable!" << llendl; + return LLVector3d::zero; + } + head_offset.clearVec(); + if (mAvatarObject->mIsSitting && mAvatarObject->getParent()) + { + mAvatarObject->updateHeadOffset(); + head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX]; + head_offset.mdV[VY] = mAvatarObject->mHeadOffset.mV[VY]; + head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ] + 0.1f; + const LLMatrix4& mat = ((LLViewerObject*) mAvatarObject->getParent())->getRenderMatrix(); + camera_position_global = getPosGlobalFromAgent + ((mAvatarObject->getPosition()+ + LLVector3(head_offset)*mAvatarObject->getRotation()) * mat); + } + else + { + head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ]; + if (mAvatarObject->mIsSitting) + { + head_offset.mdV[VZ] += 0.1; + } + camera_position_global = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());//frame_center_global; + head_offset = head_offset * mAvatarObject->getRenderRotation(); + camera_position_global = camera_position_global + head_offset; + } + } + else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) + { + LLVector3 local_camera_offset; + F32 camera_distance = 0.f; + + if (mSitCameraEnabled + && mAvatarObject.notNull() + && mAvatarObject->mIsSitting + && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); + + camera_position_global = getPosGlobalFromAgent(target_pos); + } + else + { + local_camera_offset = mCameraZoomFraction * mCameraOffsetDefault * gSavedSettings.getF32("CameraOffsetScale"); + + // are we sitting down? + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = mFrameAgent.getAtAxis() * parent_rot; + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis * ~parent_rot); + + local_camera_offset = local_camera_offset * mFrameAgent.getQuaternion() * parent_rot; + } + else + { + local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset ); + } + + if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->mIsSitting)) + { + LLVector3 plane_normal; + plane_normal.setVec(mCameraCollidePlane.mV); + + F32 offset_dot_norm = local_camera_offset * plane_normal; + if (llabs(offset_dot_norm) < 0.001f) + { + offset_dot_norm = 0.001f; + } + + camera_distance = local_camera_offset.normalize(); + + F32 pos_dot_norm = getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; + + // if agent is outside the colliding half-plane + if (pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + // check to see if camera is on the opposite side (inside) the half-plane + if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) + { + // diminish offset by factor to push it back outside the half-plane + camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; + } + } + else + { + if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; + } + } + } + else + { + camera_distance = local_camera_offset.normalize(); + } + + mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); + + if (mTargetCameraDistance != mCurrentCameraDistance) + { + F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + + mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); + } + + // Make the camera distance current + local_camera_offset *= mCurrentCameraDistance; + + // set the global camera position + LLVector3d camera_offset; + + LLVector3 av_pos = mAvatarObject.isNull() ? LLVector3::zero : mAvatarObject->getRenderPosition(); + camera_offset.setVec( local_camera_offset ); + camera_position_global = frame_center_global + head_offset + camera_offset; + + if (mAvatarObject.notNull()) + { + LLVector3d camera_lag_d; + F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); + LLVector3 target_lag; + LLVector3 vel = getVelocity(); + + // lag by appropriate amount for flying + F32 time_in_air = mAvatarObject->mTimeInAir.getElapsedTimeF32(); + if(!mCameraAnimating && mAvatarObject->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) + { + LLVector3 frame_at_axis = mFrameAgent.getAtAxis(); + frame_at_axis -= projected_vec(frame_at_axis, getReferenceUpVector()); + frame_at_axis.normalize(); + + //transition smoothly in air mode, to avoid camera pop + F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; + u = llclamp(u, 0.f, 1.f); + + lag_interp *= u; + + if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == mAvatarObject->getID()) + { + // disable camera lag when using mouse-directed steering + target_lag.clearVec(); + } + else + { + target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; + } + + mCameraLag = lerp(mCameraLag, target_lag, lag_interp); + + F32 lag_dist = mCameraLag.magVec(); + if (lag_dist > MAX_CAMERA_LAG) + { + mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; + } + + // clamp camera lag so that avatar is always in front + F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; + if (dot < -(MIN_CAMERA_LAG * u)) + { + mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; + } + } + else + { + mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); + } + + camera_lag_d.setVec(mCameraLag); + camera_position_global = camera_position_global - camera_lag_d; + } + } + } + else + { + LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); + // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value + camera_position_global = focusPosGlobal + mCameraFocusOffset; + } + + if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike()) + { + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal( + camera_position_global); + bool constrain = true; + if(regionp && regionp->canManageEstate()) + { + constrain = false; + } + if(constrain) + { + F32 max_dist = ( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) ? + APPEARANCE_MAX_ZOOM : mDrawDistance; + + LLVector3d camera_offset = camera_position_global + - gAgent.getPositionGlobal(); + F32 camera_distance = (F32)camera_offset.magVec(); + + if(camera_distance > max_dist) + { + camera_position_global = gAgent.getPositionGlobal() + + (max_dist / camera_distance) * camera_offset; + isConstrained = TRUE; + } + } + +// JC - Could constrain camera based on parcel stuff here. +// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); +// +// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) +// { +// camera_position_global = last_position_global; +// +// isConstrained = TRUE; +// } + } + + // Don't let camera go underground + F32 camera_min_off_ground = getCameraMinOffGround(); + + camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); + + if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground) + { + camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground; + isConstrained = TRUE; + } + + + if (hit_limit) + { + *hit_limit = isConstrained; + } + + return camera_position_global; +} + + +//----------------------------------------------------------------------------- +// handleScrollWheel() +//----------------------------------------------------------------------------- +void LLAgent::handleScrollWheel(S32 clicks) +{ + if ( mCameraMode == CAMERA_MODE_FOLLOW && gAgent.getFocusOnAvatar()) + { + if ( ! mFollowCam.getPositionLocked() ) // not if the followCam position is locked in place + { + mFollowCam.zoom( clicks ); + if ( mFollowCam.isZoomedToMinimumDistance() ) + { + changeCameraToMouselook(FALSE); + } + } + } + else + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); + + // Block if camera is animating + if (mCameraAnimating) + { + return; + } + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom_factor = (F32)pow(0.8, -clicks); + cameraZoomIn(zoom_factor); + } + else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + F32 current_zoom_fraction = mTargetCameraDistance / (mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); + current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); + + cameraOrbitIn(current_zoom_fraction * mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); + } + else + { + F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); + cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); + } + } +} + + +//----------------------------------------------------------------------------- +// getCameraMinOffGround() +//----------------------------------------------------------------------------- +F32 LLAgent::getCameraMinOffGround() +{ + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } + else + { + if (gSavedSettings.getBOOL("DisableCameraConstraints")) + { + return -1000.f; + } + else + { + return 0.5f; + } + } +} + + +//----------------------------------------------------------------------------- +// resetCamera() +//----------------------------------------------------------------------------- +void LLAgent::resetCamera() +{ + // Remove any pitch from the avatar + LLVector3 at = mFrameAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + // have to explicitly clear field of view zoom now + mCameraFOVZoomFactor = 0.f; + + updateCamera(); +} + +//----------------------------------------------------------------------------- +// changeCameraToMouselook() +//----------------------------------------------------------------------------- +void LLAgent::changeCameraToMouselook(BOOL animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + // visibility changes at end of animation + gViewerWindow->getWindow()->resetBusyCount(); + + // Menus should not remain open on switching to mouselook... + LLMenuGL::sMenuContainer->hideMenus(); + + // unpause avatar animation + mPauseRequest = NULL; + + LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", TRUE); + gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + if (mAvatarObject.notNull()) + { + mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE ); + mAvatarObject->stopMotion( ANIM_AGENT_BREATHE_ROT ); + } + + //gViewerWindow->stopGrab(); + LLSelectMgr::getInstance()->deselectAll(); + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + + if( mCameraMode != CAMERA_MODE_MOUSELOOK ) + { + gFocusMgr.setKeyboardFocus( NULL ); + + mLastCameraMode = mCameraMode; + mCameraMode = CAMERA_MODE_MOUSELOOK; + U32 old_flags = mControlFlags; + setControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != mControlFlags) + { + mbFlagsDirty = TRUE; + } + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + endAnimationUpdateUI(); + } + } +} + + +//----------------------------------------------------------------------------- +// changeCameraToDefault() +//----------------------------------------------------------------------------- +void LLAgent::changeCameraToDefault() +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + if (LLFollowCamMgr::getActiveFollowCamParams()) + { + changeCameraToFollow(); + } + else + { + changeCameraToThirdPerson(); + } +} + + +// Ventrella +//----------------------------------------------------------------------------- +// changeCameraToFollow() +//----------------------------------------------------------------------------- +void LLAgent::changeCameraToFollow(BOOL animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + if( mCameraMode != CAMERA_MODE_FOLLOW ) + { + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + animate = FALSE; + } + startCameraAnimation(); + + mLastCameraMode = mCameraMode; + mCameraMode = CAMERA_MODE_FOLLOW; + + // bang-in the current focus, position, and up vector of the follow cam + mFollowCam.reset( mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis ); + + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + if (mAvatarObject.notNull()) + { + mAvatarObject->mPelvisp->setPosition(LLVector3::zero); + mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); + mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + // unpause avatar animation + mPauseRequest = NULL; + + U32 old_flags = mControlFlags; + clearControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != mControlFlags) + { + mbFlagsDirty = TRUE; + } + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + endAnimationUpdateUI(); + } + } +} + +//----------------------------------------------------------------------------- +// changeCameraToThirdPerson() +//----------------------------------------------------------------------------- +void LLAgent::changeCameraToThirdPerson(BOOL animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + gViewerWindow->getWindow()->resetBusyCount(); + + mCameraZoomFraction = INITIAL_ZOOM_FRACTION; + + if (mAvatarObject.notNull()) + { + if (!mAvatarObject->mIsSitting) + { + mAvatarObject->mPelvisp->setPosition(LLVector3::zero); + } + mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); + mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + LLVector3 at_axis; + + // unpause avatar animation + mPauseRequest = NULL; + + if( mCameraMode != CAMERA_MODE_THIRD_PERSON ) + { + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + mCameraLag.clearVec(); + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + mCurrentCameraDistance = MIN_CAMERA_DISTANCE; + mTargetCameraDistance = MIN_CAMERA_DISTANCE; + animate = FALSE; + } + mLastCameraMode = mCameraMode; + mCameraMode = CAMERA_MODE_THIRD_PERSON; + U32 old_flags = mControlFlags; + clearControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != mControlFlags) + { + mbFlagsDirty = TRUE; + } + + } + + // Remove any pitch from the avatar + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis * ~obj_rot); + } + else + { + at_axis = mFrameAgent.getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis); + } + + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + endAnimationUpdateUI(); + } +} + +//----------------------------------------------------------------------------- +// changeCameraToCustomizeAvatar() +//----------------------------------------------------------------------------- +void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + // + //setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up + // + gViewerWindow->getWindow()->resetBusyCount(); + + if (gFaceEditToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + if (camera_animate) + { + // + if(gSavedSettings.getBOOL("AppearanceCameraMovement")) + // + startCameraAnimation(); + } + + // Remove any pitch from the avatar + //LLVector3 at = mFrameAgent.getAtAxis(); + //at.mV[VZ] = 0.f; + //at.normalize(); + //gAgent.resetAxes(at); + + if( mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR ) + { + mLastCameraMode = mCameraMode; + mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; + U32 old_flags = mControlFlags; + clearControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != mControlFlags) + { + mbFlagsDirty = TRUE; + } + + gFocusMgr.setKeyboardFocus( NULL ); + gFocusMgr.setMouseCapture( NULL ); + + LLVOAvatar::onCustomizeStart(); + } + + if (mAvatarObject.notNull()) + { + if(avatar_animate) + { + // Remove any pitch from the avatar + LLVector3 at = mFrameAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + + sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); + mCustomAnim = TRUE ; + mAvatarObject->startMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = mAvatarObject->findMotion(ANIM_AGENT_CUSTOMIZE); + + if (turn_motion) + { + mAnimationDuration = turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP; + + } + else + { + mAnimationDuration = gSavedSettings.getF32("ZoomTime"); + } + } + + + + gAgent.setFocusGlobal(LLVector3d::zero); + } + else + { + mCameraAnimating = FALSE; + endAnimationUpdateUI(); + } + + // + if(!gSavedSettings.getBOOL("AppearanceCameraMovement")) + { + //hmm + mCameraAnimating = FALSE; + endAnimationUpdateUI(); + } + +} + + +// +// Focus point management +// + +//----------------------------------------------------------------------------- +// startCameraAnimation() +//----------------------------------------------------------------------------- +void LLAgent::startCameraAnimation() +{ + mAnimationCameraStartGlobal = getCameraPositionGlobal(); + mAnimationFocusStartGlobal = mFocusGlobal; + mAnimationTimer.reset(); + mCameraAnimating = TRUE; + mAnimationDuration = gSavedSettings.getF32("ZoomTime"); +} + +//----------------------------------------------------------------------------- +// stopCameraAnimation() +//----------------------------------------------------------------------------- +void LLAgent::stopCameraAnimation() +{ + mCameraAnimating = FALSE; +} + +void LLAgent::clearFocusObject() +{ + if (mFocusObject.notNull()) + { + startCameraAnimation(); + + setFocusObject(NULL); + mFocusObjectOffset.clearVec(); + } +} + +void LLAgent::setFocusObject(LLViewerObject* object) +{ + mFocusObject = object; +} + +// Focus on a point, but try to keep camera position stable. +//----------------------------------------------------------------------------- +// setFocusGlobal() +//----------------------------------------------------------------------------- +void LLAgent::setFocusGlobal(const LLPickInfo& pick) +{ + LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); + + if (objectp) + { + // focus on object plus designated offset + // which may or may not be same as pick.mPosGlobal + setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); + } + else + { + // focus directly on point where user clicked + setFocusGlobal(pick.mPosGlobal, pick.mObjectID); + } +} + + +void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) +{ + setFocusObject(gObjectList.findObject(object_id)); + LLVector3d old_focus = mFocusTargetGlobal; + LLViewerObject *focus_obj = mFocusObject; + + // if focus has changed + if (old_focus != focus) + { + if (focus.isExactlyZero()) + { + if (mAvatarObject.notNull()) + { + mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = getPositionGlobal(); + } + mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; + mCameraFocusOffset = mCameraFocusOffsetTarget; + setLookAt(LOOKAT_TARGET_CLEAR); + } + else + { + mFocusTargetGlobal = focus; + if (!focus_obj) + { + mCameraFOVZoomFactor = 0.f; + } + + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; + + startCameraAnimation(); + + if (focus_obj) + { + if (focus_obj->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); + } + } + } + else // focus == mFocusTargetGlobal + { + if (focus.isExactlyZero()) + { + if (mAvatarObject.notNull()) + { + mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = getPositionGlobal(); + } + } + mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; + mCameraFocusOffset = mCameraFocusOffsetTarget; + } + + if (mFocusObject.notNull()) + { + // for attachments, make offset relative to avatar, not the attachment + if (mFocusObject->isAttachment()) + { + while (mFocusObject.notNull() // DEV-29123 - can crash with a messed-up attachment + && !mFocusObject->isAvatar()) + { + mFocusObject = (LLViewerObject*) mFocusObject->getParent(); + } + setFocusObject((LLViewerObject*)mFocusObject); + } + updateFocusOffset(); + } +} + +// Used for avatar customization +//----------------------------------------------------------------------------- +// setCameraPosAndFocusGlobal() +//----------------------------------------------------------------------------- +void LLAgent::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id) +{ + LLVector3d old_focus = mFocusTargetGlobal; + + F64 focus_delta_squared = (old_focus - focus).magVecSquared(); + const F64 ANIM_EPSILON_SQUARED = 0.0001; + if( focus_delta_squared > ANIM_EPSILON_SQUARED ) + { + startCameraAnimation(); + + if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) + { + // Compensate for the fact that the camera has already been offset to make room for LLFloaterCustomize. + mAnimationCameraStartGlobal -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * calcCustomizeAvatarUIOffset( mAnimationCameraStartGlobal )); + } + } + + //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); + setFocusObject(gObjectList.findObject(object_id)); + mFocusTargetGlobal = focus; + mCameraFocusOffsetTarget = camera_pos - focus; + mCameraFocusOffset = mCameraFocusOffsetTarget; + + if (mFocusObject) + { + if (mFocusObject->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); + } + + if( mCameraAnimating ) + { + const F64 ANIM_METERS_PER_SECOND = 10.0; + const F64 MIN_ANIM_SECONDS = 0.5; + F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); + setAnimationDuration( (F32)anim_duration ); + } + + updateFocusOffset(); +} + +//----------------------------------------------------------------------------- +// setSitCamera() +//----------------------------------------------------------------------------- +void LLAgent::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus) +{ + BOOL camera_enabled = !object_id.isNull(); + + if (camera_enabled) + { + LLViewerObject *reference_object = gObjectList.findObject(object_id); + if (reference_object) + { + //convert to root object relative? + mSitCameraPos = camera_pos; + mSitCameraFocus = camera_focus; + mSitCameraReferenceObject = reference_object; + mSitCameraEnabled = TRUE; + } + } + else + { + mSitCameraPos.clearVec(); + mSitCameraFocus.clearVec(); + mSitCameraReferenceObject = NULL; + mSitCameraEnabled = FALSE; + } +} + +//----------------------------------------------------------------------------- +// setFocusOnAvatar() +//----------------------------------------------------------------------------- +void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) +{ + if (focus_on_avatar != mFocusOnAvatar) + { + if (animate) + { + startCameraAnimation(); + } + else + { + stopCameraAnimation(); + } + } + + //RN: when focused on the avatar, we're not "looking" at it + // looking implies intent while focusing on avatar means + // you're just walking around with a camera on you...eesh. + if (!mFocusOnAvatar && focus_on_avatar) + { + setFocusGlobal(LLVector3d::zero); + mCameraFOVZoomFactor = 0.f; + if (mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + LLVector3 at_axis; + if (mAvatarObject.notNull() && mAvatarObject->getParent()) + { + LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis * ~obj_rot); + } + else + { + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + resetAxes(at_axis); + } + } + } + // unlocking camera from avatar + else if (mFocusOnAvatar && !focus_on_avatar) + { + // keep camera focus point consistent, even though it is now unlocked + setFocusGlobal(getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); + } + + mFocusOnAvatar = focus_on_avatar; +} + +//----------------------------------------------------------------------------- +// heardChat() +//----------------------------------------------------------------------------- +void LLAgent::heardChat(const LLUUID& id) +{ + // log text and voice chat to speaker mgr + // for keeping track of active speakers, etc. + LLLocalSpeakerMgr::getInstance()->speakerChatted(id); + + // don't respond to your own voice + if (id == getID()) return; + + if (ll_rand(2) == 0) + { + LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); + setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); + } + + mLastChatterID = id; + mChatTimer.reset(); +} + +//----------------------------------------------------------------------------- +// lookAtLastChat() +//----------------------------------------------------------------------------- +void LLAgent::lookAtLastChat() +{ + // Block if camera is animating or not in normal third person camera mode + if (mCameraAnimating || !cameraThirdPerson()) + { + return; + } + + LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); + if (chatter) + { + LLVector3 delta_pos; + if (chatter->isAvatar()) + { + LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; + if (mAvatarObject.notNull() && chatter_av->mHeadp) + { + delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); + } + else + { + delta_pos = chatter->getPositionAgent() - getPositionAgent(); + } + delta_pos.normalize(); + + setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + if (chatter_av->mHeadp) + { + setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), mLastChatterID); + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + } + else + { + setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + } + setFocusOnAvatar(FALSE, TRUE); + } + else + { + delta_pos = chatter->getRenderPosition() - getPositionAgent(); + delta_pos.normalize(); + + setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + setFocusOnAvatar(FALSE, TRUE); + } + } +} + +void LLAgent::lookAtObject(LLUUID object_id, ECameraPosition camera_pos) +{ + // Block if camera is animating or not in normal third person camera mode + if (mCameraAnimating || !cameraThirdPerson()) + { + return; + } + + LLViewerObject *chatter = gObjectList.findObject(object_id); + if (chatter) + { + LLVector3 delta_pos; + if (chatter->isAvatar()) + { + LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; + if (!mAvatarObject.isNull() && chatter_av->mHeadp) + { + delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); + } + else + { + delta_pos = chatter->getPositionAgent() - getPositionAgent(); + } + delta_pos.normVec(); + + setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normVec(); + LLVector3 up = left % delta_pos; + up.normVec(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + F32 radius = chatter_av->getVObjRadius(); + LLVector3d view_dist(radius, radius, 0.0f); + + if (chatter_av->mHeadp) + { + setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), object_id); + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + break; + case CAMERA_POSITION_OBJECT: + mCameraFocusOffsetTarget = view_dist; + break; + } + } + else + { + setFocusGlobal(chatter->getPositionGlobal(), object_id); + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + break; + case CAMERA_POSITION_OBJECT: + mCameraFocusOffsetTarget = view_dist; + break; + } + } + setFocusOnAvatar(FALSE, TRUE); + } + else + { + delta_pos = chatter->getRenderPosition() - getPositionAgent(); + delta_pos.normVec(); + + setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normVec(); + LLVector3 up = left % delta_pos; + up.normVec(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + setFocusGlobal(chatter->getPositionGlobal(), object_id); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + break; + case CAMERA_POSITION_OBJECT: + F32 radius = chatter->getVObjRadius(); + LLVector3d view_dist(radius, radius, 0.0f); + mCameraFocusOffsetTarget = view_dist; + break; + } + + setFocusOnAvatar(FALSE, TRUE); + } + } +} + +const F32 SIT_POINT_EXTENTS = 0.2f; + +void LLAgent::setStartPosition( U32 location_id ) +{ + LLViewerObject *object; + + if ( !(gAgentID == LLUUID::null) ) + { + // we've got an ID for an agent viewerobject + object = gObjectList.findObject(gAgentID); + if (object) + { + // we've got the viewer object + // Sometimes the agent can be velocity interpolated off of + // this simulator. Clamp it to the region the agent is + // in, a little bit in on each side. + const F32 INSET = 0.5f; //meters + const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters(); + + LLVector3 agent_pos = getPositionAgent(); + LLVector3 agent_look_at = mFrameAgent.getAtAxis(); + + if (mAvatarObject.notNull()) + { + // the z height is at the agent's feet + agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ]; + } + + agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET ); + agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET ); + + // Don't let them go below ground, or too high. + agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ], + mRegionp->getLandHeightRegion( agent_pos ), + LLWorld::getInstance()->getRegionMaxHeight() ); + // Send the CapReq + + LLSD body; + + std::string url = gAgent.getRegion()->getCapability("HomeLocation"); + std::ostringstream strBuffer; + if( url.empty() ) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetStartLocationRequest); + msg->nextBlockFast( _PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msg->nextBlockFast( _PREHASH_StartLocationData); + // corrected by sim + msg->addStringFast(_PREHASH_SimName, ""); + msg->addU32Fast(_PREHASH_LocationID, location_id); + msg->addVector3Fast(_PREHASH_LocationPos, agent_pos); + msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis()); + + // Reliable only helps when setting home location. Last + // location is sent on quit, and we don't have time to ack + // the packets. + msg->sendReliable(mRegionp->getHost()); + + const U32 HOME_INDEX = 1; + if( HOME_INDEX == location_id ) + { + setHomePosRegion( mRegionp->getHandle(), getPositionAgent() ); + } + } + else + { + strBuffer << location_id; + body["HomeLocation"]["LocationId"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_pos.mV[VX]; + body["HomeLocation"]["LocationPos"]["X"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_pos.mV[VY]; + body["HomeLocation"]["LocationPos"]["Y"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_pos.mV[VZ]; + body["HomeLocation"]["LocationPos"]["Z"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_look_at.mV[VX]; + body["HomeLocation"]["LocationLookAt"]["X"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_look_at.mV[VY]; + body["HomeLocation"]["LocationLookAt"]["Y"] = strBuffer.str(); + + strBuffer.str(""); + strBuffer << agent_look_at.mV[VZ]; + body["HomeLocation"]["LocationLookAt"]["Z"] = strBuffer.str(); + + LLHTTPClient::post( url, body, new LLHomeLocationResponder() ); + } + } + else + { + llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl; + } + } +} + +void LLAgent::requestStopMotion( LLMotion* motion ) +{ + // Notify all avatars that a motion has stopped. + // This is needed to clear the animation state bits + LLUUID anim_state = motion->getID(); + onAnimStop(motion->getID()); + + // if motion is not looping, it could have stopped by running out of time + // so we need to tell the server this +// llinfos << "Sending stop for motion " << motion->getName() << llendl; + sendAnimationRequest( anim_state, ANIM_REQUEST_STOP ); +} + +void LLAgent::onAnimStop(const LLUUID& id) +{ + // handle automatic state transitions (based on completion of animation playback) + if(id == ANIM_AGENT_STAND + // + // I really do not like doing this + || id == ANIM_AGENT_STAND_1 + || id == ANIM_AGENT_STAND_2 + || id == ANIM_AGENT_STAND_3 + || id == ANIM_AGENT_STAND_4) + // + { + // + if(LLAO::isEnabled()) + LLAO::mTimer->pause();//Timer only pauses if its not paused, check is inside function. + // + stopFidget(); + } + else if (id == ANIM_AGENT_AWAY) + { + clearAFK(); + } + else if (id == ANIM_AGENT_STANDUP) + { + // send stand up command + setControlFlags(AGENT_CONTROL_FINISH_ANIM); + + // now trigger dusting self off animation + if (mAvatarObject.notNull() && !mAvatarObject->mBelowWater && rand() % 3 == 0) + sendAnimationRequest( ANIM_AGENT_BRUSH, ANIM_REQUEST_START ); + } + else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND) + { + setControlFlags(AGENT_CONTROL_FINISH_ANIM); + } +} + +BOOL LLAgent::isGodlike() const +{ + return mAgentAccess.isGodlike(); +} + +U8 LLAgent::getGodLevel() const +{ + return mAgentAccess.getGodLevel(); +} + +bool LLAgent::wantsPGOnly() const +{ + return mAgentAccess.wantsPGOnly(); +} + +bool LLAgent::canAccessMature() const +{ + return mAgentAccess.canAccessMature(); +} + +bool LLAgent::canAccessAdult() const +{ + return mAgentAccess.canAccessAdult(); +} + +bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const +{ + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle( region_handle ); + if( regionp ) + { + switch( regionp->getSimAccess() ) + { + case SIM_ACCESS_MATURE: + if( !canAccessMature() ) + return false; + break; + case SIM_ACCESS_ADULT: + if( !canAccessAdult() ) + return false; + break; + default: + // Oh, go on and hear the silly noises. + break; + } + } + + return true; +} + +bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const +{ + U64 region_handle = to_region_handle_global( pos_global.mdV[0], pos_global.mdV[1] ); + return canAccessMaturityInRegion( region_handle ); +} + +bool LLAgent::prefersPG() const +{ + return mAgentAccess.prefersPG(); +} + +bool LLAgent::prefersMature() const +{ + return mAgentAccess.prefersMature(); +} + +bool LLAgent::prefersAdult() const +{ + return mAgentAccess.prefersAdult(); +} + +bool LLAgent::isTeen() const +{ + return mAgentAccess.isTeen(); +} + +bool LLAgent::isMature() const +{ + return mAgentAccess.isMature(); +} + +bool LLAgent::isAdult() const +{ + return mAgentAccess.isAdult(); +} + +void LLAgent::setTeen(bool teen) +{ + mAgentAccess.setTeen(teen); +} + +//static +int LLAgent::convertTextToMaturity(char text) +{ + return LLAgentAccess::convertTextToMaturity(text); +} + +bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) +{ + // Update agent access preference on the server + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + if (!url.empty()) + { + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + if (preferredMaturity == SIM_ACCESS_PG) + { + access_prefs["max"] = "PG"; + } + else if (preferredMaturity == SIM_ACCESS_MATURE) + { + access_prefs["max"] = "M"; + } + if (preferredMaturity == SIM_ACCESS_ADULT) + { + access_prefs["max"] = "A"; + } + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " + << url << llendl; + LLHTTPClient::post(url, body, new LLHTTPClient::Responder()); // Ignore response + return true; + } + return false; +} + +BOOL LLAgent::getAdminOverride() const +{ + return mAgentAccess.getAdminOverride(); +} + +void LLAgent::setMaturity(char text) +{ + mAgentAccess.setMaturity(text); +} + +void LLAgent::setAdminOverride(BOOL b) +{ + mAgentAccess.setAdminOverride(b); +} + +void LLAgent::setGodLevel(U8 god_level) +{ + mAgentAccess.setGodLevel(god_level); +} + +void LLAgent::setAOTransition() +{ + mAgentAccess.setTransition(); +} + +const LLAgentAccess& LLAgent::getAgentAccess() +{ + return mAgentAccess; +} + + +void LLAgent::buildFullname(std::string& name) const +{ + if (mAvatarObject.notNull()) + { + name = mAvatarObject->getFullname(); + } +} + +void LLAgent::buildFullnameAndTitle(std::string& name) const +{ + if (isGroupMember()) + { + name = mGroupTitle; + name += ' '; + } + else + { + name.erase(0, name.length()); + } + + if (mAvatarObject.notNull()) + { + name += mAvatarObject->getFullname(); + } +} + +BOOL LLAgent::isInGroup(const LLUUID& group_id) const +{ + if (isGodlike()) + return true; + + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + return TRUE; + } + } + return FALSE; +} + +// This implementation should mirror LLAgentInfo::hasPowerInGroup +BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const +{ + if (isGodlike()) + return true; + + // GP_NO_POWERS can also mean no power is enough to grant an ability. + if (GP_NO_POWERS == power) return FALSE; + + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + return (BOOL)((mGroups.get(i).mPowers & power) > 0); + } + } + return FALSE; +} + +BOOL LLAgent::hasPowerInActiveGroup(U64 power) const +{ + return (mGroupID.notNull() && (hasPowerInGroup(mGroupID, power))); +} + +U64 LLAgent::getPowerInGroup(const LLUUID& group_id) const +{ + if (isGodlike()) + return GP_ALL_POWERS; + + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + return (mGroups.get(i).mPowers); + } + } + + return GP_NO_POWERS; +} + +BOOL LLAgent::getGroupData(const LLUUID& group_id, LLGroupData& data) const +{ + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + data = mGroups.get(i); + return TRUE; + } + } + return FALSE; +} + +S32 LLAgent::getGroupContribution(const LLUUID& group_id) const +{ + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + S32 contribution = mGroups.get(i).mContribution; + return contribution; + } + } + return 0; +} + +BOOL LLAgent::setGroupContribution(const LLUUID& group_id, S32 contribution) +{ + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + mGroups.get(i).mContribution = contribution; + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("SetGroupContribution"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + msg->nextBlock("Data"); + msg->addUUID("GroupID", group_id); + msg->addS32("Contribution", contribution); + sendReliableMessage(); + return TRUE; + } + } + return FALSE; +} + +BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile) +{ + S32 count = mGroups.count(); + for(S32 i = 0; i < count; ++i) + { + if(mGroups.get(i).mID == group_id) + { + mGroups.get(i).mAcceptNotices = accept_notices; + mGroups.get(i).mListInProfile = list_in_profile; + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("SetGroupAcceptNotices"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + msg->nextBlock("Data"); + msg->addUUID("GroupID", group_id); + msg->addBOOL("AcceptNotices", accept_notices); + msg->nextBlock("NewData"); + msg->addBOOL("ListInProfile", list_in_profile); + sendReliableMessage(); + return TRUE; + } + } + return FALSE; +} + +// utility to build a location string +void LLAgent::buildLocationString(std::string& str) +{ + const LLVector3& agent_pos_region = getPositionAgent(); + S32 pos_x = S32(agent_pos_region.mV[VX]); + S32 pos_y = S32(agent_pos_region.mV[VY]); + S32 pos_z = S32(agent_pos_region.mV[VZ]); + + // Round the numbers based on the velocity + LLVector3 agent_velocity = getVelocity(); + F32 velocity_mag_sq = agent_velocity.magVecSquared(); + + const F32 FLY_CUTOFF = 6.f; // meters/sec + const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; + const F32 WALK_CUTOFF = 1.5f; // meters/sec + const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; + + if (velocity_mag_sq > FLY_CUTOFF_SQ) + { + pos_x -= pos_x % 4; + pos_y -= pos_y % 4; + } + else if (velocity_mag_sq > WALK_CUTOFF_SQ) + { + pos_x -= pos_x % 2; + pos_y -= pos_y % 2; + } + + // create a defult name and description for the landmark + std::string buffer; + if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() ) + { + // the parcel doesn't have a name + buffer = llformat("%.32s (%d, %d, %d)", + getRegion()->getName().c_str(), + pos_x, pos_y, pos_z); + } + else + { + // the parcel has a name, so include it in the landmark name + buffer = llformat("%.32s, %.32s (%d, %d, %d)", + LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(), + getRegion()->getName().c_str(), + pos_x, pos_y, pos_z); + } + str = buffer; +} + +LLQuaternion LLAgent::getHeadRotation() +{ + if (mAvatarObject.isNull() || !mAvatarObject->mPelvisp || !mAvatarObject->mHeadp) + { + return LLQuaternion::DEFAULT; + } + + if (!gAgent.cameraMouselook()) + { + return mAvatarObject->getRotation(); + } + + // We must be in mouselook + LLVector3 look_dir( LLViewerCamera::getInstance()->getAtAxis() ); + LLVector3 up = look_dir % mFrameAgent.getLeftAxis(); + LLVector3 left = up % look_dir; + + LLQuaternion rot(look_dir, left, up); + if (mAvatarObject->getParent()) + { + rot = rot * ~mAvatarObject->getParent()->getRotation(); + } + + return rot; +} + +void LLAgent::sendAnimationRequests(LLDynamicArray &anim_ids, EAnimRequest request) +{ + if (gAgentID.isNull()) + { + return; + } + + S32 num_valid_anims = 0; + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_AgentAnimation); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + + for (S32 i = 0; i < anim_ids.count(); i++) + { + if (anim_ids[i].isNull()) + { + continue; + } + msg->nextBlockFast(_PREHASH_AnimationList); + msg->addUUIDFast(_PREHASH_AnimID, (anim_ids[i]) ); + msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); + num_valid_anims++; + } + + msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); + msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); + if (num_valid_anims) + { + sendReliableMessage(); + } +} + +void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request) +{ + if (gAgentID.isNull() || anim_id.isNull() || !mRegionp) + { + return; + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_AgentAnimation); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + + msg->nextBlockFast(_PREHASH_AnimationList); + msg->addUUIDFast(_PREHASH_AnimID, (anim_id) ); + msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE); + + msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); + msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); + sendReliableMessage(); +} + +void LLAgent::sendWalkRun(bool running) +{ + LLMessageSystem* msgsys = gMessageSystem; + if (msgsys) + { + msgsys->newMessageFast(_PREHASH_SetAlwaysRun); + msgsys->nextBlockFast(_PREHASH_AgentData); + msgsys->addUUIDFast(_PREHASH_AgentID, getID()); + msgsys->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(running) ); + sendReliableMessage(); + } +} + +void LLAgent::friendsChanged() +{ + LLCollectProxyBuddies collector; + LLAvatarTracker::instance().applyFunctor(collector); + mProxyForAgents = collector.mProxy; +} + +BOOL LLAgent::isGrantedProxy(const LLPermissions& perm) +{ + return (mProxyForAgents.count(perm.getOwner()) > 0); +} + +BOOL LLAgent::allowOperation(PermissionBit op, + const LLPermissions& perm, + U64 group_proxy_power, + U8 god_minimum) +{ + // Check god level. + if (getGodLevel() >= god_minimum) return TRUE; + + if (!perm.isOwned()) return FALSE; + + // A group member with group_proxy_power can act as owner. + BOOL is_group_owned; + LLUUID owner_id; + perm.getOwnership(owner_id, is_group_owned); + LLUUID group_id(perm.getGroup()); + LLUUID agent_proxy(getID()); + + if (is_group_owned) + { + if (hasPowerInGroup(group_id, group_proxy_power)) + { + // Let the member assume the group's id for permission requests. + agent_proxy = owner_id; + } + } + else + { + // Check for granted mod permissions. + if ((PERM_OWNER != op) && isGrantedProxy(perm)) + { + agent_proxy = owner_id; + } + } + + // This is the group id to use for permission requests. + // Only group members may use this field. + LLUUID group_proxy = LLUUID::null; + if (group_id.notNull() && isInGroup(group_id)) + { + group_proxy = group_id; + } + + // We now have max ownership information. + if (PERM_OWNER == op) + { + // This this was just a check for ownership, we can now return the answer. + return (agent_proxy == owner_id); + } + + return perm.allowOperationBy(op, agent_proxy, group_proxy); +} + + +void LLAgent::getName(std::string& name) +{ + name.clear(); + + if (mAvatarObject.notNull()) + { + LLNameValue *first_nv = mAvatarObject->getNVPair("FirstName"); + LLNameValue *last_nv = mAvatarObject->getNVPair("LastName"); + if (first_nv && last_nv) + { + name = first_nv->printData() + " " + last_nv->printData(); + } + else + { + llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl; + } + } + else + { + name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName"); + } +} + +const LLColor4 &LLAgent::getEffectColor() +{ + return mEffectColor; +} + +void LLAgent::setEffectColor(const LLColor4 &color) +{ + mEffectColor = color; +} + +void LLAgent::initOriginGlobal(const LLVector3d &origin_global) +{ + mAgentOriginGlobal = origin_global; +} + +void update_group_floaters(const LLUUID& group_id) +{ + LLFloaterGroupInfo::refreshGroup(group_id); + + // update avatar info + LLFloaterAvatarInfo* fa = LLFloaterAvatarInfo::getInstance(gAgent.getID()); + if(fa) + { + fa->resetGroupList(); + } + + if (gIMMgr) + { + // update the talk view + gIMMgr->refresh(); + } + + gAgent.fireEvent(new LLEvent(&gAgent, "new group"), ""); +} + +// static +void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **) +{ + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); + + if (agent_id != gAgentID) + { + llwarns << "processAgentDropGroup for agent other than me" << llendl; + return; + } + + LLUUID group_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id ); + + // Remove the group if it already exists remove it and add the new data to pick up changes. + LLGroupData gd; + gd.mID = group_id; + S32 index = gAgent.mGroups.find(gd); + if (index != -1) + { + gAgent.mGroups.remove(index); + if (gAgent.getGroupID() == group_id) + { + gAgent.mGroupID.setNull(); + gAgent.mGroupPowers = 0; + gAgent.mGroupName.clear(); + gAgent.mGroupTitle.clear(); + } + + // refresh all group information + gAgent.sendAgentDataUpdateRequest(); + + LLGroupMgr::getInstance()->clearGroupData(group_id); + // close the floater for this group, if any. + LLFloaterGroupInfo::closeGroup(group_id); + // refresh the group panel of the search window, if necessary. + LLFloaterDirectory::refreshGroup(group_id); + } + else + { + llwarns << "processAgentDropGroup, agent is not part of group " << group_id << llendl; + } +} + +class LLAgentDropGroupViewerNode : public LLHTTPNode +{ + virtual void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + + if ( + !input.isMap() || + !input.has("body") ) + { + //what to do with badly formed message? + response->status(400); + response->result(LLSD("Invalid message parameters")); + } + + LLSD body = input["body"]; + if ( body.has("body") ) + { + //stupid message system doubles up the "body"s + body = body["body"]; + } + + if ( + body.has("AgentData") && + body["AgentData"].isArray() && + body["AgentData"][0].isMap() ) + { + llinfos << "VALID DROP GROUP" << llendl; + + //there is only one set of data in the AgentData block + LLSD agent_data = body["AgentData"][0]; + LLUUID agent_id; + LLUUID group_id; + + agent_id = agent_data["AgentID"].asUUID(); + group_id = agent_data["GroupID"].asUUID(); + + if (agent_id != gAgentID) + { + llwarns + << "AgentDropGroup for agent other than me" << llendl; + + response->notFound(); + return; + } + + // Remove the group if it already exists remove it + // and add the new data to pick up changes. + LLGroupData gd; + gd.mID = group_id; + S32 index = gAgent.mGroups.find(gd); + if (index != -1) + { + gAgent.mGroups.remove(index); + if (gAgent.getGroupID() == group_id) + { + gAgent.mGroupID.setNull(); + gAgent.mGroupPowers = 0; + gAgent.mGroupName.clear(); + gAgent.mGroupTitle.clear(); + } + + // refresh all group information + gAgent.sendAgentDataUpdateRequest(); + + LLGroupMgr::getInstance()->clearGroupData(group_id); + // close the floater for this group, if any. + LLFloaterGroupInfo::closeGroup(group_id); + // refresh the group panel of the search window, + //if necessary. + LLFloaterDirectory::refreshGroup(group_id); + } + else + { + llwarns + << "AgentDropGroup, agent is not part of group " + << group_id << llendl; + } + + response->result(LLSD()); + } + else + { + //what to do with badly formed message? + response->status(400); + response->result(LLSD("Invalid message parameters")); + } + } +}; + +LLHTTPRegistration + gHTTPRegistrationAgentDropGroupViewerNode( + "/message/AgentDropGroup"); + +// static +void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) +{ + LLUUID agent_id; + + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); + + if (agent_id != gAgentID) + { + llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl; + return; + } + + S32 count = msg->getNumberOfBlocksFast(_PREHASH_GroupData); + LLGroupData group; + S32 index = -1; + bool need_floater_update = false; + for(S32 i = 0; i < count; ++i) + { + msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group.mID, i); + msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupInsigniaID, group.mInsigniaID, i); + msg->getU64(_PREHASH_GroupData, "GroupPowers", group.mPowers, i); + msg->getBOOL(_PREHASH_GroupData, "AcceptNotices", group.mAcceptNotices, i); + msg->getS32(_PREHASH_GroupData, "Contribution", group.mContribution, i); + msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group.mName, i); + + if(group.mID.notNull()) + { + need_floater_update = true; + // Remove the group if it already exists remove it and add the new data to pick up changes. + index = gAgent.mGroups.find(group); + if (index != -1) + { + gAgent.mGroups.remove(index); + } + gAgent.mGroups.put(group); + } + if (need_floater_update) + { + update_group_floaters(group.mID); + } + } + +} + +class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode +{ + virtual void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLSD body = input["body"]; + if(body.has("body")) + body = body["body"]; + LLUUID agent_id = body["AgentData"][0]["AgentID"].asUUID(); + + if (agent_id != gAgentID) + { + llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl; + return; + } + + LLSD group_data = body["GroupData"]; + + LLSD::array_iterator iter_group = + group_data.beginArray(); + LLSD::array_iterator end_group = + group_data.endArray(); + int group_index = 0; + for(; iter_group != end_group; ++iter_group) + { + + LLGroupData group; + S32 index = -1; + bool need_floater_update = false; + + group.mID = (*iter_group)["GroupID"].asUUID(); + group.mPowers = ll_U64_from_sd((*iter_group)["GroupPowers"]); + group.mAcceptNotices = (*iter_group)["AcceptNotices"].asBoolean(); + group.mListInProfile = body["NewGroupData"][group_index]["ListInProfile"].asBoolean(); + group.mInsigniaID = (*iter_group)["GroupInsigniaID"].asUUID(); + group.mName = (*iter_group)["GroupName"].asString(); + group.mContribution = (*iter_group)["Contribution"].asInteger(); + + group_index++; + + if(group.mID.notNull()) + { + need_floater_update = true; + // Remove the group if it already exists remove it and add the new data to pick up changes. + index = gAgent.mGroups.find(group); + if (index != -1) + { + gAgent.mGroups.remove(index); + } + gAgent.mGroups.put(group); + } + if (need_floater_update) + { + update_group_floaters(group.mID); + } + } + } +}; + +LLHTTPRegistration + gHTTPRegistrationAgentGroupDataUpdateViewerNode ("/message/AgentGroupDataUpdate"); + +// static +void LLAgent::processAgentDataUpdate(LLMessageSystem *msg, void **) +{ + LLUUID agent_id; + + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); + + if (agent_id != gAgentID) + { + llwarns << "processAgentDataUpdate for agent other than me" << llendl; + return; + } + + msg->getStringFast(_PREHASH_AgentData, _PREHASH_GroupTitle, gAgent.mGroupTitle); + LLUUID active_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_ActiveGroupID, active_id); + + + if(active_id.notNull()) + { + gAgent.mGroupID = active_id; + msg->getU64(_PREHASH_AgentData, "GroupPowers", gAgent.mGroupPowers); + msg->getString(_PREHASH_AgentData, _PREHASH_GroupName, gAgent.mGroupName); + } + else + { + gAgent.mGroupID.setNull(); + gAgent.mGroupPowers = 0; + gAgent.mGroupName.clear(); + } + + update_group_floaters(active_id); +} + +// static +void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **) +{ + S32 block_count = msg->getNumberOfBlocks("Data"); + for (S32 block_index = 0; block_index < block_count; block_index++) + { + BOOL take_controls; + U32 controls; + BOOL passon; + U32 i; + msg->getBOOL("Data", "TakeControls", take_controls, block_index); + if (take_controls) + { + // take controls + msg->getU32("Data", "Controls", controls, block_index ); + msg->getBOOL("Data", "PassToAgent", passon, block_index ); + U32 total_count = 0; + for (i = 0; i < TOTAL_CONTROLS; i++) + { + if (controls & ( 1 << i)) + { + if (passon) + { + gAgent.mControlsTakenPassedOnCount[i]++; + } + else + { + gAgent.mControlsTakenCount[i]++; + } + total_count++; + } + } + + // Any control taken? If so, might be first time. + if (total_count > 0) + { + LLFirstUse::useOverrideKeys(); + } + } + else + { + // release controls + msg->getU32("Data", "Controls", controls, block_index ); + msg->getBOOL("Data", "PassToAgent", passon, block_index ); + for (i = 0; i < TOTAL_CONTROLS; i++) + { + if (controls & ( 1 << i)) + { + if (passon) + { + gAgent.mControlsTakenPassedOnCount[i]--; + if (gAgent.mControlsTakenPassedOnCount[i] < 0) + { + gAgent.mControlsTakenPassedOnCount[i] = 0; + } + } + else + { + gAgent.mControlsTakenCount[i]--; + if (gAgent.mControlsTakenCount[i] < 0) + { + gAgent.mControlsTakenCount[i] = 0; + } + } + } + } + } + } +} + +/* +// static +void LLAgent::processControlTake(LLMessageSystem *msg, void **) +{ + U32 controls; + msg->getU32("Data", "Controls", controls ); + U32 passon; + msg->getBOOL("Data", "PassToAgent", passon ); + + S32 i; + S32 total_count = 0; + for (i = 0; i < TOTAL_CONTROLS; i++) + { + if (controls & ( 1 << i)) + { + if (passon) + { + gAgent.mControlsTakenPassedOnCount[i]++; + } + else + { + gAgent.mControlsTakenCount[i]++; + } + total_count++; + } + } + + // Any control taken? If so, might be first time. + if (total_count > 0) + { + LLFirstUse::useOverrideKeys(); + } +} + +// static +void LLAgent::processControlRelease(LLMessageSystem *msg, void **) +{ + U32 controls; + msg->getU32("Data", "Controls", controls ); + U32 passon; + msg->getBOOL("Data", "PassToAgent", passon ); + + S32 i; + for (i = 0; i < TOTAL_CONTROLS; i++) + { + if (controls & ( 1 << i)) + { + if (passon) + { + gAgent.mControlsTakenPassedOnCount[i]--; + if (gAgent.mControlsTakenPassedOnCount[i] < 0) + { + gAgent.mControlsTakenPassedOnCount[i] = 0; + } + } + else + { + gAgent.mControlsTakenCount[i]--; + if (gAgent.mControlsTakenCount[i] < 0) + { + gAgent.mControlsTakenCount[i] = 0; + } + } + } + } +} +*/ + +//static +void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data) +{ + gAgent.mNumPendingQueries--; + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (!avatarp || avatarp->isDead()) + { + llwarns << "No avatar for user in cached texture update!" << llendl; + return; + } + + if (gAgent.cameraCustomizeAvatar()) + { + // ignore baked textures when in customize mode + return; + } + + S32 query_id; + mesgsys->getS32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, query_id); + + S32 num_texture_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_WearableData); + + + S32 num_results = 0; + for (S32 texture_block = 0; texture_block < num_texture_blocks; texture_block++) + { + LLUUID texture_id; + U8 texture_index; + + mesgsys->getUUIDFast(_PREHASH_WearableData, _PREHASH_TextureID, texture_id, texture_block); + mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block); + + if (texture_id.notNull() + && (S32)texture_index < BAKED_NUM_INDICES + && gAgent.mActiveCacheQueries[ texture_index ] == query_id) + { + //llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl; + avatarp->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id); + //avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id ); + gAgent.mActiveCacheQueries[ texture_index ] = 0; + num_results++; + } + } + + llinfos << "Received cached texture response for " << num_results << " textures." << llendl; + + avatarp->updateMeshTextures(); + + if (gAgent.mNumPendingQueries == 0) + { + // RN: not sure why composites are disabled at this point + avatarp->setCompositeUpdatesEnabled(TRUE); + gAgent.sendAgentSetAppearance(); + } +} + +BOOL LLAgent::anyControlGrabbed() const +{ + U32 i; + for (i = 0; i < TOTAL_CONTROLS; i++) + { + if (gAgent.mControlsTakenCount[i] > 0) + return TRUE; + if (gAgent.mControlsTakenPassedOnCount[i] > 0) + return TRUE; + } + return FALSE; +} + +BOOL LLAgent::isControlGrabbed(S32 control_index) const +{ + return mControlsTakenCount[control_index] > 0; +} + +void LLAgent::forceReleaseControls() +{ + gMessageSystem->newMessage("ForceScriptControlRelease"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", getID()); + gMessageSystem->addUUID("SessionID", getSessionID()); + sendReliableMessage(); +} + +void LLAgent::setHomePosRegion( const U64& region_handle, const LLVector3& pos_region) +{ + mHaveHomePosition = TRUE; + mHomeRegionHandle = region_handle; + mHomePosRegion = pos_region; +} + +BOOL LLAgent::getHomePosGlobal( LLVector3d* pos_global ) +{ + if(!mHaveHomePosition) + { + return FALSE; + } + F32 x = 0; + F32 y = 0; + from_region_handle( mHomeRegionHandle, &x, &y); + pos_global->setVec( x + mHomePosRegion.mV[VX], y + mHomePosRegion.mV[VY], mHomePosRegion.mV[VZ] ); + return TRUE; +} + +void LLAgent::clearVisualParams(void *data) +{ + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + avatarp->clearVisualParamWeights(); + avatarp->updateVisualParams(); + } +} + +//--------------------------------------------------------------------------- +// Teleport +//--------------------------------------------------------------------------- + +// teleportCore() - stuff to do on any teleport +// protected +bool LLAgent::teleportCore(bool is_local) +{ + if(TELEPORT_NONE != mTeleportState) + { + llwarns << "Attempt to teleport when already teleporting." << llendl; + // + //return false; + teleportCancel(); + // + } + +#if 0 + // This should not exist. It has been added, removed, added, and now removed again. + // This change needs to come from the simulator. Otherwise, the agent ends up out of + // sync with other viewers. Discuss in DEV-14145/VWR-6744 before reenabling. + + // Stop all animation before actual teleporting + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + for ( LLVOAvatar::AnimIterator anim_it= avatarp->mPlayingAnimations.begin(); + anim_it != avatarp->mPlayingAnimations.end(); + ++anim_it) + { + avatarp->stopMotion(anim_it->first); + } + avatarp->processAnimationStateChanges(); + } +#endif + + // Don't call LLFirstUse::useTeleport because we don't know + // yet if the teleport will succeed. Look in + // process_teleport_location_reply + + // close the map and find panels so we can see our destination + LLFloaterWorldMap::hide(NULL); + LLFloaterDirectory::hide(NULL); + + // hide land floater too - it'll be out of date + LLFloaterLand::hideInstance(); + + LLViewerParcelMgr::getInstance()->deselectLand(); + LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL); + + // Close all pie menus, deselect land, etc. + // Don't change the camera until we know teleport succeeded. JC + // + if(gAgent.getFocusOnAvatar()) + // + resetView(FALSE); + + // local logic + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TELEPORT_COUNT); + if (is_local) + { + gAgent.setTeleportState( LLAgent::TELEPORT_LOCAL ); + } + else + { + gTeleportDisplay = TRUE; + gAgent.setTeleportState( LLAgent::TELEPORT_START ); + + //release geometry from old location + gPipeline.resetVertexBuffers(); + + if (gSavedSettings.getBOOL("SpeedRez")) + { + F32 draw_distance = gSavedSettings.getF32("RenderFarClip"); + if (gSavedDrawDistance < draw_distance) + { + gSavedDrawDistance = draw_distance; + } + gSavedSettings.setF32("SavedRenderFarClip", gSavedDrawDistance); + gSavedSettings.setF32("RenderFarClip", 32.0f); + } + if(gSavedSettings.getBOOL("OptionPlayTpSound")) + make_ui_sound("UISndTeleportOut"); + } + + // MBW -- Let the voice client know a teleport has begun so it can leave the existing channel. + // This was breaking the case of teleporting within a single sim. Backing it out for now. +// gVoiceClient->leaveChannel(); + + return true; +} + +void LLAgent::teleportRequest( + const U64& region_handle, + const LLVector3& pos_local, + bool look_at_from_camera) +{ + LLViewerRegion* regionp = getRegion(); + bool is_local = (region_handle == to_region_handle(getPositionGlobal())); + if(regionp && teleportCore(is_local)) + { + llinfos << "TeleportLocationRequest: '" << region_handle << "':" << pos_local + << llendl; + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("TeleportLocationRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msg->nextBlockFast(_PREHASH_Info); + msg->addU64("RegionHandle", region_handle); + msg->addVector3("Position", pos_local); + // + //LLVector3 look_at(0,1,0); + LLVector3 look_at = LLViewerCamera::getInstance()->getAtAxis(); + /*if (look_at_from_camera) + { + look_at = LLViewerCamera::getInstance()->getAtAxis(); + }*/ + // + msg->addVector3("LookAt", look_at); + sendReliableMessage(); + } +} + +// Landmark ID = LLUUID::null means teleport home +void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) +{ + LLViewerRegion *regionp = getRegion(); + if(regionp && teleportCore()) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_TeleportLandmarkRequest); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msg->addUUIDFast(_PREHASH_LandmarkID, landmark_asset_id); + sendReliableMessage(); + } +} + +void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) +{ + LLViewerRegion* regionp = getRegion(); + if(regionp && teleportCore()) + { + U32 teleport_flags = 0x0; + if (godlike) + { + teleport_flags |= TELEPORT_FLAGS_VIA_GODLIKE_LURE; + teleport_flags |= TELEPORT_FLAGS_DISABLE_CANCEL; + } + else + { + teleport_flags |= TELEPORT_FLAGS_VIA_LURE; + } + + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_TeleportLureRequest); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msg->addUUIDFast(_PREHASH_LureID, lure_id); + // teleport_flags is a legacy field, now derived sim-side: + msg->addU32("TeleportFlags", teleport_flags); + sendReliableMessage(); + } +} + + +// James Cook, July 28, 2005 +void LLAgent::teleportCancel() +{ + LLViewerRegion* regionp = getRegion(); + if(regionp) + { + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("TeleportCancel"); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + sendReliableMessage(); + } + gTeleportDisplay = FALSE; + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); +} + + +void LLAgent::teleportViaLocation(const LLVector3d& pos_global) +{ + LLViewerRegion* regionp = getRegion(); + U64 handle = to_region_handle(pos_global); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if(regionp && info) + { + LLVector3d region_origin = info->getGlobalOrigin(); + LLVector3 pos_local( + (F32)(pos_global.mdV[VX] - region_origin.mdV[VX]), + (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]), + (F32)(pos_global.mdV[VZ])); + teleportRequest(handle, pos_local); + } + else if(regionp && + teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) + { + llwarns << "Using deprecated teleportlocationrequest." << llendl; + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_TeleportLocationRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + + msg->nextBlockFast(_PREHASH_Info); + F32 width = regionp->getWidth(); + LLVector3 pos(fmod((F32)pos_global.mdV[VX], width), + fmod((F32)pos_global.mdV[VY], width), + (F32)pos_global.mdV[VZ]); + F32 region_x = (F32)(pos_global.mdV[VX]); + F32 region_y = (F32)(pos_global.mdV[VY]); + U64 region_handle = to_region_handle_global(region_x, region_y); + msg->addU64Fast(_PREHASH_RegionHandle, region_handle); + msg->addVector3Fast(_PREHASH_Position, pos); + pos.mV[VX] += 1; + // + LLVector3 lookat = LLViewerCamera::getInstance()->getAtAxis(); + //msg->addVector3Fast(_PREHASH_LookAt, pos); + msg->addVector3Fast(_PREHASH_LookAt, lookat); + // + sendReliableMessage(); + } +} + +// Teleport to global position, but keep facing in the same direction +void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) +{ + mbTeleportKeepsLookAt = true; + setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction + U64 region_handle = to_region_handle(pos_global); + LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); + teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); +} + +void LLAgent::setTeleportState(ETeleportState state) +{ + mTeleportState = state; + if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime")) + { + LLFloaterSnapshot::hide(0); + } + if (mTeleportState == TELEPORT_NONE) + { + mbTeleportKeepsLookAt = false; + } + // OGPX : Only compute a 'slurl' in non-OGP mode. In OGP, set it to regionuri in floaterteleport. + if ((mTeleportState == TELEPORT_MOVING)&& (!gSavedSettings.getBOOL("OpenGridProtocol"))) + { + // We're outa here. Save "back" slurl. + mTeleportSourceSLURL = getSLURL(); + } +} + +void LLAgent::stopCurrentAnimations() +{ + // This function stops all current overriding animations on this + // avatar, propagating this change back to the server. + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + for ( LLVOAvatar::AnimIterator anim_it = + avatarp->mPlayingAnimations.begin(); + anim_it != avatarp->mPlayingAnimations.end(); + anim_it++) + { + if (anim_it->first == + ANIM_AGENT_SIT_GROUND_CONSTRAINED) + { + // don't cancel a ground-sit anim, as viewers + // use this animation's status in + // determining whether we're sitting. ick. + } + else + { + // stop this animation locally + avatarp->stopMotion(anim_it->first, TRUE); + // ...and tell the server to tell everyone. + sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP); + } + } + + // re-assert at least the default standing animation, because + // viewers get confused by avs with no associated anims. + sendAnimationRequest(ANIM_AGENT_STAND, + ANIM_REQUEST_START); + } +} + +void LLAgent::fidget() +{ + if (!getAFK()) + { + F32 curTime = mFidgetTimer.getElapsedTimeF32(); + if (curTime > mNextFidgetTime) + { + // pick a random fidget anim here + S32 oldFidget = mCurrentFidget; + + mCurrentFidget = ll_rand(NUM_AGENT_STAND_ANIMS); + + if (mCurrentFidget != oldFidget) + { + //LLAgent::stopFidget(); + // + // for the sack of smaller packets, make this cancel the last one only + if(oldFidget != 0) + sendAnimationRequest(AGENT_STAND_ANIMS[oldFidget],ANIM_REQUEST_STOP); + // + + switch(mCurrentFidget) + { + case 0: + mCurrentFidget = 0; + break; + case 1: + sendAnimationRequest(ANIM_AGENT_STAND_1, ANIM_REQUEST_START); + mCurrentFidget = 1; + break; + case 2: + sendAnimationRequest(ANIM_AGENT_STAND_2, ANIM_REQUEST_START); + mCurrentFidget = 2; + break; + case 3: + sendAnimationRequest(ANIM_AGENT_STAND_3, ANIM_REQUEST_START); + mCurrentFidget = 3; + break; + case 4: + sendAnimationRequest(ANIM_AGENT_STAND_4, ANIM_REQUEST_START); + mCurrentFidget = 4; + break; + } + } + + // calculate next fidget time + mNextFidgetTime = curTime + ll_frand(MAX_FIDGET_TIME - MIN_FIDGET_TIME) + MIN_FIDGET_TIME; + } + } +} + +void LLAgent::stopFidget() +{ + LLDynamicArray anims; + anims.put(ANIM_AGENT_STAND_1); + anims.put(ANIM_AGENT_STAND_2); + anims.put(ANIM_AGENT_STAND_3); + anims.put(ANIM_AGENT_STAND_4); + + gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); +} + + +void LLAgent::requestEnterGodMode() +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestGodlikePowers); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_RequestBlock); + msg->addBOOLFast(_PREHASH_Godlike, TRUE); + msg->addUUIDFast(_PREHASH_Token, LLUUID::null); + + // simulators need to know about your request + sendReliableMessage(); +} + +void LLAgent::requestLeaveGodMode() +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestGodlikePowers); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_RequestBlock); + msg->addBOOLFast(_PREHASH_Godlike, FALSE); + msg->addUUIDFast(_PREHASH_Token, LLUUID::null); + + // simulator needs to know about your request + sendReliableMessage(); +} + +// wearables +LLAgent::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback() +{ + gAgent.createStandardWearablesAllDone(); +} + +LLAgent::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback() +{ + gAgent.sendAgentWearablesUpdate(); +} + +LLAgent::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback( + LLPointer cb, S32 index, LLWearable* wearable, U32 todo) : + mIndex(index), + mWearable(wearable), + mTodo(todo), + mCB(cb) +{ +} + +void LLAgent::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item) +{ + if (inv_item.isNull()) + return; + + gAgent.addWearabletoAgentInventoryDone(mIndex, inv_item, mWearable); + + if (mTodo & CALL_UPDATE) + { + gAgent.sendAgentWearablesUpdate(); + } + if (mTodo & CALL_RECOVERDONE) + { + gAgent.recoverMissingWearableDone(); + } + /* + * Do this for every one in the loop + */ + if (mTodo & CALL_CREATESTANDARDDONE) + { + gAgent.createStandardWearablesDone(mIndex); + } + if (mTodo & CALL_MAKENEWOUTFITDONE) + { + gAgent.makeNewOutfitDone(mIndex); + } +} + +void LLAgent::addWearabletoAgentInventoryDone( + S32 index, + const LLUUID& item_id, + LLWearable* wearable) +{ + if (item_id.isNull()) + return; + + LLUUID old_item_id = mWearableEntry[index].mItemID; + mWearableEntry[index].mItemID = item_id; + mWearableEntry[index].mWearable = wearable; + if (old_item_id.notNull()) + gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if(item && wearable) + { + // We're changing the asset id, so we both need to set it + // locally via setAssetUUID() and via setTransactionID() which + // will be decoded on the server. JC + item->setAssetUUID(wearable->getID()); + item->setTransactionID(wearable->getTransactionID()); + gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id); + item->updateServer(FALSE); + } + gInventory.notifyObservers(); +} + +void LLAgent::sendAgentWearablesUpdate() +{ + // First make sure that we have inventory items for each wearable + S32 i; + for(i=0; i < WT_COUNT; ++i) + { + LLWearable* wearable = mWearableEntry[ i ].mWearable; + if (wearable) + { + if( mWearableEntry[ i ].mItemID.isNull() ) + { + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + i, + wearable, + addWearableToAgentInventoryCallback::CALL_NONE); + addWearableToAgentInventory(cb, wearable); + } + else + { + gInventory.addChangedMask( LLInventoryObserver::LABEL, + mWearableEntry[i].mItemID ); + } + } + } + + // Then make sure the inventory is in sync with the avatar. + gInventory.notifyObservers(); + + // Send the AgentIsNowWearing + gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing); + + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); + + LL_DEBUGS("Wearables") << "sendAgentWearablesUpdate()" << LL_ENDL; + for(i=0; i < WT_COUNT; ++i) + { + gMessageSystem->nextBlockFast(_PREHASH_WearableData); + + U8 type_u8 = (U8)i; + gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8 ); + + LLWearable* wearable = mWearableEntry[ i ].mWearable; + if( wearable ) + { + LL_DEBUGS("Wearables") << "Sending wearable " << wearable->getName() << " mItemID = " << mWearableEntry[ i ].mItemID << LL_ENDL; + gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID ); + } + else + { + LL_DEBUGS("Wearables") << "Not wearing wearable type " << LLWearable::typeToTypeName((EWearableType)i) << LL_ENDL; + gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null ); + } + + LL_DEBUGS("Wearables") << " " << LLWearable::typeToTypeLabel((EWearableType)i) << " : " << (wearable ? wearable->getID() : LLUUID::null) << LL_ENDL; + } + gAgent.sendReliableMessage(); +} + +void LLAgent::saveWearable( EWearableType type, BOOL send_update ) +{ + LLWearable* old_wearable = mWearableEntry[(S32)type].mWearable; + if( old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()) ) + { + LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable ); + mWearableEntry[(S32)type].mWearable = new_wearable; + + LLInventoryItem* item = gInventory.getItem(mWearableEntry[(S32)type].mItemID); + if( item ) + { + // Update existing inventory item + LLPointer template_item = + new LLViewerInventoryItem(item->getUUID(), + item->getParentUUID(), + item->getPermissions(), + new_wearable->getID(), + new_wearable->getAssetType(), + item->getInventoryType(), + item->getName(), + item->getDescription(), + item->getSaleInfo(), + item->getFlags(), + item->getCreationDate()); + template_item->setTransactionID(new_wearable->getTransactionID()); + template_item->updateServer(FALSE); + gInventory.updateItem(template_item); + } + else + { + // Add a new inventory item (shouldn't ever happen here) + U32 todo = addWearableToAgentInventoryCallback::CALL_NONE; + if (send_update) + { + todo |= addWearableToAgentInventoryCallback::CALL_UPDATE; + } + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + (S32)type, + new_wearable, + todo); + addWearableToAgentInventory(cb, new_wearable); + return; + } + + getAvatarObject()->wearableUpdated( type ); + + if( send_update ) + { + sendAgentWearablesUpdate(); + } + } +} + +void LLAgent::saveWearableAs( + EWearableType type, + const std::string& new_name, + BOOL save_in_lost_and_found) +{ + if(!isWearableCopyable(type)) + { + llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; + return; + } + LLWearable* old_wearable = getWearable(type); + if(!old_wearable) + { + llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; + return; + } + LLInventoryItem* item = gInventory.getItem(mWearableEntry[type].mItemID); + if(!item) + { + llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl; + return; + } + std::string trunc_name(new_name); + LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); + LLWearable* new_wearable = gWearableList.createCopyFromAvatar( + old_wearable, + trunc_name); + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + type, + new_wearable, + addWearableToAgentInventoryCallback::CALL_UPDATE); + LLUUID category_id; + if (save_in_lost_and_found) + { + category_id = gInventory.findCategoryUUIDForType( + LLAssetType::AT_LOST_AND_FOUND); + } + else + { + // put in same folder as original + category_id = item->getParentUUID(); + } + + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + category_id, + new_name, + cb); + +/* + LLWearable* old_wearable = getWearable( type ); + if( old_wearable ) + { + std::string old_name = old_wearable->getName(); + old_wearable->setName( new_name ); + LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable ); + old_wearable->setName( old_name ); + + LLUUID category_id; + LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID ); + if( item ) + { + new_wearable->setPermissions(item->getPermissions()); + if (save_in_lost_and_found) + { + category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + } + else + { + // put in same folder as original + category_id = item->getParentUUID(); + } + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(view) + { + view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); + } + } + + mWearableEntry[ type ].mWearable = new_wearable; + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + type, + addWearableToAgentInventoryCallback::CALL_UPDATE); + addWearableToAgentInventory(cb, new_wearable, category_id); + } +*/ +} + +void LLAgent::revertWearable( EWearableType type ) +{ + LLWearable* wearable = mWearableEntry[(S32)type].mWearable; + if( wearable ) + { + wearable->writeToAvatar( TRUE ); + } + sendAgentSetAppearance(); +} + +void LLAgent::revertAllWearables() +{ + for( S32 i=0; i < WT_COUNT; i++ ) + { + revertWearable( (EWearableType)i ); + } +} + +void LLAgent::saveAllWearables() +{ + //if(!gInventory.isLoaded()) + //{ + // return; + //} + + for( S32 i=0; i < WT_COUNT; i++ ) + { + saveWearable( (EWearableType)i, FALSE ); + } + sendAgentWearablesUpdate(); +} + +// Called when the user changes the name of a wearable inventory item that is currenlty being worn. +void LLAgent::setWearableName( const LLUUID& item_id, const std::string& new_name ) +{ + for( S32 i=0; i < WT_COUNT; i++ ) + { + if( mWearableEntry[i].mItemID == item_id ) + { + LLWearable* old_wearable = mWearableEntry[i].mWearable; + llassert( old_wearable ); + + std::string old_name = old_wearable->getName(); + old_wearable->setName( new_name ); + LLWearable* new_wearable = gWearableList.createCopy( old_wearable ); + LLInventoryItem* item = gInventory.getItem(item_id); + if(item) + { + new_wearable->setPermissions(item->getPermissions()); + } + old_wearable->setName( old_name ); + + mWearableEntry[i].mWearable = new_wearable; + sendAgentWearablesUpdate(); + break; + } + } +} + + +BOOL LLAgent::isWearableModifiable(EWearableType type) +{ + LLUUID item_id = getWearableItem(type); + if(!item_id.isNull()) + { + LLInventoryItem* item = gInventory.getItem(item_id); + if(item && item->getPermissions().allowModifyBy(gAgent.getID(), + gAgent.getGroupID())) + { + return TRUE; + } + } + return FALSE; +} + +BOOL LLAgent::isWearableCopyable(EWearableType type) +{ + LLUUID item_id = getWearableItem(type); + if(!item_id.isNull()) + { + LLInventoryItem* item = gInventory.getItem(item_id); + if(item && item->getPermissions().allowCopyBy(gAgent.getID(), + gAgent.getGroupID())) + { + return TRUE; + } + } + return FALSE; +} + +U32 LLAgent::getWearablePermMask(EWearableType type) +{ + LLUUID item_id = getWearableItem(type); + if(!item_id.isNull()) + { + LLInventoryItem* item = gInventory.getItem(item_id); + if(item) + { + return item->getPermissions().getMaskOwner(); + } + } + return PERM_NONE; +} + +LLInventoryItem* LLAgent::getWearableInventoryItem(EWearableType type) +{ + LLUUID item_id = getWearableItem(type); + LLInventoryItem* item = NULL; + if(item_id.notNull()) + { + item = gInventory.getItem(item_id); + } + return item; +} + +LLWearable* LLAgent::getWearableFromWearableItem( const LLUUID& item_id ) +{ + for( S32 i=0; i < WT_COUNT; i++ ) + { + if( mWearableEntry[i].mItemID == item_id ) + { + return mWearableEntry[i].mWearable; + } + } + return NULL; +} + + +void LLAgent::sendAgentWearablesRequest() +{ + gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + sendReliableMessage(); +} + +// Used to enable/disable menu items. +// static +BOOL LLAgent::selfHasWearable( void* userdata ) +{ + EWearableType type = (EWearableType)(intptr_t)userdata; + return gAgent.getWearable( type ) != NULL; +} + +BOOL LLAgent::isWearingItem( const LLUUID& item_id ) +{ + return (getWearableFromWearableItem( item_id ) != NULL); +} + +// static +void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void** user_data ) +{ + // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates + // that may result from AgentWearablesRequest having been sent more than once. + static bool first = true; + if (!first) return; + first = false; + + LLUUID agent_id; + gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); + + LLVOAvatar* avatar = gAgent.getAvatarObject(); + if( avatar && (agent_id == avatar->getID()) ) + { + gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgent.mAgentWearablesUpdateSerialNum ); + + S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); + if( num_wearables < 4 ) + { + // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin). + // The fact that they don't have any here (only a dummy is sent) implies that this account existed + // before we had wearables, or that the database has gotten messed up. + return; + } + //else + //{ + // // OGPX HACK: OGP authentication does not pass back login-flags, + // // thus doesn't check for "gendered" flag + // // so this isn't an ideal place for this because the check in idle_startup in STATE_WEARABLES_WAIT + // // is happening *before* this call. That causes the welcomechoosesex dialog to be displayed + // // but I'm torn on removing this commented out code because I'm unsure how the initial wearables + // // code will work out. + // gAgent.setGenderChosen(TRUE); + //} + + //lldebugs << "processAgentInitialWearablesUpdate()" << llendl; + // Add wearables + LLUUID asset_id_array[ WT_COUNT ]; + S32 i; + for( i=0; i < num_wearables; i++ ) + { + U8 type_u8 = 0; + gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i ); + if( type_u8 >= WT_COUNT ) + { + continue; + } + EWearableType type = (EWearableType) type_u8; + + LLUUID item_id; + gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i ); + + LLUUID asset_id; + gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i ); + if( asset_id.isNull() ) + { + LLWearable::removeFromAvatar( type, FALSE ); + } + else + { + LLAssetType::EType asset_type = LLWearable::typeToAssetType( type ); + if( asset_type == LLAssetType::AT_NONE ) + { + continue; + } + + gAgent.mWearableEntry[type].mItemID = item_id; + asset_id_array[type] = asset_id; + } + + LL_DEBUGS("Wearables") << " " << LLWearable::typeToTypeLabel(type) << " " << asset_id << " item id " << gAgent.mWearableEntry[type].mItemID.asString() << LL_ENDL; + } + + // now that we have the asset ids...request the wearable assets + for( i = 0; i < WT_COUNT; i++ ) + { + LL_DEBUGS("Wearables") << " fetching " << asset_id_array[i] << LL_ENDL; + if( !gAgent.mWearableEntry[i].mItemID.isNull() ) + { + gWearableList.getAsset( + asset_id_array[i], + LLStringUtil::null, + LLWearable::typeToAssetType( (EWearableType) i ), + LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); + } + } + } +} + +// A single wearable that the avatar was wearing on start-up has arrived from the database. +// static +void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdata ) +{ + EWearableType type = (EWearableType)(intptr_t)userdata; + + LLVOAvatar* avatar = gAgent.getAvatarObject(); + if( !avatar ) + { + return; + } + + if( wearable ) + { + llassert( type == wearable->getType() ); + gAgent.mWearableEntry[ type ].mWearable = wearable; + + // disable composites if initial textures are baked + avatar->setupComposites(); + gAgent.queryWearableCache(); + + wearable->writeToAvatar( FALSE ); + avatar->setCompositeUpdatesEnabled(TRUE); + gInventory.addChangedMask( LLInventoryObserver::LABEL, gAgent.mWearableEntry[type].mItemID ); + } + else + { + // Somehow the asset doesn't exist in the database. + gAgent.recoverMissingWearable( type ); + } + + gInventory.notifyObservers(); + + // Have all the wearables that the avatar was wearing at log-in arrived? + if( !gAgent.mWearablesLoaded ) + { + gAgent.mWearablesLoaded = TRUE; + for( S32 i = 0; i < WT_COUNT; i++ ) + { + if( !gAgent.mWearableEntry[i].mItemID.isNull() && !gAgent.mWearableEntry[i].mWearable ) + { + gAgent.mWearablesLoaded = FALSE; + break; + } + } + } + + if( gAgent.mWearablesLoaded ) + { + // Make sure that the server's idea of the avatar's wearables actually match the wearables. + gAgent.sendAgentSetAppearance(); + + // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time. + // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive. + if( !gAgent.cameraCustomizeAvatar() ) + { + avatar->requestLayerSetUploads(); + } + } +} + +// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the +// database. If for some reason, we can't load one of those assets, we can try to reconstruct it so that +// the user isn't left without a shape, for example. (We can do that only after the inventory has loaded.) +void LLAgent::recoverMissingWearable( EWearableType type ) +{ + // Try to recover by replacing missing wearable with a new one. + LLNotifications::instance().add("ReplacedMissingWearable"); + lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; + LLWearable* new_wearable = gWearableList.createNewWearable(type); + + S32 type_s32 = (S32) type; + mWearableEntry[type_s32].mWearable = new_wearable; + new_wearable->writeToAvatar( TRUE ); + + // Add a new one in the lost and found folder. + // (We used to overwrite the "not found" one, but that could potentially + // destory content.) JC + LLUUID lost_and_found_id = + gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + type_s32, + new_wearable, + addWearableToAgentInventoryCallback::CALL_RECOVERDONE); + addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE); +} + +void LLAgent::recoverMissingWearableDone() +{ + // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated? + mWearablesLoaded = TRUE; + for( S32 i = 0; i < WT_COUNT; i++ ) + { + if( !mWearableEntry[i].mItemID.isNull() && !mWearableEntry[i].mWearable ) + { + mWearablesLoaded = FALSE; + break; + } + } + + if( mWearablesLoaded ) + { + // Make sure that the server's idea of the avatar's wearables actually match the wearables. + sendAgentSetAppearance(); + } + else + { + gInventory.addChangedMask( LLInventoryObserver::LABEL, LLUUID::null ); + gInventory.notifyObservers(); + } +} + +void LLAgent::createStandardWearables(BOOL female) +{ + llwarns << "Creating Standard " << (female ? "female" : "male" ) + << " Wearables" << llendl; + + if (mAvatarObject.isNull()) + { + return; + } + + if(female) mAvatarObject->setSex(SEX_FEMALE); + else mAvatarObject->setSex(SEX_MALE); + + BOOL create[WT_COUNT] = + { + TRUE, //WT_SHAPE + TRUE, //WT_SKIN + TRUE, //WT_HAIR + TRUE, //WT_EYES + TRUE, //WT_SHIRT + TRUE, //WT_PANTS + TRUE, //WT_SHOES + TRUE, //WT_SOCKS + FALSE, //WT_JACKET + FALSE, //WT_GLOVES + TRUE, //WT_UNDERSHIRT + TRUE, //WT_UNDERPANTS + FALSE, //WT_SKIRT + FALSE, //WT_ALPHA + FALSE //WT_TATTOO + }; + + for( S32 i=0; i < WT_COUNT; i++ ) + { + bool once = false; + LLPointer donecb = NULL; + if( create[i] ) + { + if (!once) + { + once = true; + donecb = new createStandardWearablesAllDoneCallback; + } + llassert( mWearableEntry[i].mWearable == NULL ); + LLWearable* wearable = gWearableList.createNewWearable((EWearableType)i); + mWearableEntry[i].mWearable = wearable; + // no need to update here... + LLPointer cb = + new addWearableToAgentInventoryCallback( + donecb, + i, + wearable, + addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE); + addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE); + } + } +} +void LLAgent::createStandardWearablesDone(S32 index) +{ + LLWearable* wearable = mWearableEntry[index].mWearable; + + if (wearable) + { + wearable->writeToAvatar(TRUE); + } +} + +void LLAgent::createStandardWearablesAllDone() +{ + // ... because sendAgentWearablesUpdate will notify inventory + // observers. + mWearablesLoaded = TRUE; + sendAgentWearablesUpdate(); + sendAgentSetAppearance(); + + // Treat this as the first texture entry message, if none received yet + mAvatarObject->onFirstTEMessageReceived(); +} + +void LLAgent::makeNewOutfit( + const std::string& new_folder_name, + const LLDynamicArray& wearables_to_include, + const LLDynamicArray& attachments_to_include, + BOOL rename_clothing) +{ + if (mAvatarObject.isNull()) + { + return; + } + + // First, make a folder in the Clothes directory. + LLUUID folder_id = gInventory.createNewCategory( + gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING), + LLAssetType::AT_NONE, + new_folder_name); + + bool found_first_item = false; + + /////////////////// + // Wearables + + if( wearables_to_include.count() ) + { + // Then, iterate though each of the wearables and save copies of them in the folder. + S32 i; + S32 count = wearables_to_include.count(); + LLDynamicArray delete_items; + LLPointer cbdone = NULL; + for( i = 0; i < count; ++i ) + { + S32 index = wearables_to_include[i]; + LLWearable* old_wearable = mWearableEntry[ index ].mWearable; + if( old_wearable ) + { + std::string new_name; + LLWearable* new_wearable; + new_wearable = gWearableList.createCopy(old_wearable); + if (rename_clothing) + { + new_name = new_folder_name; + new_name.append(" "); + new_name.append(old_wearable->getTypeLabel()); + LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); + new_wearable->setName(new_name); + } + + LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID); + S32 todo = addWearableToAgentInventoryCallback::CALL_NONE; + if (!found_first_item) + { + found_first_item = true; + /* set the focus to the first item */ + todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE; + /* send the agent wearables update when done */ + cbdone = new sendAgentWearablesUpdateCallback; + } + LLPointer cb = + new addWearableToAgentInventoryCallback( + cbdone, + index, + new_wearable, + todo); + if (isWearableCopyable((EWearableType)index)) + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + folder_id, + new_name, + cb); + } + else + { + move_inventory_item( + gAgent.getID(), + gAgent.getSessionID(), + item->getUUID(), + folder_id, + new_name, + cb); + } + } + } + gInventory.notifyObservers(); + } + + + /////////////////// + // Attachments + + if( attachments_to_include.count() ) + { + BOOL msg_started = FALSE; + LLMessageSystem* msg = gMessageSystem; + for( S32 i = 0; i < attachments_to_include.count(); i++ ) + { + S32 attachment_pt = attachments_to_include[i]; + LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL ); + if(!attachment) continue; + LLViewerObject* attached_object = attachment->getObject(); + if(!attached_object) continue; + const LLUUID& item_id = attachment->getItemID(); + if(item_id.isNull()) continue; + LLInventoryItem* item = gInventory.getItem(item_id); + if(!item) continue; + if(!msg_started) + { + msg_started = TRUE; + msg->newMessage("CreateNewOutfitAttachments"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", getID()); + msg->addUUID("SessionID", getSessionID()); + msg->nextBlock("HeaderData"); + msg->addUUID("NewFolderID", folder_id); + } + msg->nextBlock("ObjectData"); + msg->addUUID("OldItemID", item_id); + msg->addUUID("OldFolderID", item->getParentUUID()); + } + + if( msg_started ) + { + sendReliableMessage(); + } + + } +} + +void LLAgent::makeNewOutfitDone(S32 index) +{ + LLUUID first_item_id = mWearableEntry[index].mItemID; + // Open the inventory and select the first item we added. + if( first_item_id.notNull() ) + { + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(view) + { + view->getPanel()->setSelection(first_item_id, TAKE_FOCUS_NO); + } + } +} + + +void LLAgent::addWearableToAgentInventory( + LLPointer cb, + LLWearable* wearable, + const LLUUID& category_id, + BOOL notify) +{ + create_inventory_item( + gAgent.getID(), + gAgent.getSessionID(), + category_id, + wearable->getTransactionID(), + wearable->getName(), + wearable->getDescription(), + wearable->getAssetType(), + LLInventoryType::IT_WEARABLE, + wearable->getType(), + wearable->getPermissions().getMaskNextOwner(), + cb); +} + +//----------------------------------------------------------------------------- +// sendAgentSetAppearance() +//----------------------------------------------------------------------------- +void LLAgent::sendAgentSetAppearance() +{ + if (mAvatarObject.isNull()) return; + + if (mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar()) + { + return; + } + + + llinfos << "TAT: Sent AgentSetAppearance: " << mAvatarObject->getBakedStatusForPrintout() << llendl; + //dumpAvatarTEs( "sendAgentSetAppearance()" ); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_AgentSetAppearance); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + + // correct for the collision tolerance (to make it look like the + // agent is actually walking on the ground/object) + // NOTE -- when we start correcting all of the other Havok geometry + // to compensate for the COLLISION_TOLERANCE ugliness we will have + // to tweak this number again + const LLVector3 body_size = mAvatarObject->mBodySize; + msg->addVector3Fast(_PREHASH_Size, body_size); + + // To guard against out of order packets + // Note: always start by sending 1. This resets the server's count. 0 on the server means "uninitialized" + mAppearanceSerialNum++; + msg->addU32Fast(_PREHASH_SerialNum, mAppearanceSerialNum ); + + // is texture data current relative to wearables? + // KLW - TAT this will probably need to check the local queue. + BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded; + + for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) + { + const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); + + // if we're not wearing a skirt, we don't need the texture to be baked + if (texture_index == TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT)) + { + continue; + } + + // IMG_DEFAULT_AVATAR means not baked + if (!mAvatarObject->isTextureDefined(texture_index)) + { + textures_current = FALSE; + break; + } + } + + // only update cache entries if we have all our baked textures + if (textures_current) + { + llinfos << "TAT: Sending cached texture data" << llendl; + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) + { + const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); + LLUUID hash; + for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) + { + // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; + const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; + const LLWearable* wearable = getWearable(wearable_type); + if (wearable) + { + hash ^= wearable->getID(); + } + } + if (hash.notNull()) + { + hash ^= wearable_dict->mHashID; + } + + const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); + + msg->nextBlockFast(_PREHASH_WearableData); + msg->addUUIDFast(_PREHASH_CacheID, hash); + msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); + } + msg->nextBlockFast(_PREHASH_ObjectData); + + // Tag changing support + if (!gSavedSettings.controlExists("SpoofClientUUID")) + { + gSavedSettings.declareString("SpoofClientUUID", "8873757c-092a-98fb-1afd-ecd347566fcd", "FAKIN' BAKE-IN"); + gSavedSettings.setString("SpoofClientUUID", "8873757c-092a-98fb-1afd-ecd347566fcd"); + } + + mAvatarObject->packTEMessage( gMessageSystem, 1, gSavedSettings.getString("SpoofClientUUID") ); + } + else + { + // If the textures aren't baked, send NULL for texture IDs + // This means the baked texture IDs on the server will be untouched. + // Once all textures are baked, another AvatarAppearance message will be sent to update the TEs + msg->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0); + } + + + S32 transmitted_params = 0; + for (LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarObject->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*)mAvatarObject->getNextVisualParam()) + { + if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) + { + msg->nextBlockFast(_PREHASH_VisualParam ); + + // We don't send the param ids. Instead, we assume that the receiver has the same params in the same sequence. + const F32 param_value = param->getWeight(); + const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight()); + msg->addU8Fast(_PREHASH_ParamValue, new_weight ); + transmitted_params++; + } + } + +// llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; + sendReliableMessage(); +} + +void LLAgent::sendAgentDataUpdateRequest() +{ + gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + sendReliableMessage(); +} + +void LLAgent::removeWearable( EWearableType type ) +{ + LLWearable* old_wearable = mWearableEntry[ type ].mWearable; + + if ( (gAgent.isTeen()) + && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) + { + // Can't take off underclothing in simple UI mode or on PG accounts + return; + } + + if( old_wearable ) + { + if( old_wearable->isDirty() ) + { + LLSD payload; + payload["wearable_type"] = (S32)type; + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + LLNotifications::instance().add("WearableSave", LLSD(), payload, &LLAgent::onRemoveWearableDialog); + return; + } + else + { + removeWearableFinal( type ); + } + } +} + +// static +bool LLAgent::onRemoveWearableDialog(const LLSD& notification, const LLSD& response ) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger(); + switch( option ) + { + case 0: // "Save" + gAgent.saveWearable( type ); + gAgent.removeWearableFinal( type ); + break; + + case 1: // "Don't Save" + gAgent.removeWearableFinal( type ); + break; + + case 2: // "Cancel" + break; + + default: + llassert(0); + break; + } + return false; +} + +// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal. +void LLAgent::removeWearableFinal( EWearableType type ) +{ + LLWearable* old_wearable = mWearableEntry[ type ].mWearable; + + gInventory.addChangedMask( LLInventoryObserver::LABEL, mWearableEntry[type].mItemID ); + + mWearableEntry[ type ].mWearable = NULL; + mWearableEntry[ type ].mItemID.setNull(); + + queryWearableCache(); + + if( old_wearable ) + { + old_wearable->removeFromAvatar( TRUE ); + } + + // Update the server + sendAgentWearablesUpdate(); + sendAgentSetAppearance(); + gInventory.notifyObservers(); +} + +void LLAgent::copyWearableToInventory( EWearableType type ) +{ + LLWearable* wearable = mWearableEntry[ type ].mWearable; + if( wearable ) + { + // Save the old wearable if it has changed. + if( wearable->isDirty() ) + { + wearable = gWearableList.createCopyFromAvatar( wearable ); + mWearableEntry[ type ].mWearable = wearable; + } + + // Make a new entry in the inventory. (Put it in the same folder as the original item if possible.) + LLUUID category_id; + LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID ); + if( item ) + { + category_id = item->getParentUUID(); + wearable->setPermissions(item->getPermissions()); + } + LLPointer cb = + new addWearableToAgentInventoryCallback( + LLPointer(NULL), + type, + wearable); + addWearableToAgentInventory(cb, wearable, category_id); + } +} + + +// A little struct to let setWearable() communicate more than one value with onSetWearableDialog(). +struct LLSetWearableData +{ + LLSetWearableData( const LLUUID& new_item_id, LLWearable* new_wearable ) : + mNewItemID( new_item_id ), mNewWearable( new_wearable ) {} + LLUUID mNewItemID; + LLWearable* mNewWearable; +}; + +BOOL LLAgent::needsReplacement(EWearableType wearableType, S32 remove) +{ + return TRUE; + /*if (remove) return TRUE; + + return getWearable(wearableType) ? TRUE : FALSE;*/ +} + +// Assumes existing wearables are not dirty. +void LLAgent::setWearableOutfit( + const LLInventoryItem::item_array_t& items, + const LLDynamicArray< LLWearable* >& wearables, + BOOL remove ) +{ + lldebugs << "setWearableOutfit() start" << llendl; + + BOOL wearables_to_remove[WT_COUNT]; + wearables_to_remove[WT_SHAPE] = FALSE; + wearables_to_remove[WT_SKIN] = FALSE; + wearables_to_remove[WT_HAIR] = FALSE; + wearables_to_remove[WT_EYES] = FALSE; + wearables_to_remove[WT_SHIRT] = remove; + wearables_to_remove[WT_PANTS] = remove; + wearables_to_remove[WT_SHOES] = remove; + wearables_to_remove[WT_SOCKS] = remove; + wearables_to_remove[WT_JACKET] = remove; + wearables_to_remove[WT_GLOVES] = remove; + wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove; + wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove; + wearables_to_remove[WT_SKIRT] = remove; + wearables_to_remove[WT_ALPHA] = remove; + wearables_to_remove[WT_TATTOO] = remove; + + S32 count = wearables.count(); + llassert( items.count() == count ); + + S32 i; + for( i = 0; i < count; i++ ) + { + LLWearable* new_wearable = wearables[i]; + LLPointer new_item = items[i]; + + EWearableType type = new_wearable->getType(); + wearables_to_remove[type] = FALSE; + + LLWearable* old_wearable = mWearableEntry[ type ].mWearable; + if( old_wearable ) + { + const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; + if( (old_wearable->getID() == new_wearable->getID()) && + (old_item_id == new_item->getUUID()) ) + { + lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl; + continue; + } + + gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); + + // Assumes existing wearables are not dirty. + if( old_wearable->isDirty() ) + { + llassert(0); + continue; + } + } + + mWearableEntry[ type ].mItemID = new_item->getUUID(); + mWearableEntry[ type ].mWearable = new_wearable; + } + + std::vector wearables_being_removed; + + for( i = 0; i < WT_COUNT; i++ ) + { + if( wearables_to_remove[i] ) + { + wearables_being_removed.push_back(mWearableEntry[ i ].mWearable); + mWearableEntry[ i ].mWearable = NULL; + + gInventory.addChangedMask(LLInventoryObserver::LABEL, mWearableEntry[ i ].mItemID); + mWearableEntry[ i ].mItemID.setNull(); + } + } + + gInventory.notifyObservers(); + + queryWearableCache(); + + std::vector::iterator wearable_iter; + + for( wearable_iter = wearables_being_removed.begin(); + wearable_iter != wearables_being_removed.end(); + ++wearable_iter) + { + LLWearable* wearablep = *wearable_iter; + if (wearablep) + { + wearablep->removeFromAvatar( TRUE ); + } + } + + for( i = 0; i < count; i++ ) + { + wearables[i]->writeToAvatar( TRUE ); + } + + // Start rendering & update the server + mWearablesLoaded = TRUE; + sendAgentWearablesUpdate(); + sendAgentSetAppearance(); + + lldebugs << "setWearableOutfit() end" << llendl; +} + + +// User has picked "wear on avatar" from a menu. +void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable ) +{ + EWearableType type = new_wearable->getType(); + + LLWearable* old_wearable = mWearableEntry[ type ].mWearable; + if( old_wearable ) + { + const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; + if( (old_wearable->getID() == new_wearable->getID()) && + (old_item_id == new_item->getUUID()) ) + { + lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl; + return; + } + + if( old_wearable->isDirty() ) + { + // Bring up modal dialog: Save changes? Yes, No, Cancel + LLSD payload; + payload["item_id"] = new_item->getUUID(); + LLNotifications::instance().add( "WearableSave", LLSD(), payload, boost::bind(LLAgent::onSetWearableDialog, _1, _2, new_wearable)); + return; + } + } + + setWearableFinal( new_item, new_wearable ); +} + +// static +bool LLAgent::onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable ) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID()); + if( !new_item ) + { + delete wearable; + return false; + } + + switch( option ) + { + case 0: // "Save" + gAgent.saveWearable( wearable->getType() ); + gAgent.setWearableFinal( new_item, wearable ); + break; + + case 1: // "Don't Save" + gAgent.setWearableFinal( new_item, wearable ); + break; + + case 2: // "Cancel" + break; + + default: + llassert(0); + break; + } + + delete wearable; + return false; +} + +// Called from setWearable() and onSetWearableDialog() to actually set the wearable. +void LLAgent::setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable ) +{ + EWearableType type = new_wearable->getType(); + + // Replace the old wearable with a new one. + llassert( new_item->getAssetUUID() == new_wearable->getID() ); + LLUUID old_item_id = mWearableEntry[ type ].mItemID; + mWearableEntry[ type ].mItemID = new_item->getUUID(); + mWearableEntry[ type ].mWearable = new_wearable; + + if (old_item_id.notNull()) + { + gInventory.addChangedMask( LLInventoryObserver::LABEL, old_item_id ); + gInventory.notifyObservers(); + } + + //llinfos << "LLVOAvatar::setWearable()" << llendl; + queryWearableCache(); + new_wearable->writeToAvatar( TRUE ); + + // Update the server + sendAgentWearablesUpdate(); + sendAgentSetAppearance(); +} + +void LLAgent::queryWearableCache() +{ + if (!mWearablesLoaded) + { + return; + } + + // Look up affected baked textures. + // If they exist: + // disallow updates for affected layersets (until dataserver responds with cache request.) + // If cache miss, turn updates back on and invalidate composite. + // If cache hit, modify baked texture entries. + // + // Cache requests contain list of hashes for each baked texture entry. + // Response is list of valid baked texture assets. (same message) + + gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); + gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID); + + S32 num_queries = 0; + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) + { + const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); + LLUUID hash; + for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) + { + // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; + const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; + const LLWearable* wearable = getWearable(wearable_type); + if (wearable) + { + hash ^= wearable->getID(); + } + } + if (hash.notNull()) + { + hash ^= wearable_dict->mHashID; + num_queries++; + // *NOTE: make sure at least one request gets packed + + //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl; + gMessageSystem->nextBlockFast(_PREHASH_WearableData); + gMessageSystem->addUUIDFast(_PREHASH_ID, hash); + gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index); + } + + mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID; + } + + llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; + gMessageSystem->sendReliable(getRegion()->getHost()); + mNumPendingQueries++; + mTextureCacheQueryID++; +} + +// User has picked "remove from avatar" from a menu. +// static +void LLAgent::userRemoveWearable( void* userdata ) +{ + EWearableType type = (EWearableType)(intptr_t)userdata; + + if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES) ) //&& + //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) + { + gAgent.removeWearable( type ); + } +} + +void LLAgent::userRemoveAllClothes( void* userdata ) +{ + // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty. + if( gFloaterCustomize ) + { + gFloaterCustomize->askToSaveIfDirty( LLAgent::userRemoveAllClothesStep2, NULL ); + } + else + { + LLAgent::userRemoveAllClothesStep2( TRUE, NULL ); + } +} + +void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata ) +{ + if( proceed ) + { + gAgent.removeWearable( WT_SHIRT ); + gAgent.removeWearable( WT_PANTS ); + gAgent.removeWearable( WT_SHOES ); + gAgent.removeWearable( WT_SOCKS ); + gAgent.removeWearable( WT_JACKET ); + gAgent.removeWearable( WT_GLOVES ); + gAgent.removeWearable( WT_UNDERSHIRT ); + gAgent.removeWearable( WT_UNDERPANTS ); + gAgent.removeWearable( WT_SKIRT ); + gAgent.removeWearable( WT_ALPHA ); + gAgent.removeWearable( WT_TATTOO ); + } +} + +void LLAgent::userRemoveAllAttachments( void* userdata ) +{ + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if(!avatarp) + { + llwarns << "No avatar found." << llendl; + return; + } + + gMessageSystem->newMessage("ObjectDetach"); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); + iter != avatarp->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLViewerObject* objectp = attachment->getObject(); + if (objectp) + { + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); + } + } + gMessageSystem->sendReliable( gAgent.getRegionHost() ); +} + +void LLAgent::observeFriends() +{ + if(!mFriendObserver) + { + mFriendObserver = new LLAgentFriendObserver; + LLAvatarTracker::instance().addObserver(mFriendObserver); + friendsChanged(); + } +} + +void LLAgent::parseTeleportMessages(const std::string& xml_filename) +{ + LLXMLNodePtr root; + BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + + if (!success || !root || !root->hasName( "teleport_messages" )) + { + llerrs << "Problem reading teleport string XML file: " + << xml_filename << llendl; + return; + } + + for (LLXMLNode* message_set = root->getFirstChild(); + message_set != NULL; + message_set = message_set->getNextSibling()) + { + if ( !message_set->hasName("message_set") ) continue; + + std::map *teleport_msg_map = NULL; + std::string message_set_name; + + if ( message_set->getAttributeString("name", message_set_name) ) + { + //now we loop over all the string in the set and add them + //to the appropriate set + if ( message_set_name == "errors" ) + { + teleport_msg_map = &sTeleportErrorMessages; + } + else if ( message_set_name == "progress" ) + { + teleport_msg_map = &sTeleportProgressMessages; + } + } + + if ( !teleport_msg_map ) continue; + + std::string message_name; + for (LLXMLNode* message_node = message_set->getFirstChild(); + message_node != NULL; + message_node = message_node->getNextSibling()) + { + if ( message_node->hasName("message") && + message_node->getAttributeString("name", message_name) ) + { + (*teleport_msg_map)[message_name] = + message_node->getTextContents(); + } //end if ( message exists and has a name) + } //end for (all message in set) + }//end for (all message sets in xml file) +} + +// OGPX - This code will change when capabilities get refactored. +// Right now this is used for capabilities that we get from OGP agent domain +void LLAgent::setCapability(const std::string& name, const std::string& url) +{ +#if 0 // OGPX : I think (hope?) we don't need this + // but I'm leaving it here commented out because I'm not quite + // sure why the region capabilities code had it wedged in setCap call + // Maybe the agent domain capabilities will need something like this as well + + if (name == "EventQueueGet") + { + delete mEventPoll; + mEventPoll = NULL; + mEventPoll = new LLEventPoll(url, getHost()); + } + else if (name == "UntrustedSimulatorMessage") + { + LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url)); + } + else +#endif + { + mCapabilities[name] = url; + } +} + +//OGPX : Agent Domain capabilities... this needs to be refactored +std::string LLAgent::getCapability(const std::string& name) const +{ + CapabilityMap::const_iterator iter = mCapabilities.find(name); + if (iter == mCapabilities.end()) + { + return ""; + } + return iter->second; +} +// + +void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity) +{ + const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0)); + LLSimInfo* siminfo; + siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal); + if(siminfo) + { + llinfos << fromname << "'s teleport lure is to " << siminfo->getName() << " (" << maturity << ")" << llendl; + std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(x), S32(y), S32(z)); + std::string msg; + msg = llformat("%s's teleport lure is to %s", fromname.c_str(), url.c_str()); + if(maturity != "") + msg.append(llformat(" (%s)", maturity.c_str())); + LLChat chat(msg); + LLFloaterChat::addChat(chat); + } + else + { + LLAgent::lure_show = TRUE; + LLAgent::lure_name = fromname; + LLAgent::lure_posglobal = posglobal; + LLAgent::lure_global_x = U16(global_x / 256); + LLAgent::lure_global_y = U16(global_y / 256); + LLAgent::lure_x = x; + LLAgent::lure_y = y; + LLAgent::lure_z = z; + LLAgent::lure_maturity = maturity; + LLWorldMapMessage::getInstance()->sendMapBlockRequest(lure_global_x, lure_global_y, lure_global_x, lure_global_y, true); + } +} + +void LLAgent::onFoundLureDestination() +{ + LLAgent::lure_show = FALSE; + LLSimInfo* siminfo; + siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(LLAgent::lure_posglobal); + if(siminfo) + { + llinfos << LLAgent::lure_name << "'s teleport lure is to " << siminfo->getName() << " (" << LLAgent::lure_maturity << ")" << llendl; + std::string url = LLURLDispatcher::buildSLURL(siminfo->getName(), S32(LLAgent::lure_x), S32(LLAgent::lure_y), S32(LLAgent::lure_z)); + std::string msg; + msg = llformat("%s's teleport lure is to %s", LLAgent::lure_name.c_str(), url.c_str()); + if(LLAgent::lure_maturity != "") + msg.append(llformat(" (%s)", LLAgent::lure_maturity.c_str())); + LLChat chat(msg); + LLFloaterChat::addChat(chat); + } + else + llwarns << "Grand scheme failed" << llendl; +} + +// + +// EOF + diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 68c975c48..18f1cbd38 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -410,6 +410,10 @@ public: void setFlying(BOOL fly); void toggleFlying(); + static BOOL getPhantom(); + static void setPhantom(BOOL phantom); + static void togglePhantom(); + // Does this parcel allow you to fly? BOOL canFly(); @@ -785,6 +789,9 @@ public: static int lure_y; static int lure_z; static std::string lure_maturity; + + static LLVector3 exlStartMeasurePoint; + static LLVector3 exlEndMeasurePoint; // S32 mNumPendingQueries; @@ -808,6 +815,8 @@ public: // private: + static BOOL exlPhantom; + bool mbTeleportKeepsLookAt; // try to keep look-at after teleport is complete bool mbAlwaysRun; // should the avatar run by default rather than walk bool mbRunning; // is the avatar trying to run right now diff --git a/indra/newview/llao.cpp b/indra/newview/llao.cpp index 2c91dfa6b..06d5c4370 100644 --- a/indra/newview/llao.cpp +++ b/indra/newview/llao.cpp @@ -8,6 +8,8 @@ #include "llsdserialize.h" #include "llagent.h" #include "llvoavatar.h" +//this is for debugging ;D +//#define AO_DEBUG //static variables std::list LLAO::mStandOverrides; @@ -276,32 +278,32 @@ std::string LLFloaterAO::idstr(LLUUID id) void LLFloaterAO::refresh() { - childSetText("line_walking", idstr(LLAO::mOverrides[LLUUID("6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0")])); - childSetText("line_running", idstr(LLAO::mOverrides[LLUUID("05ddbff8-aaa9-92a1-2b74-8fe77a29b445")])); - childSetText("line_crouchwalk", idstr(LLAO::mOverrides[LLUUID("47f5f6fb-22e5-ae44-f871-73aaaf4a6022")])); - childSetText("line_flying", idstr(LLAO::mOverrides[LLUUID("aec4610c-757f-bc4e-c092-c6e9caf18daf")])); - childSetText("line_turn_left", idstr(LLAO::mOverrides[LLUUID("56e0ba0d-4a9f-7f27-6117-32f2ebbf6135")])); - childSetText("line_turn_right", idstr(LLAO::mOverrides[LLUUID("2d6daa51-3192-6794-8e2e-a15f8338ec30")])); - childSetText("line_jumping", idstr(LLAO::mOverrides[LLUUID("2305bd75-1ca9-b03b-1faa-b176b8a8c49e")])); - childSetText("line_fly_up", idstr(LLAO::mOverrides[LLUUID("62c5de58-cb33-5743-3d07-9e4cd4352864")])); - childSetText("line_crouching", idstr(LLAO::mOverrides[LLUUID("201f3fdf-cb1f-dbec-201f-7333e328ae7c")])); - childSetText("line_fly_down", idstr(LLAO::mOverrides[LLUUID("20f063ea-8306-2562-0b07-5c853b37b31e")])); - mStandsCombo->clearRows(); - for(std::list::iterator itr = LLAO::mStandOverrides.begin();itr != LLAO::mStandOverrides.end(); - itr++) - { - mStandsCombo->add((*itr).asString()); - } - mStandsCombo->setSimple(LLStringExplicit(LLAO::mStandOverrides.back().asString())); - childSetText("line_hover", idstr(LLAO::mOverrides[LLUUID("4ae8016b-31b9-03bb-c401-b1ea941db41d")])); - childSetText("line_sitting", idstr(LLAO::mOverrides[LLUUID("1a5fe8ac-a804-8a5d-7cbd-56bd83184568")])); - childSetText("line_prejump", idstr(LLAO::mOverrides[LLUUID("7a4e87fe-de39-6fcb-6223-024b00893244")])); - childSetText("line_falling", idstr(LLAO::mOverrides[LLUUID("666307d9-a860-572d-6fd4-c3ab8865c094")])); - childSetText("line_stride", idstr(LLAO::mOverrides[LLUUID("1cb562b0-ba21-2202-efb3-30f82cdf9595")])); - childSetText("line_soft_landing", idstr(LLAO::mOverrides[LLUUID("7a17b059-12b2-41b1-570a-186368b6aa6f")])); - childSetText("line_medium_landing", idstr(LLAO::mOverrides[LLUUID("f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57")])); - childSetText("line_hard_landing", idstr(LLAO::mOverrides[LLUUID("3da1d753-028a-5446-24f3-9c9b856d9422")])); - childSetText("line_flying_slow", idstr(LLAO::mOverrides[LLUUID("2b5a38b2-5e00-3a97-a495-4c826bc443e6")])); + childSetText("line_walking", idstr(LLAO::mOverrides[LLUUID("6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0")])); + childSetText("line_running", idstr(LLAO::mOverrides[LLUUID("05ddbff8-aaa9-92a1-2b74-8fe77a29b445")])); + childSetText("line_crouchwalk", idstr(LLAO::mOverrides[LLUUID("47f5f6fb-22e5-ae44-f871-73aaaf4a6022")])); + childSetText("line_flying", idstr(LLAO::mOverrides[LLUUID("aec4610c-757f-bc4e-c092-c6e9caf18daf")])); + childSetText("line_turn_left", idstr(LLAO::mOverrides[LLUUID("56e0ba0d-4a9f-7f27-6117-32f2ebbf6135")])); + childSetText("line_turn_right", idstr(LLAO::mOverrides[LLUUID("2d6daa51-3192-6794-8e2e-a15f8338ec30")])); + childSetText("line_jumping", idstr(LLAO::mOverrides[LLUUID("2305bd75-1ca9-b03b-1faa-b176b8a8c49e")])); + childSetText("line_fly_up", idstr(LLAO::mOverrides[LLUUID("62c5de58-cb33-5743-3d07-9e4cd4352864")])); + childSetText("line_crouching", idstr(LLAO::mOverrides[LLUUID("201f3fdf-cb1f-dbec-201f-7333e328ae7c")])); + childSetText("line_fly_down", idstr(LLAO::mOverrides[LLUUID("20f063ea-8306-2562-0b07-5c853b37b31e")])); + mStandsCombo->clearRows(); + for(std::list::iterator itr = LLAO::mStandOverrides.begin();itr != LLAO::mStandOverrides.end(); + itr++) + { + mStandsCombo->add((*itr).asString()); + } + mStandsCombo->setSimple(LLStringExplicit(LLAO::mStandOverrides.back().asString())); + childSetText("line_hover", idstr(LLAO::mOverrides[LLUUID("4ae8016b-31b9-03bb-c401-b1ea941db41d")])); + childSetText("line_sitting", idstr(LLAO::mOverrides[LLUUID("1a5fe8ac-a804-8a5d-7cbd-56bd83184568")])); + childSetText("line_prejump", idstr(LLAO::mOverrides[LLUUID("7a4e87fe-de39-6fcb-6223-024b00893244")])); + childSetText("line_falling", idstr(LLAO::mOverrides[LLUUID("666307d9-a860-572d-6fd4-c3ab8865c094")])); + childSetText("line_stride", idstr(LLAO::mOverrides[LLUUID("1cb562b0-ba21-2202-efb3-30f82cdf9595")])); + childSetText("line_soft_landing", idstr(LLAO::mOverrides[LLUUID("7a17b059-12b2-41b1-570a-186368b6aa6f")])); + childSetText("line_medium_landing", idstr(LLAO::mOverrides[LLUUID("f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57")])); + childSetText("line_hard_landing", idstr(LLAO::mOverrides[LLUUID("3da1d753-028a-5446-24f3-9c9b856d9422")])); + childSetText("line_flying_slow", idstr(LLAO::mOverrides[LLUUID("2b5a38b2-5e00-3a97-a495-4c826bc443e6")])); childSetText("line_sitting_on_ground", idstr(LLAO::mOverrides[LLUUID("1a2bd58e-87ff-0df8-0b4c-53e047b0bb6e")])); } // static diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c309d0e98..de859ad94 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -101,6 +101,7 @@ #include "llbuildnewviewsscheduler.h" // // The files below handle dependencies from cleanup. +#include "llcalc.h" #include "llkeyframemotion.h" #include "llworldmap.h" #include "llhudmanager.h" @@ -170,6 +171,9 @@ #include "llparcel.h" + + + #include "llinventoryview.h" #include "llcommandlineparser.h" @@ -193,9 +197,16 @@ #include "lllcd.h" #endif + //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. + + + + + + #if LL_DARWIN extern void init_apple_menu(const char* product); #endif // LL_DARWIN @@ -254,6 +265,7 @@ BOOL gDisconnected = FALSE; // Minimap scale in pixels per region + // used to restore texture state after a mode switch LLFrameTimer gRestoreGLTimer; BOOL gRestoreGL = FALSE; @@ -283,6 +295,8 @@ BOOL gLogoutInProgress = FALSE; static std::string gPlaceAvatarCap; //OGPX TODO: should belong elsewhere, as part of the llagent caps? + + //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; @@ -298,7 +312,7 @@ static BOOL gDoDisconnect = FALSE; static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) -const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; +const char* const VIEWER_WINDOW_CLASSNAME = "Ascent"; //---------------------------------------------------------------------------- // File scope definitons @@ -314,6 +328,19 @@ static std::string gHelperURI; LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; + + + + + + + + + + + + + void idle_afk_check() { // check idle timers @@ -323,6 +350,14 @@ void idle_afk_check() } } + + + + + + + + // A callback set in LLAppViewer::init() static void ui_audio_callback(const LLUUID& uuid) { @@ -549,6 +584,7 @@ LLAppViewer::LLAppViewer() : sInstance = this; } + LLAppViewer::~LLAppViewer() { destroyMainloopTimeout(); @@ -596,13 +632,7 @@ bool LLAppViewer::init() // Build a string representing the current version number. // meh - gCurrentVersion = llformat("%s %d.%d.%d (%d)", - gSavedSettings.getString("SpecifiedChannel").c_str(), - gSavedSettings.getU32("SpecifiedVersionMaj"), - gSavedSettings.getU32("SpecifiedVersionMin"), - gSavedSettings.getU32("SpecifiedVersionPatch"), - gSavedSettings.getU32("SpecifiedVersionBuild") ); - // + gCurrentVersion = "1.0.0.0"; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -1973,7 +2003,7 @@ bool LLAppViewer::initConfiguration() mYieldTime = gSavedSettings.getS32("YieldTime"); // XUI:translate - gSecondLife = "Snowglobe"; + gSecondLife = "Ascent"; // Read skin/branding settings if specified. //if (! gDirUtilp->getSkinDir().empty() ) @@ -2198,7 +2228,7 @@ bool LLAppViewer::initWindow() BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth"); // //gViewerWindow = new LLViewerWindow(gWindowTitle, "Second Life", - gViewerWindow = new LLViewerWindow("Inertia", "Second Life", + gViewerWindow = new LLViewerWindow("Ascent", "Second Life", // gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"), gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"), @@ -2328,14 +2358,7 @@ void LLAppViewer::writeSystemInfo() { gDebugInfo["SLLog"] = LLError::logFileName(); - // - //gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); - gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("SpecifiedChannel"); - gDebugInfo["ClientInfo"]["MajorVersion"] = (S32)gSavedSettings.getU32("SpecifiedVersionMaj"); - gDebugInfo["ClientInfo"]["MinorVersion"] = (S32)gSavedSettings.getU32("SpecifiedVersionMin"); - gDebugInfo["ClientInfo"]["PatchVersion"] = (S32)gSavedSettings.getU32("SpecifiedVersionPatch"); - gDebugInfo["ClientInfo"]["BuildVersion"] = (S32)gSavedSettings.getU32("SpecifiedVersionBuild"); - // + gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); @@ -3329,7 +3352,10 @@ void LLAppViewer::idle() { // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); - send_agent_update(TRUE); + if(!gAgent.getPhantom()) + { + send_agent_update(TRUE); + } agent_update_timer.reset(); } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 501c548b1..819756c3a 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -583,10 +583,10 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) case BE_DARKNESS: if( tex ) { - if(tex->getID()== IMG_DEFAULT) - { - return TRUE; - } + if(tex->getID()== IMG_DEFAULT) + { + return TRUE; + } bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); } diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 973d72642..30f14ecf0 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -30,7 +30,7 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ - + #include "llviewerprecompiledheaders.h" #include "llfloaterabout.h" @@ -64,6 +64,11 @@ #include "lldxhardware.h" #endif + + + + + extern LLCPUInfo gSysCPU; extern LLMemoryInfo gSysMemory; extern U32 gPacketsIn; @@ -87,10 +92,8 @@ LLFloaterAbout::LLFloaterAbout() LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml"); // Support for changing product name. - // - std::string title("Aboot "); - title += "Inertia"; - // + std::string title("About "); + title += LLAppViewer::instance()->getSecondLifeTitle(); setTitle(title); LLViewerTextEditor *support_widget = @@ -123,8 +126,8 @@ LLFloaterAbout::LLFloaterAbout() // // gSavedSettings.getString("VersionChannelName").c_str()); gSavedSettings.getString("SpecifiedChannel").c_str()); - support_widget->appendColoredText("Spoofed Identification: " + version, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); // + support_widget->appendColoredText(version, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style); std::string support; diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index d476897c5..55530e355 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -307,6 +307,7 @@ BOOL LLFloaterAnimPreview::postBuild() { mTransactionID.generate(); mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + mAnimPreview = new LLPreviewAnimation(256, 256); // motion will be returned, but it will be in a load-pending state, as this is a new motion diff --git a/indra/newview/llfloaterexploreanimations.cpp b/indra/newview/llfloaterexploreanimations.cpp index 104b999d2..1704e63e3 100644 --- a/indra/newview/llfloaterexploreanimations.cpp +++ b/indra/newview/llfloaterexploreanimations.cpp @@ -51,9 +51,6 @@ LLFloaterExploreAnimations::~LLFloaterExploreAnimations() BOOL LLFloaterExploreAnimations::postBuild(void) { childSetCommitCallback("anim_list", onSelectAnimation, this); - childSetAction("copy_uuid_btn", onClickCopyUUID, this); - childSetAction("open_btn", onClickOpen, this); - childSetAction("jelly_roll_btn", onClickJellyRoll, this); LLRect r = getRect(); mPreviewRect.set(r.getWidth() - 266, r.getHeight() - 25, r.getWidth() - 10, r.getHeight() - 256); update(); @@ -272,49 +269,6 @@ void LLFloaterExploreAnimations::onSelectAnimation(LLUICtrl* ctrl, void* user_da preview->setZoom(2.0f); } -// static -void LLFloaterExploreAnimations::onClickCopyUUID(void* data) -{ - LLFloaterExploreAnimations* floater = (LLFloaterExploreAnimations*)data; - LLScrollListCtrl* list = floater->getChild("anim_list"); - LLUUID selection = list->getSelectedValue().asUUID(); - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(selection.asString())); -} - -void LLFloaterExploreAnimations::onClickOpen(void* data) -{ - LLFloaterExploreAnimations* floater = (LLFloaterExploreAnimations*)data; - LLScrollListCtrl* list = floater->getChild("anim_list"); - LLUUID selection = list->getSelectedValue().asUUID(); - LLUUID item = LLLocalInventory::addItem(selection.asString(), LLAssetType::AT_ANIMATION, selection, true); -} - -void LLFloaterExploreAnimations::onClickJellyRoll(void* data) -{ - std::string hover_text; - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - LLObjectSelection::valid_iterator sel_it = selection->valid_begin(); - LLObjectSelection::valid_iterator sel_end = selection->valid_end(); - for( ; sel_it != sel_end; ++sel_it) - { - LLViewerObject* objectp = (*sel_it)->getObject(); - hover_text = objectp->getDebugText(); - if(hover_text != "") - { - break; - } - } - - LLFloaterExploreAnimations* floater = (LLFloaterExploreAnimations*)data; - LLScrollListCtrl* list = floater->getChild("anim_list"); - LLUUID anim_id = list->getSelectedValue().asUUID(); - - LLFloaterNewLocalInventory* createy = new LLFloaterNewLocalInventory(); - createy->childSetText("name_line", hover_text); - createy->childSetText("asset_id_line", anim_id.asString()); - createy->childSetValue("type_combo", "animatn"); - createy->childSetText("creator_id_line", LLFloaterNewLocalInventory::sLastCreatorId.asString()); -} //----------------------------------------------------------------------------- // handleMouseDown() //----------------------------------------------------------------------------- diff --git a/indra/newview/llfloaterexploreanimations.h b/indra/newview/llfloaterexploreanimations.h index 0ee24b3fb..544ca965c 100644 --- a/indra/newview/llfloaterexploreanimations.h +++ b/indra/newview/llfloaterexploreanimations.h @@ -38,9 +38,6 @@ private: // static stuff! public: static void onSelectAnimation(LLUICtrl* ctrl, void* user_data); - static void onClickCopyUUID(void* data); - static void onClickOpen(void* data); - static void onClickJellyRoll(void* data); BOOL handleMouseDown(S32 x, S32 y, MASK mask); BOOL handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 658de90fe..4fb258aca 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -78,7 +78,6 @@ BOOL LLFloaterExploreSounds::postBuild(void) childSetAction("play_in_world_btn", handle_play_in_world, this); childSetAction("play_ambient_btn", handle_play_ambient, this); childSetAction("look_at_btn", handle_look_at, this); - childSetAction("open_btn", handle_open, this); childSetAction("copy_uuid_btn", handle_copy_uuid, this); childSetAction("stop_btn", handle_stop, this); @@ -393,23 +392,7 @@ void LLFloaterExploreSounds::handle_look_at(void* user_data) // static void LLFloaterExploreSounds::handle_open(void* user_data) { - LLFloaterExploreSounds* floater = (LLFloaterExploreSounds*)user_data; - LLScrollListCtrl* list = floater->getChild("sound_list"); - std::vector selection = list->getAllSelected(); - std::vector::iterator selection_iter = selection.begin(); - std::vector::iterator selection_end = selection.end(); - std::vector asset_list; - for( ; selection_iter != selection_end; ++selection_iter) - { - LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue()); - if(item.mID.isNull()) continue; - // Unique assets only - if(std::find(asset_list.begin(), asset_list.end(), item.mAssetID) == asset_list.end()) - { - asset_list.push_back(item.mAssetID); - LLUUID inv_item = LLLocalInventory::addItem(item.mAssetID.asString(), LLAssetType::AT_SOUND, item.mAssetID, true); - } - } + } // static diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 014a631a5..c5e26afbb 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -60,6 +60,14 @@ #include "lltextbox.h" #include "llvoiceclient.h" +#include "llsdserialize.h" +#include "llfilepicker.h" + +#include "llviewermenufile.h" +#include "llviewermenu.h" +#include "llviewernetwork.h" +#include "hippogridmanager.h" + //Maximum number of people you can select to do an operation on at once. #define MAX_FRIEND_SELECT 20 #define DEFAULT_PERIOD 5.0 @@ -110,7 +118,8 @@ LLPanelFriends::LLPanelFriends() : mObserver(NULL), mShowMaxSelectWarning(TRUE), mAllowRightsChange(TRUE), - mNumRightsChanged(0) + mNumRightsChanged(0), + mNumOnline(0) { mEventTimer.stop(); mObserver = new LLLocalFriendsObserver(this); @@ -193,6 +202,9 @@ BOOL LLPanelFriends::postBuild() childSetCommitCallback("friend_list", onSelectName, this); childSetDoubleClickCallback("friend_list", onClickIM); + getChild("s_num")->setValue("0"); + getChild("f_num")->setValue(llformat("%d", mFriendsList->getItemCount())); + U32 changed_mask = LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE; refreshNames(changed_mask); @@ -202,6 +214,8 @@ BOOL LLPanelFriends::postBuild() childSetAction("pay_btn", onClickPay, this); childSetAction("add_btn", onClickAddFriend, this); childSetAction("remove_btn", onClickRemove, this); + childSetAction("export_btn", onClickExport, this); + childSetAction("import_btn", onClickImport, this); setDefaultBtn("im_btn"); @@ -238,14 +252,16 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS]; online_status_column["column"] = "icon_online_status"; online_status_column["type"] = "icon"; - + if (isOnline) { + mNumOnline++; friend_column["font-style"] = "BOLD"; online_status_column["value"] = "icon_avatar_online.tga"; } else if(isOnlineSIP) { + mNumOnline++; friend_column["font-style"] = "BOLD"; online_status_column["value"] = ONLINE_SIP_ICON_NAME; } @@ -264,6 +280,20 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) edit_my_object_column["column"] = "icon_edit_mine"; edit_my_object_column["type"] = "checkbox"; edit_my_object_column["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); + + LLSD& see_online_them_column = element["columns"][LIST_VISIBLE_ONLINE_THEIRS]; + see_online_them_column["column"] = "icon_visible_online_theirs"; + see_online_them_column["type"] = "checkbox"; + see_online_them_column["enabled"] = ""; + see_online_them_column["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); + + + + LLSD& mapstalk_them_column = element["columns"][LIST_VISIBLE_MAP_THEIRS]; + mapstalk_them_column["column"] = "icon_visible_map_theirs"; + mapstalk_them_column["type"] = "checkbox"; + mapstalk_them_column["enabled"] = ""; + mapstalk_them_column["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION); LLSD& edit_their_object_column = element["columns"][LIST_EDIT_THEIRS]; edit_their_object_column["column"] = "icon_edit_theirs"; @@ -298,12 +328,18 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh if(isOnline) { + mNumOnline++; statusIcon = "icon_avatar_online.tga"; } else if(isOnlineSIP) { + mNumOnline++; statusIcon = ONLINE_SIP_ICON_NAME; } + else + { + mNumOnline--; + } itemp->getColumn(LIST_ONLINE_STATUS)->setValue(statusIcon); @@ -313,6 +349,13 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)); itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)); itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)); + //Notes in the original code imply this may not always work. Good to know. -HgB + itemp->getColumn(LIST_VISIBLE_ONLINE_THEIRS)->setValue(info->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS)); + + + itemp->getColumn(LIST_VISIBLE_MAP_THEIRS)->setValue(info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)); + itemp->getColumn(LIST_EDIT_THEIRS)->setValue(info->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)); + S32 change_generation = have_name ? info->getChangeSerialNum() : -1; itemp->getColumn(LIST_FRIEND_UPDATE_GEN)->setValue(change_generation); @@ -325,9 +368,10 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh void LLPanelFriends::refreshRightsChangeList() { - LLDynamicArray friends = getSelectedIDs(); - S32 num_selected = friends.size(); + LLDynamicArray friends = getSelectedIDs(); + + S32 num_selected = friends.size(); bool can_offer_teleport = num_selected >= 1; bool selected_friends_online = true; @@ -347,7 +391,6 @@ void LLPanelFriends::refreshRightsChangeList() { processing_label->setVisible(false); } - const LLRelationship* friend_status = NULL; for(LLDynamicArray::iterator itr = friends.begin(); itr != friends.end(); ++itr) { @@ -365,6 +408,11 @@ void LLPanelFriends::refreshRightsChangeList() can_offer_teleport = false; } } + + //Stuff for the online/total/select counts. + + getChild("s_num")->setValue(llformat("%d", num_selected)); + getChild("f_num")->setValue(llformat("%d / %d", mNumOnline, mFriendsList->getItemCount())); if (num_selected == 0) // nothing selected { @@ -426,6 +474,7 @@ void LLPanelFriends::refreshNames(U32 changed_mask) BOOL LLPanelFriends::refreshNamesSync(const LLAvatarTracker::buddy_map_t & all_buddies) { + mNumOnline = 0; mFriendsList->deleteAllItems(); BOOL have_names = TRUE; @@ -441,6 +490,7 @@ BOOL LLPanelFriends::refreshNamesSync(const LLAvatarTracker::buddy_map_t & all_b BOOL LLPanelFriends::refreshNamesPresence(const LLAvatarTracker::buddy_map_t & all_buddies) { + std::vector items = mFriendsList->getAllData(); std::sort(items.begin(), items.end(), SortFriendsByID()); @@ -512,7 +562,6 @@ void LLPanelFriends::refreshUI() childSetText("friend_name_label", LLStringUtil::null); } - //Options that can only be performed with one friend selected childSetEnabled("profile_btn", single_selected && !multiple_selected); childSetEnabled("pay_btn", single_selected && !multiple_selected); @@ -737,6 +786,183 @@ void LLPanelFriends::onClickRemove(void* user_data) } } +void LLPanelFriends::onClickExport(void* user_data) +{ + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + std::string agn; + gAgent.getName(agn); + std::string filename = agn+".friendlist"; + LLFilePicker& picker = LLFilePicker::instance(); + if(!picker.getSaveFile( LLFilePicker::FFSAVE_ALL, filename ) ) + { + // User canceled save. + return; + } + filename = picker.getFirstFile(); + std::vector selected = panelp->mFriendsList->getAllData();//->getAllSelected(); + + LLSD llsd; + //U32 count = 0; + //std::string friendlist; + for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) + { + LLSD fraind; + std::string friend_name = (*itr)->getColumn(LIST_FRIEND_NAME)->getValue().asString(); + std::string friend_uuid = (*itr)->getUUID().asString(); + bool show_online_status = (*itr)->getColumn(LIST_VISIBLE_ONLINE)->getValue().asBoolean(); + bool show_map_location = (*itr)->getColumn(LIST_VISIBLE_MAP)->getValue().asBoolean(); + bool allow_modify_objects = (*itr)->getColumn(LIST_EDIT_MINE)->getValue().asBoolean(); + fraind["name"] = friend_name; + fraind["see_online"] = show_online_status; + fraind["can_map"] = show_map_location; + fraind["can_mod"] = allow_modify_objects; + //friendlist += friend_name+"|"+friend_uuid+"|"+show_online_status+"|"+show_map_location+"|"+allow_modify_objects+"\n"; + llsd[friend_uuid] = fraind; + //count += 1; + } + + std::string grid_uri = gHippoGridManager->getConnectedGrid()->getLoginUri(); + //LLStringUtil::toLower(uris[0]); + llsd["GRID"] = grid_uri; + + llofstream export_file; + export_file.open(filename); + LLSDSerialize::toPrettyXML(llsd, export_file); + export_file.close(); +} + +bool LLPanelFriends::merging; + +void LLPanelFriends::onClickImport(void* user_data) +//THIS CODE IS DESIGNED SO THAT EXP/IMP BETWEEN GRIDS WILL FAIL +//because assuming someone having the same name on another grid is the same person is generally a bad idea +//i might add the option to query the user as to intelligently detecting matching names on a alternative grid +// jcool410 +{ + //LLPanelFriends* panelp = (LLPanelFriends*)user_data; + //is_agent_friend( + + const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ALL); + + if (filename.empty()) + return; + + llifstream importer(filename); + LLSD data; + LLSDSerialize::fromXMLDocument(data, importer); + if(data.has("GRID")) + { + std::string grid = gHippoGridManager->getConnectedGrid()->getLoginUri(); + if(grid != data["GRID"])return; + data.erase("GRID"); + } + +#if LL_WINDOWS + std::string file = filename.substr(filename.find_last_of("\\")+1); +#else + std::string file = filename.substr(filename.find_last_of("/")+1); +#endif + + std::string importstate = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "friendimportstate.dat"); + + llifstream stateload(importstate); + LLSD importstatellsd; + LLSDSerialize::fromXMLDocument(importstatellsd, stateload); + + + //LLMessageSystem* msg = gMessageSystem; + LLSD newdata; + + LLSD::map_const_iterator iter; + for(iter = data.beginMap(); iter != data.endMap(); ++iter) + {//first= var second = val + LLSD content = iter->second; + if(!content.has("name"))continue; + if(!content.has("see_online"))continue; + if(!content.has("can_map"))continue; + if(!content.has("can_mod"))continue; + + LLUUID agent_id = LLUUID(iter->first); + if(merging && importstatellsd.has(agent_id.asString()))continue;//dont need to request what weve already requested from another list import and have not got a reply yet + + std::string agent_name = content["name"]; + if(!is_agent_friend(agent_id))//dont need to request what we have + { + if(merging)importstatellsd[agent_id.asString()] = content;//MERGEEEE + requestFriendship(agent_id, agent_name, "Imported from "+file); + newdata[iter->first] = iter->second; + }else + { + //data.erase(iter->first); + //--iter;//god help us all + } + } + data = newdata; + newdata = LLSD(); + + if(!merging) + { + merging = true;//this hack is to support importing multiple account lists without spamming users but considering LLs fail in forcing silent declines + importstatellsd = data; + } + + llofstream export_file; + export_file.open(importstate); + LLSDSerialize::toPrettyXML(importstatellsd, export_file); + export_file.close(); +} + +void LLPanelFriends::FriendImportState(LLUUID id, bool accepted) +{ + std::string importstate = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "friendimportstate.dat"); + if(LLFile::isfile(importstate)) + { + llifstream importer(importstate); + LLSD data; + LLSDSerialize::fromXMLDocument(data, importer); + + if(!data.has(id.asString()))return; + + LLSD user = data[id.asString()]; + if(accepted) + { + BOOL can_map = user["can_map"].asBoolean(); + BOOL can_mod = user["can_mod"].asBoolean(); + BOOL see_online = user["see_online"].asBoolean(); + S32 rights = 0; + if(can_map)rights |= LLRelationship::GRANT_MAP_LOCATION; + if(can_mod)rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + if(see_online)rights |= LLRelationship::GRANT_ONLINE_STATUS; + if(is_agent_friend(id))//is this legit shit yo + { + const LLRelationship* friend_status = LLAvatarTracker::instance().getBuddyInfo(id); + if(friend_status) + { + S32 tr = friend_status->getRightsGrantedTo(); + if(tr != rights) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_GrantUserRights); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgent.getID()); + msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Rights); + msg->addUUID(_PREHASH_AgentRelated, id); + msg->addS32(_PREHASH_RelatedRights, rights); + gAgent.sendReliableMessage(); + } + } + } + } + data.erase(id.asString());//if they declined then we need to forget about it, if they accepted it is done + + llofstream export_file; + export_file.open(importstate); + LLSDSerialize::toPrettyXML(data, export_file); + export_file.close(); + } +} + // static void LLPanelFriends::onClickOfferTeleport(void* user_data) { diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index a5c94ee48..780e0e1b3 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -92,6 +92,8 @@ private: LIST_VISIBLE_ONLINE, LIST_VISIBLE_MAP, LIST_EDIT_MINE, + LIST_VISIBLE_ONLINE_THEIRS, + LIST_VISIBLE_MAP_THEIRS, LIST_EDIT_THEIRS, LIST_FRIEND_UPDATE_GEN }; @@ -129,7 +131,11 @@ private: static void onClickProfile(void* user_data); static void onClickAddFriend(void* user_data); static void onClickRemove(void* user_data); - + static void onClickExport(void* user_data); + static void onClickImport(void* user_data); +public: + static void FriendImportState(LLUUID id, bool accepted); +private: static void onClickOfferTeleport(void* user_data); static void onClickPay(void* user_data); @@ -147,6 +153,8 @@ private: BOOL mShowMaxSelectWarning; BOOL mAllowRightsChange; S32 mNumRightsChanged; + S32 mNumOnline; + static bool merging; }; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 96e26cd64..649addfc1 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -76,10 +76,16 @@ #include "llviewerwindow.h" #include "llviewercontrol.h" #include "roles_constants.h" +#include "llworld.h" + + + + static std::string OWNER_ONLINE = "0"; static std::string OWNER_OFFLINE = "1"; static std::string OWNER_GROUP = "2"; +static std::string OWNER_INSIM = "4"; // constants used in callbacks below - syntactic sugar. static const BOOL BUY_GROUP_LAND = TRUE; @@ -278,7 +284,6 @@ void* LLFloaterLand::createPanelLandOptions(void* data) return self->mPanelOptions; } - // static void* LLFloaterLand::createPanelLandAudio(void* data) { @@ -347,7 +352,8 @@ BOOL LLPanelLandGeneral::postBuild() mBtnSetGroup = getChild("Set..."); mBtnSetGroup->setClickedCallback(onClickSetGroup, this); - + getChild("group_profile")->setClickedCallback(onClickInfoGroup, this); + mCheckDeedToGroup = getChild( "check deed"); childSetCommitCallback("check deed", onCommitAny, this); @@ -785,6 +791,16 @@ void LLPanelLandGeneral::onClickSetGroup(void* userdata) } } +// static +void LLPanelLandGeneral::onClickInfoGroup(void* userdata) +{ + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)userdata; + LLParcel* parcel = panelp->mParcel->getParcel(); + if (!parcel) return; + LLUUID id = parcel->getGroupID(); + if(id.notNull())LLFloaterGroupInfo::showFromUUID(parcel->getGroupID()); +} + // static void LLPanelLandGeneral::onClickProfile(void* data) { @@ -836,6 +852,12 @@ void LLPanelLandGeneral::onClickBuyLand(void* data) LLViewerParcelMgr::getInstance()->startBuyLand(*for_group); } + + + + + + BOOL LLPanelLandGeneral::enableDeedToGroup(void* data) { LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; @@ -1038,6 +1060,7 @@ BOOL LLPanelLandObjects::postBuild() mBtnReturnOwnerList->setClickedCallback(onClickReturnOwnerList, this); mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga"); + mIconAvatarInSim = LLUIImageList::getInstance()->getUIImage("ff_visible_map.tga"); mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga"); mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga"); @@ -1465,6 +1488,11 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo self->mFirstReply = FALSE; } + LLVector3d mypos = gAgent.getPositionGlobal(); + std::vector avatar_ids; + std::vector positions; + LLWorld::instance().getAvatars(&avatar_ids, &positions, mypos, F32_MAX); + for(S32 i = 0; i < rows; ++i) { msg->getUUIDFast(_PREHASH_Data, _PREHASH_OwnerID, owner_id, i); @@ -1480,12 +1508,19 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo continue; } + BOOL in_sim = (std::find(avatar_ids.begin(), avatar_ids.end(), owner_id) != avatar_ids.end()); + LLScrollListItem *row = new LLScrollListItem( TRUE, NULL, owner_id); if (is_group_owned) { row->addColumn(self->mIconGroup); row->addColumn(OWNER_GROUP, FONT); } + else if (in_sim) + { + row->addColumn(self->mIconAvatarInSim); + row->addColumn(OWNER_INSIM, FONT); + } else if (is_online) { row->addColumn(self->mIconAvatarOnline); diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 3f3d8e50d..d140a1d93 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -86,6 +86,10 @@ public: virtual void onOpen(); virtual BOOL postBuild(); + + + + protected: // Does its own instance management, so clients not allowed @@ -104,7 +108,6 @@ protected: static void* createPanelLandAccess(void* data); static void* createPanelLandBan(void* data); - protected: static LLParcelSelectionObserver* sObserver; static S32 sLastTab; @@ -142,6 +145,7 @@ public: void setGroup(const LLUUID& group_id); static void onClickProfile(void*); static void onClickSetGroup(void*); + static void onClickInfoGroup(void*); static void cbGroupID(LLUUID group_id, void* userdata); static BOOL enableDeedToGroup(void*); static void onClickDeed(void*); @@ -289,6 +293,7 @@ protected: LLNameListCtrl *mOwnerList; LLPointer mIconAvatarOnline; + LLPointer mIconAvatarInSim; LLPointer mIconAvatarOffline; LLPointer mIconGroup; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index df2505cfe..879319763 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -65,7 +65,8 @@ #include "llprefschat.h" #include "llprefsvoice.h" #include "llprefsim.h" -#include "hbprefsinert.h" +#include "ascentprefssys.h" +#include "ascentprefsvan.h" #include "llresizehandle.h" #include "llresmgr.h" #include "llassetstorage.h" @@ -134,7 +135,8 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def mMsgPanel(NULL), mSkinsPanel(NULL), mLCDPanel(NULL), - mPrefsInert(NULL) + mPrefsAscentSys(NULL), + mPrefsAscentVan(NULL) { mGeneralPanel = new LLPanelGeneral(); mTabContainer->addTabPanel(mGeneralPanel, mGeneralPanel->getLabel(), FALSE, onTabChanged, mTabContainer); @@ -194,9 +196,13 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def mTabContainer->addTabPanel(mSkinsPanel, mSkinsPanel->getLabel(), FALSE, onTabChanged, mTabContainer); mSkinsPanel->setDefaultBtn(default_btn); - mPrefsInert = new LLPrefsInert(); - mTabContainer->addTabPanel(mPrefsInert->getPanel(), mPrefsInert->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer); - mPrefsInert->getPanel()->setDefaultBtn(default_btn); + mPrefsAscentSys = new LLPrefsAscentSys(); + mTabContainer->addTabPanel(mPrefsAscentSys->getPanel(), mPrefsAscentSys->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer); + mPrefsAscentSys->getPanel()->setDefaultBtn(default_btn); + + mPrefsAscentVan = new LLPrefsAscentVan(); + mTabContainer->addTabPanel(mPrefsAscentVan->getPanel(), mPrefsAscentVan->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer); + mPrefsAscentVan->getPanel()->setDefaultBtn(default_btn); if (!mTabContainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) { @@ -257,12 +263,16 @@ LLPreferenceCore::~LLPreferenceCore() delete mSkinsPanel; mSkinsPanel = NULL; } - if (mPrefsInert) + if (mPrefsAscentSys) { - delete mPrefsInert; - mPrefsInert = NULL; + delete mPrefsAscentSys; + mPrefsAscentSys = NULL; + } + if (mPrefsAscentVan) + { + delete mPrefsAscentVan; + mPrefsAscentVan = NULL; } - } @@ -278,7 +288,8 @@ void LLPreferenceCore::apply() mPrefsIM->apply(); mMsgPanel->apply(); mSkinsPanel->apply(); - mPrefsInert->apply(); + mPrefsAscentSys->apply(); + mPrefsAscentVan->apply(); // hardware menu apply LLFloaterHardwareSettings::instance()->apply(); @@ -307,7 +318,8 @@ void LLPreferenceCore::cancel() mPrefsIM->cancel(); mMsgPanel->cancel(); mSkinsPanel->cancel(); - mPrefsInert->cancel(); + mPrefsAscentSys->cancel(); + mPrefsAscentVan->cancel(); // cancel hardware menu LLFloaterHardwareSettings::instance()->cancel(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index b24a03853..dcfc6d79e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -57,7 +57,8 @@ class LLPrefsIM; class LLPanelMsgs; class LLPanelSkins; class LLScrollListCtrl; -class LLPrefsInert; +class LLPrefsAscentSys; +class LLPrefsAscentVan; class LLPreferenceCore { @@ -93,7 +94,8 @@ private: LLPanelWeb *mWebPanel; LLPanelMsgs *mMsgPanel; LLPanelLCD *mLCDPanel; - LLPrefsInert *mPrefsInert; + LLPrefsAscentSys *mPrefsAscentSys; + LLPrefsAscentVan *mPrefsAscentVan; }; // Floater to control preferences (display, audio, bandwidth, general. diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index 044d24280..bb7cf85a7 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -59,10 +59,9 @@ #include "lluictrlfactory.h" -// -#include "llclipboard.h" -// - +// +#include "llclipboard.h" +// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLPropertiesObserver @@ -160,9 +159,9 @@ LLFloaterProperties::LLFloaterProperties(const std::string& name, const LLRect& mItemID(item_id), mObjectID(object_id), mDirty(TRUE) - // - , mExpanded(FALSE) - // + // + , mExpanded(FALSE) + // { LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml"); @@ -201,13 +200,13 @@ LLFloaterProperties::LLFloaterProperties(const std::string& name, const LLRect& childSetCommitCallback("RadioSaleType",&onCommitSaleType, this); // "Price" label for edit childSetCommitCallback("EditPrice",&onCommitSaleInfo, this); - // - childSetAction("more_btn", &onClickMore, this); - childSetAction("less_btn", &onClickLess, this); - childSetAction("copy_btn", &onClickCopy, this); - childSetAction("update_btn", &onClickUpdate, this); - setExpanded(mExpanded); - // + // + childSetAction("more_btn", &onClickMore, this); + childSetAction("less_btn", &onClickLess, this); + childSetAction("copy_btn", &onClickCopy, this); + childSetAction("update_btn", &onClickUpdate, this); + setExpanded(mExpanded); + // // The UI has been built, now fill in all the values refresh(); } @@ -294,28 +293,28 @@ void LLFloaterProperties::draw() void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) { - // - childSetText("EditItemID", item->getUUID().asString()); - childSetText("EditFolderID", item->getParentUUID().asString()); - childSetText("EditGroup", item->getPermissions().getGroup().asString()); - childSetText("EditAssetID", item->getAssetUUID().asString()); - - std::string type_str = LLAssetType::lookup(item->getType()); - if(type_str.c_str() == NULL) type_str = llformat("%d", item->getType()); - childSetText("EditType", type_str); - - std::string invtype_str = LLInventoryType::lookup(item->getInventoryType()); - if(invtype_str.c_str() == NULL) invtype_str = llformat("%d", item->getInventoryType()); - childSetText("EditInvType", invtype_str); - childSetText("EditFlags", llformat("%d", item->getFlags())); - - std::ostringstream strm; - item->exportLegacyStream(strm, TRUE); - std::string str(strm.str()); - LLStringUtil::replaceTabsWithSpaces(str, 4); - childSetText("item_text", str); - // - + // + childSetText("EditItemID", item->getUUID().asString()); + childSetText("EditFolderID", item->getParentUUID().asString()); + childSetText("EditGroup", item->getPermissions().getGroup().asString()); + childSetText("EditAssetID", item->getAssetUUID().asString()); + + std::string type_str = LLAssetType::lookup(item->getType()); + if(type_str.c_str() == NULL) type_str = llformat("%d", item->getType()); + childSetText("EditType", type_str); + + std::string invtype_str = LLInventoryType::lookup(item->getInventoryType()); + if(invtype_str.c_str() == NULL) invtype_str = llformat("%d", item->getInventoryType()); + childSetText("EditInvType", invtype_str); + childSetText("EditFlags", llformat("%d", item->getFlags())); + + std::ostringstream strm; + item->exportLegacyStream(strm, TRUE); + std::string str(strm.str()); + LLStringUtil::replaceTabsWithSpaces(str, 4); + childSetText("item_text", str); + // + //////////////////////// // PERMISSIONS LOOKUP // //////////////////////// @@ -980,163 +979,163 @@ void LLFloaterProperties::closeByID(const LLUUID& item_id, const LLUUID &object_ } } -// -void LLFloaterProperties::onClickMore(void* user_data) -{ - LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; - if(floaterp) - { - LLMultiProperties* host = (LLMultiProperties*)floaterp->getHost(); - if(host) - host->setExpanded(TRUE); - else - floaterp->setExpanded(TRUE); - } -} - -void LLFloaterProperties::onClickLess(void* user_data) -{ - LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; - if(floaterp) - { - LLMultiProperties* host = (LLMultiProperties*)floaterp->getHost(); - if(host) - host->setExpanded(FALSE); - else - floaterp->setExpanded(FALSE); - } -} - -void LLFloaterProperties::setExpanded(BOOL expanded) -{ - mExpanded = expanded; - LLRect rect = getRect(); - if(expanded) - rect.setOriginAndSize(rect.mLeft, rect.mBottom, 800, rect.getHeight()); - else - rect.setOriginAndSize(rect.mLeft, rect.mBottom, 350, rect.getHeight()); - setRect(rect); - childSetVisible("more_btn", !mExpanded); - childSetVisible("less_btn", mExpanded); - childSetVisible("item_text", mExpanded); - childSetVisible("copy_btn", mExpanded); - childSetVisible("update_btn", mExpanded); - if(getHost()) - setCanTearOff(!expanded); // idk why it comes out ugly if expanded -} - -// static -void LLFloaterProperties::onClickCopy(void* user_data) -{ - LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; - if(floaterp) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->findItem(); - if(item) - { - std::string str(floaterp->childGetValue("item_text").asString()); - std::string::size_type pos; - while((pos = str.find(" ")) != std::string::npos) - { - str.replace(pos, 4, "\t"); - } - - std::istringstream strm(str); - LLViewerInventoryItem* temp = new LLViewerInventoryItem(); - temp->importLegacyStream(strm); - std::ostringstream strm2; - temp->exportLegacyStream(strm2, TRUE); - LLWString wstr(utf8str_to_wstring(strm2.str())); - - gClipboard.copyFromSubstring(wstr, 0, wstr.length()); - - //delete temp; - } - } -} - -// static -void LLFloaterProperties::onClickUpdate(void* user_data) -{ - LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; - if(floaterp) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->findItem(); - if(item) - { - std::string str(floaterp->childGetValue("item_text").asString()); - std::string::size_type pos; - while((pos = str.find(" ")) != std::string::npos) - { - str.replace(pos, 4, "\t"); - } - - std::istringstream strm(str); - item->importLegacyStream(strm); - - if(floaterp->mObjectID.isNull()) - { - // This is in the agent's inventory. - item->updateServer(FALSE); - gInventory.updateItem(item); - gInventory.notifyObservers(); - - item->setComplete(FALSE); - item->fetchFromServer(); - } - else - { - // This is in an object's contents. - LLViewerObject* object = gObjectList.findObject(floaterp->mObjectID); - if(object) - { - object->updateInventory( - item, - TASK_INVENTORY_ITEM_KEY, - false); - object->fetchInventoryFromServer(); - } - } - } - } -} -// - +// +void LLFloaterProperties::onClickMore(void* user_data) +{ + LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; + if(floaterp) + { + LLMultiProperties* host = (LLMultiProperties*)floaterp->getHost(); + if(host) + host->setExpanded(TRUE); + else + floaterp->setExpanded(TRUE); + } +} + +void LLFloaterProperties::onClickLess(void* user_data) +{ + LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; + if(floaterp) + { + LLMultiProperties* host = (LLMultiProperties*)floaterp->getHost(); + if(host) + host->setExpanded(FALSE); + else + floaterp->setExpanded(FALSE); + } +} + +void LLFloaterProperties::setExpanded(BOOL expanded) +{ + mExpanded = expanded; + LLRect rect = getRect(); + if(expanded) + rect.setOriginAndSize(rect.mLeft, rect.mBottom, 800, rect.getHeight()); + else + rect.setOriginAndSize(rect.mLeft, rect.mBottom, 350, rect.getHeight()); + setRect(rect); + childSetVisible("more_btn", !mExpanded); + childSetVisible("less_btn", mExpanded); + childSetVisible("item_text", mExpanded); + childSetVisible("copy_btn", mExpanded); + childSetVisible("update_btn", mExpanded); + if(getHost()) + setCanTearOff(!expanded); // idk why it comes out ugly if expanded +} + +// static +void LLFloaterProperties::onClickCopy(void* user_data) +{ + LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; + if(floaterp) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->findItem(); + if(item) + { + std::string str(floaterp->childGetValue("item_text").asString()); + std::string::size_type pos; + while((pos = str.find(" ")) != std::string::npos) + { + str.replace(pos, 4, "\t"); + } + + std::istringstream strm(str); + LLViewerInventoryItem* temp = new LLViewerInventoryItem(); + temp->importLegacyStream(strm); + std::ostringstream strm2; + temp->exportLegacyStream(strm2, TRUE); + LLWString wstr(utf8str_to_wstring(strm2.str())); + + gClipboard.copyFromSubstring(wstr, 0, wstr.length()); + + //delete temp; + } + } +} + +// static +void LLFloaterProperties::onClickUpdate(void* user_data) +{ + LLFloaterProperties* floaterp = (LLFloaterProperties*)user_data; + if(floaterp) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->findItem(); + if(item) + { + std::string str(floaterp->childGetValue("item_text").asString()); + std::string::size_type pos; + while((pos = str.find(" ")) != std::string::npos) + { + str.replace(pos, 4, "\t"); + } + + std::istringstream strm(str); + item->importLegacyStream(strm); + + if(floaterp->mObjectID.isNull()) + { + // This is in the agent's inventory. + item->updateServer(FALSE); + gInventory.updateItem(item); + gInventory.notifyObservers(); + + item->setComplete(FALSE); + item->fetchFromServer(); + } + else + { + // This is in an object's contents. + LLViewerObject* object = gObjectList.findObject(floaterp->mObjectID); + if(object) + { + object->updateInventory( + item, + TASK_INVENTORY_ITEM_KEY, + false); + object->fetchInventoryFromServer(); + } + } + } + } +} +// + ///---------------------------------------------------------------------------- /// LLMultiProperties ///---------------------------------------------------------------------------- LLMultiProperties::LLMultiProperties(const LLRect &rect) : LLMultiFloater(std::string("Properties"), rect) -// -, mExpanded(FALSE) -// +// +, mExpanded(FALSE) +// { } -void LLMultiProperties::setExpanded(BOOL expanded) -{ - mExpanded = expanded; - LLRect rect = getRect(); - LLRect tab_rect = mTabContainer->getRect(); - if(expanded) - { - rect.setOriginAndSize(rect.mLeft, rect.mBottom, 800, rect.getHeight()); - tab_rect.setOriginAndSize(tab_rect.mLeft, tab_rect.mBottom, 800, tab_rect.getHeight()); - } - else - { - rect.setOriginAndSize(rect.mLeft, rect.mBottom, 350, rect.getHeight()); - tab_rect.setOriginAndSize(tab_rect.mLeft, tab_rect.mBottom, 350, tab_rect.getHeight()); - } - setRect(rect); - mTabContainer->setRect(tab_rect); - for (S32 i = 0; i < mTabContainer->getTabCount(); i++) - { - LLFloaterProperties* floaterp = (LLFloaterProperties*)mTabContainer->getPanelByIndex(i); - floaterp->setExpanded(expanded); - } -} - +void LLMultiProperties::setExpanded(BOOL expanded) +{ + mExpanded = expanded; + LLRect rect = getRect(); + LLRect tab_rect = mTabContainer->getRect(); + if(expanded) + { + rect.setOriginAndSize(rect.mLeft, rect.mBottom, 800, rect.getHeight()); + tab_rect.setOriginAndSize(tab_rect.mLeft, tab_rect.mBottom, 800, tab_rect.getHeight()); + } + else + { + rect.setOriginAndSize(rect.mLeft, rect.mBottom, 350, rect.getHeight()); + tab_rect.setOriginAndSize(tab_rect.mLeft, tab_rect.mBottom, 350, tab_rect.getHeight()); + } + setRect(rect); + mTabContainer->setRect(tab_rect); + for (S32 i = 0; i < mTabContainer->getTabCount(); i++) + { + LLFloaterProperties* floaterp = (LLFloaterProperties*)mTabContainer->getPanelByIndex(i); + floaterp->setExpanded(expanded); + } +} + ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 14ca2e97a..c9475bc7a 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -81,6 +81,7 @@ #include "llviewerjoystick.h" #include "lluictrlfactory.h" + // Globals LLFloaterTools *gFloaterTools = NULL; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 7550a1245..73b2d0d98 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -162,6 +162,7 @@ LLFolderViewItem::LLFolderViewItem( const std::string& name, LLUIImagePtr icon, mIcon(icon), mHasVisibleChildren(FALSE), mIndentation(0), + mNumDescendantsSelected(0), mFiltered(FALSE), mLastFilterGeneration(-1), mStringMatchOffset(std::string::npos), @@ -281,19 +282,23 @@ void LLFolderViewItem::refreshFromListener() { if(mListener) { - mLabel = mListener->getDisplayName(); - setIcon(mListener->getIcon()); - time_t creation_date = mListener->getCreationDate(); - if (mCreationDate != creation_date) - { - mCreationDate = mListener->getCreationDate(); - dirtyFilter(); - } - mLabelStyle = mListener->getLabelStyle(); - mLabelSuffix = mListener->getLabelSuffix(); - + //Super crazy hack to build the creator search label - RK LLInventoryItem* item = gInventory.getItem(mListener->getUUID()); - + std::string creator_name; + if(item) + { + if(item->getCreatorUUID().notNull()) + { + gCacheName->getFullName(item->getCreatorUUID(), creator_name); + } + } + mLabelCreator = creator_name; + /*if(creator_name == "(Loading...)") + mLabelCreator = ""; + else + mLabelCreator = creator_name;*/ + + //Label for desc search std::string desc; if (item) { @@ -303,18 +308,23 @@ void LLFolderViewItem::refreshFromListener() LLStringUtil::toUpper(desc); } } - mSearchableLabelDesc = desc; + mLabelDesc = desc; - std::string creator_name; - if (item) + //Label for name search + mLabel = mListener->getDisplayName(); + + //Build label for combined search - RK + mLabelAll = mLabel + " " + mLabelCreator + " " + mLabelDesc; + + setIcon(mListener->getIcon()); + time_t creation_date = mListener->getCreationDate(); + if (mCreationDate != creation_date) { - if (item->getCreatorUUID().notNull()) - { - gCacheName->getFullName(item->getCreatorUUID(), creator_name); - LLStringUtil::toUpper(creator_name); - } + mCreationDate = mListener->getCreationDate(); + dirtyFilter(); } - mSearchableLabelCreator = creator_name; + mLabelStyle = mListener->getLabelStyle(); + mLabelSuffix = mListener->getLabelSuffix(); } } @@ -323,12 +333,32 @@ void LLFolderViewItem::refresh() refreshFromListener(); std::string searchable_label(mLabel); - searchable_label.append(mLabelSuffix); - LLStringUtil::toUpper(searchable_label); + std::string searchable_label_creator(mLabelCreator); + std::string searchable_label_desc(mLabelDesc); + std::string searchable_label_all(mLabelAll); - if (mSearchableLabel.compare(searchable_label)) + //add the (no modify), (no transfer) etc stuff to each label. + searchable_label.append(mLabelSuffix); + searchable_label_creator.append(mLabelSuffix); + searchable_label_desc.append(mLabelSuffix); + searchable_label_all.append(mLabelSuffix); + + //all labels need to be uppercase. + LLStringUtil::toUpper(searchable_label); + LLStringUtil::toUpper(searchable_label_creator); + LLStringUtil::toUpper(searchable_label_desc); + LLStringUtil::toUpper(searchable_label_all); + + if (mSearchableLabel.compare(searchable_label) || + mSearchableLabelCreator.compare(searchable_label_creator) || + mSearchableLabelDesc.compare(searchable_label_desc) || + mSearchableLabelAll.compare(searchable_label_all)) { mSearchableLabel.assign(searchable_label); + mSearchableLabelCreator.assign(searchable_label_creator); + mSearchableLabelDesc.assign(searchable_label_desc); + mSearchableLabelAll.assign(searchable_label_all); + dirtyFilter(); // some part of label has changed, so overall width has potentially changed if (mParentFolder) @@ -490,16 +520,9 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) { - if (selection == this && mIsSelected != selected) + if(selection == this && mIsSelected != selected) { - if (mIsSelected) - { - deselectItem(); - } - else - { - selectItem(); - } + mIsSelected = selected; if(mListener) { mListener->selectItem(); @@ -509,6 +532,22 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte return FALSE; } +void LLFolderViewItem::recursiveDeselect(BOOL deselect_self) +{ + if (mIsSelected && deselect_self) + { + mIsSelected = FALSE; + + // update ancestors' count of selected descendents + LLFolderViewFolder* parent_folder = getParentFolder(); + while(parent_folder) + { + parent_folder->mNumDescendantsSelected--; + parent_folder = parent_folder->getParentFolder(); + } + } +} + void LLFolderViewItem::deselectItem(void) { llassert(mIsSelected); @@ -611,6 +650,16 @@ void LLFolderViewItem::preview( void ) } } + + + + + + + + + + void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) @@ -628,31 +677,20 @@ void LLFolderViewItem::rename(const std::string& new_name) } } -std::string& LLFolderViewItem::getSearchableLabel() +const std::string& LLFolderViewItem::getSearchableLabel() const { - mSearchable = ""; - U32 flags = mRoot->getSearchType(); - if (flags == 0 || (flags & 1)) + U32 type = mRoot->getFilter()->getSearchType(); + switch(type) { - mSearchable = mSearchableLabel; + case 1: + return mSearchableLabelCreator; + case 2: + return mSearchableLabelDesc; + case 3: + return mSearchableLabelAll; + default: + return mSearchableLabel; } - if (flags & 2) - { - if (mSearchable.length()) - { - mSearchable += " "; - } - mSearchable += mSearchableLabelDesc; - } - if (flags & 4) - { - if (mSearchable.length()) - { - mSearchable += " "; - } - mSearchable += mSearchableLabelCreator; - } - return mSearchable; } const std::string& LLFolderViewItem::getName( void ) const @@ -738,12 +776,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { src = LLToolDragAndDrop::SOURCE_LIBRARY; } - // - else if(mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gLocalInventoryRoot)) - { // Note: this is only ok if all future pretend folders are subcategories of Pretend Inventory - src = LLToolDragAndDrop::SOURCE_LIBRARY; - } - // + can_drag = root->startDrag(src); if (can_drag) { @@ -784,10 +817,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - // - //preview(); - openItem(); - // + preview(); return TRUE; } @@ -1018,13 +1048,16 @@ void LLFolderViewItem::draw() if (sBoxImage.notNull() && mStringMatchOffset != std::string::npos) { // don't draw backgrounds for zero-length strings - std::string combined_string = mLabel + mLabelSuffix; S32 filter_string_length = mRoot->getFilterSubString().size(); - std::string combined_string_upper = combined_string; - LLStringUtil::toUpper(combined_string_upper); - if (filter_string_length > 0 && (mRoot->getSearchType() & 1) && - combined_string_upper.find(mRoot->getFilterSubString()) == mStringMatchOffset) + std::string combined_string = mLabel + mLabelSuffix; + + //fix so that highlighting works properly again - rkeast + std::string check = combined_string; + LLStringUtil::toUpper(check); + + if ((filter_string_length > 0) && (check.find(mRoot->getFilterSubString()) != -1)) { +// llinfos << "mLabel " << mLabel<< " mLabelSuffix " << mLabelSuffix << " mLabel " << mLabel << " mLabel " << mLabel << llendl; S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; S32 bottom = llfloor(getRect().getHeight() - sFont->getLineHeight() - 3); @@ -1447,10 +1480,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem BOOL rv = FALSE; if( selection == this ) { - if (!isSelected()) - { - selectItem(); - } + mIsSelected = TRUE; if(mListener) { mListener->selectItem(); @@ -1459,10 +1489,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem } else { - if (isSelected()) - { - deselectItem(); - } + mIsSelected = FALSE; rv = FALSE; } BOOL child_selected = FALSE; @@ -1475,6 +1502,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem { rv = TRUE; child_selected = TRUE; + mNumDescendantsSelected++; } } for (items_t::iterator iter = mItems.begin(); @@ -1485,6 +1513,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem { rv = TRUE; child_selected = TRUE; + mNumDescendantsSelected++; } } if(openitem && child_selected) @@ -1503,30 +1532,28 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec BOOL rv = FALSE; if(selection == this) { - if (isSelected() != selected) - { - rv = TRUE; - if (selected) - { - selectItem(); - } - else - { - deselectItem(); - } - } + mIsSelected = selected; if(mListener && selected) { mListener->selectItem(); } + rv = TRUE; } for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) { folders_t::iterator fit = iter++; - if ((*fit)->changeSelection(selection, selected)) + if((*fit)->changeSelection(selection, selected)) { + if (selected) + { + mNumDescendantsSelected++; + } + else + { + mNumDescendantsSelected--; + } rv = TRUE; } } @@ -1534,22 +1561,33 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec iter != mItems.end();) { items_t::iterator iit = iter++; - if ((*iit)->changeSelection(selection, selected)) + if((*iit)->changeSelection(selection, selected)) { + if (selected) + { + mNumDescendantsSelected++; + } + else + { + mNumDescendantsSelected--; + } rv = TRUE; } } return rv; } -void LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& selected_items) +S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& selected_items) { + S32 num_selected = 0; + // pass on to child folders first for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) { folders_t::iterator fit = iter++; - (*fit)->extendSelection(selection, last_selected, selected_items); + num_selected += (*fit)->extendSelection(selection, last_selected, selected_items); + mNumDescendantsSelected += num_selected; } // handle selection of our immediate children... @@ -1642,6 +1680,8 @@ void LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderVi if (item->changeSelection(item, TRUE)) { selected_items.put(item); + mNumDescendantsSelected++; + num_selected++; } } } @@ -1651,15 +1691,30 @@ void LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderVi if (selection->changeSelection(selection, TRUE)) { selected_items.put(selection); + mNumDescendantsSelected++; + num_selected++; } } + + return num_selected; } void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self) { - if (isSelected() && deselect_self) + // make sure we don't have negative values + llassert(mNumDescendantsSelected >= 0); + + if (mIsSelected && deselect_self) { - deselectItem(); + mIsSelected = FALSE; + + // update ancestors' count of selected descendents + LLFolderViewFolder* parent_folder = getParentFolder(); + while(parent_folder) + { + parent_folder->mNumDescendantsSelected--; + parent_folder = parent_folder->getParentFolder(); + } } if (0 == mNumDescendantsSelected) @@ -1667,19 +1722,14 @@ void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self) return; } - // Deselect all items in this folder. for (items_t::iterator iter = mItems.begin(); iter != mItems.end();) { items_t::iterator iit = iter++; LLFolderViewItem* item = (*iit); - if (item->isSelected()) - { - item->deselectItem(); - } + item->recursiveDeselect(TRUE); } - // Recursively deselect all folders in this folder. for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) { @@ -2739,59 +2789,6 @@ U32 LLFolderView::getSortOrder() const return mSortOrder; } -U32 LLFolderView::toggleSearchType(std::string toggle) -{ - if (toggle == "name") - { - if (mSearchType & 1) - { - mSearchType &= 6; - } - else - { - mSearchType |= 1; - } - } - else if (toggle == "description") - { - if (mSearchType & 2) - { - mSearchType &= 5; - } - else - { - mSearchType |= 2; - } - } - else if (toggle == "creator") - { - if (mSearchType & 4) - { - mSearchType &= 3; - } - else - { - mSearchType |= 4; - } - } - if (mSearchType == 0) - { - mSearchType = 1; - } - - if (getFilterSubString().length()) - { - mFilter.setModified(LLInventoryFilter::FILTER_RESTART); - } - - return mSearchType; -} - -U32 LLFolderView::getSearchType() const -{ - return mSearchType; -} - BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { // enforce sort order of My Inventory followed by Library @@ -2938,6 +2935,7 @@ void LLFolderView::filter( LLInventoryFilter& filter ) LLFastTimer t2(LLFastTimer::FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) { mFiltered = FALSE; @@ -3088,24 +3086,29 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) return rv; } -void LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items) +S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items) { + S32 rv = 0; + // now store resulting selection if (mAllowMultiSelect) { LLFolderViewItem *cur_selection = getCurSelectedItem(); - LLFolderViewFolder::extendSelection(selection, cur_selection, items); + rv = LLFolderViewFolder::extendSelection(selection, cur_selection, items); for (S32 i = 0; i < items.count(); i++) { addToSelectionList(items[i]); + rv++; } } else { setSelection(selection, FALSE, FALSE); + rv++; } mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + return rv; } void LLFolderView::sanitizeSelection() @@ -4628,6 +4631,10 @@ LLInventoryFilter::LLInventoryFilter(const std::string& name) : mModified(FALSE), mNeedTextRebuild(TRUE) { + //fix to get rid of gSavedSettings use - rkeast + mSearchType = 0; + mPartialSearch = false; + mFilterOps.mFilterTypes = 0xffffffff; mFilterOps.mMinDate = time_min(); mFilterOps.mMaxDate = time_max(); @@ -4672,13 +4679,50 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item) } LLFolderViewEventListener* listener = item->getListener(); const LLUUID& item_id = listener->getUUID(); - mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; - BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE) - && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) + + //When searching for all labels, we need to explode the filter string + //Into an array, and then compare each string to the label seperately + //Otherwise the filter substring needs to be + //formatted in the same order as the label - rkeast + + BOOL passed; + //Added ability to toggle this type of searching for all labels cause it's convienient - RKeast + if(mSearchType == 3 || mPartialSearch) + { + std::istringstream i(mFilterSubString); + std::string blah; + + LLDynamicArray search_array; + + while(i >> blah) + { + search_array.put(blah); + } + + BOOL subStringMatch = true; + for(int i = 0; i < search_array.getLength(); i++) + { + mSubStringMatchOffset = (search_array.get(i)).size() ? item->getSearchableLabel().find(search_array.get(i)) : std::string::npos; + subStringMatch = subStringMatch && ((search_array.get(i)).size() == 0 || mSubStringMatchOffset != std::string::npos); + } + + passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE) + && (subStringMatch) && (mFilterWorn == false || gAgent.isWearingItem(item_id) || (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isWearingAttachment(item_id))) && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions) && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate); + } + else + { + mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE) + && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) + && (mFilterWorn == false || gAgent.isWearingItem(item_id) || + (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isWearingAttachment(item_id))) + && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions) + && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate); + } return passed; } @@ -4727,6 +4771,31 @@ BOOL LLInventoryFilter::isModifiedAndClear() return ret; } +//fix to get rid of gSavedSettings use - rkeast +void LLInventoryFilter::setPartialSearch(bool toggle) +{ + + mPartialSearch = toggle; +} + +//fix to get rid of gSavedSettings use - rkeast +bool LLInventoryFilter::getPartialSearch() +{ + return mPartialSearch; +} + +//fix to get rid of gSavedSettings use - rkeast +void LLInventoryFilter::setSearchType(U32 type) +{ + mSearchType = type; +} + +//fix to get rid of gSavedSettings use - rkeast +U32 LLInventoryFilter::getSearchType() +{ + return mSearchType; +} + void LLInventoryFilter::setFilterTypes(U32 types) { if (mFilterOps.mFilterTypes != types) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index b3007b779..bff8aa282 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -166,7 +166,14 @@ public: class LLInventoryFilter { + public: + //fix to get rid of gSavedSettings use - rkeast + void setPartialSearch(bool toggle); + bool getPartialSearch(); + void setSearchType(U32 type); + U32 getSearchType(); + typedef enum e_folder_show { SHOW_ALL_FOLDERS, @@ -246,6 +253,10 @@ public: void fromLLSD(LLSD& data); protected: + //fix to get rid of gSavedSettings use - rkeast + U32 mSearchType; + bool mPartialSearch; + struct filter_ops { U32 mFilterTypes; @@ -320,12 +331,10 @@ class LLFolderView; class LLFolderViewItem : public LLUICtrl { +protected: friend class LLFolderViewEventListener; -private: - BOOL mIsSelected; -protected: static const LLFontGL* sFont; static const LLFontGL* sSmallFont; static LLColor4 sFgColor; @@ -340,14 +349,21 @@ protected: std::string mLabel; std::string mSearchableLabel; - std::string mSearchableLabelDesc; + std::string mLabelCreator; std::string mSearchableLabelCreator; - std::string mSearchable; + + std::string mLabelDesc; + std::string mSearchableLabelDesc; + + std::string mLabelAll; + std::string mSearchableLabelAll; + std::string mType; S32 mLabelWidth; U32 mCreationDate; LLFolderViewFolder* mParentFolder; LLFolderViewEventListener* mListener; + BOOL mIsSelected; BOOL mIsCurSelection; BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; @@ -356,6 +372,7 @@ protected: std::string mStatusText; BOOL mHasVisibleChildren; S32 mIndentation; + S32 mNumDescendantsSelected; BOOL mFiltered; S32 mLastFilterGeneration; std::string::size_type mStringMatchOffset; @@ -420,13 +437,18 @@ public: // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + + // This method is used to set the selection state of an item. // If 'selection' is 'this' then note selection. // Returns TRUE if the selection state of this item was changed. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); // this method is used to group select items - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items) { } + virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items){ return FALSE; } + + // this method is used to group select items + virtual void recursiveDeselect(BOOL deselect_self); // this method is used to deselect this element void deselectItem(); @@ -446,6 +468,8 @@ public: // destroys this item recursively virtual void destroyView(); + S32 getNumSelectedDescendants() { return mNumDescendantsSelected; } + BOOL isSelected() const { return mIsSelected; } void setIsCurSelection(BOOL select) { mIsCurSelection = select; } @@ -466,7 +490,7 @@ public: // viewed. This method will ask the viewed object itself. const std::string& getName( void ) const; - std::string& getSearchableLabel( void ); + const std::string& getSearchableLabel() const; // This method returns the label displayed on the view. This // method was primarily added to allow sorting on the folder @@ -554,7 +578,7 @@ public: UNKNOWN, TRASH, NOT_TRASH } ETrash; -private: + S32 mNumDescendantsSelected; public: // Accessed needed by LLFolderViewItem @@ -634,10 +658,10 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); // this method is used to group select items - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items); + virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items); // Deselect this folder and all folder/items it contains recursively. - void recursiveDeselect(BOOL deselect_self); + virtual void recursiveDeselect(BOOL deselect_self); // Returns true is this object and all of its children can be removed. virtual BOOL isRemovable(); @@ -801,7 +825,7 @@ public: // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items); + virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items); virtual BOOL getSelectionList(std::set &selection); diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 45837fbb1..3baacb7a8 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -1,534 +1,534 @@ -/** - * @file llhudeffectlookat.cpp - * @brief LLHUDEffectLookAt class implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llhudeffectlookat.h" - -#include "llrender.h" - -#include "message.h" -#include "llagent.h" -#include "llvoavatar.h" -#include "lldrawable.h" -#include "llviewerobjectlist.h" -#include "llrendersphere.h" -#include "llselectmgr.h" -#include "llglheaders.h" - - -#include "llxmltree.h" +/** + * @file llhudeffectlookat.cpp + * @brief LLHUDEffectLookAt class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llhudeffectlookat.h" + +#include "llrender.h" + +#include "message.h" +#include "llagent.h" +#include "llvoavatar.h" +#include "lldrawable.h" +#include "llviewerobjectlist.h" +#include "llrendersphere.h" +#include "llselectmgr.h" +#include "llglheaders.h" + + +#include "llxmltree.h" // #include "llresmgr.h" #include "llhudrender.h" -#include "llviewerwindow.h" +#include "llviewerwindow.h" #include "llviewercontrol.h" // - - -BOOL LLHUDEffectLookAt::sDebugLookAt = FALSE; - -// packet layout -const S32 SOURCE_AVATAR = 0; -const S32 TARGET_OBJECT = 16; -const S32 TARGET_POS = 32; -const S32 LOOKAT_TYPE = 56; -const S32 PKT_SIZE = 57; - -// throttle -const F32 MAX_SENDS_PER_SEC = 4.f; - -const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; -const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; - - -// can't use actual F32_MAX, because we add this to the current frametime -const F32 MAX_TIMEOUT = F32_MAX / 2.f; - -/** - * Simple data class holding values for a particular type of attention. - */ -class LLAttention -{ -public: - LLAttention() - : mTimeout(0.f), - mPriority(0.f) - {} - LLAttention(F32 timeout, F32 priority, const std::string& name, LLColor3 color) : - mTimeout(timeout), mPriority(priority), mName(name), mColor(color) - { - } - F32 mTimeout, mPriority; - std::string mName; - LLColor3 mColor; -}; - -/** - * Simple data class holding a list of attentions, one for every type. - */ -class LLAttentionSet -{ -public: - LLAttentionSet(const LLAttention attentions[]) - { - for(int i=0; igetAttributeString("name", str); - LLAttentionSet& attentions = (str.compare("Masculine") == 0) ? gBoyAttentions : gGirlAttentions; - for (LLXmlTreeNode* attention_node = gender->getChildByName( "param" ); - attention_node; - attention_node = gender->getNextNamedChild()) - { - attention_node->getAttributeString("attention", str); - LLAttention* attention; - if (str == "idle") attention = &attentions[LOOKAT_TARGET_IDLE]; - else if(str == "auto_listen") attention = &attentions[LOOKAT_TARGET_AUTO_LISTEN]; - else if(str == "freelook") attention = &attentions[LOOKAT_TARGET_FREELOOK]; - else if(str == "respond") attention = &attentions[LOOKAT_TARGET_RESPOND]; - else if(str == "hover") attention = &attentions[LOOKAT_TARGET_HOVER]; - else if(str == "conversation") attention = &attentions[LOOKAT_TARGET_CONVERSATION]; - else if(str == "select") attention = &attentions[LOOKAT_TARGET_SELECT]; - else if(str == "focus") attention = &attentions[LOOKAT_TARGET_FOCUS]; - else if(str == "mouselook") attention = &attentions[LOOKAT_TARGET_MOUSELOOK]; - else return FALSE; - - F32 priority, timeout; - attention_node->getAttributeF32("priority", priority); - attention_node->getAttributeF32("timeout", timeout); - if(timeout < 0) timeout = MAX_TIMEOUT; - attention->mPriority = priority; - attention->mTimeout = timeout; - } - return TRUE; -} - -static BOOL loadAttentions() -{ - static BOOL first_time = TRUE; - if( ! first_time) - { - return TRUE; // maybe not ideal but otherwise it can continue to fail forever. - } - first_time = FALSE; - - std::string filename; - filename = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"attentions.xml"); - LLXmlTree xml_tree; - BOOL success = xml_tree.parseFile( filename, FALSE ); - if( !success ) - { - return FALSE; - } - LLXmlTreeNode* root = xml_tree.getRoot(); - if( !root ) - { - return FALSE; - } - - //------------------------------------------------------------------------- - // (root) - //------------------------------------------------------------------------- - if( !root->hasName( "linden_attentions" ) ) - { - llwarns << "Invalid linden_attentions 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") ) - { - llwarns << "Invalid linden_attentions file version: " << version << llendl; - return FALSE; - } - - //------------------------------------------------------------------------- - // - //------------------------------------------------------------------------- - for (LLXmlTreeNode* child = root->getChildByName( "gender" ); - child; - child = root->getNextNamedChild()) - { - if( !loadGender( child ) ) - { - return FALSE; - } - } - - return TRUE; -} - - - - -//----------------------------------------------------------------------------- -// LLHUDEffectLookAt() -//----------------------------------------------------------------------------- -LLHUDEffectLookAt::LLHUDEffectLookAt(const U8 type) : - LLHUDEffect(type), - mKillTime(0.f), - mLastSendTime(0.f) -{ - clearLookAtTarget(); - // parse the default sets - loadAttentions(); - // initialize current attention set. switches when avatar sex changes. - mAttentions = &gGirlAttentions; -} - -//----------------------------------------------------------------------------- -// ~LLHUDEffectLookAt() -//----------------------------------------------------------------------------- -LLHUDEffectLookAt::~LLHUDEffectLookAt() -{ -} - -//----------------------------------------------------------------------------- -// packData() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys) -{ - // Pack the default data - LLHUDEffect::packData(mesgsys); - - // Pack the type-specific data. Uses a fun packed binary format. Whee! - U8 packed_data[PKT_SIZE]; - memset(packed_data, 0, PKT_SIZE); - - if (mSourceObject) - { - htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16); - } - else - { - htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16); - } - - // pack both target object and position - // position interpreted as offset if target object is non-null - if (mTargetObject) - { - htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16); - } - else - { - htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16); - } - - htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24); - - U8 lookAtTypePacked = (U8)mTargetType; - - htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1); - - mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE); - - mLastSendTime = mTimer.getElapsedTimeF32(); -} - -//----------------------------------------------------------------------------- -// unpackData() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum) -{ - LLVector3d new_target; - U8 packed_data[PKT_SIZE]; - - LLUUID dataId; - mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum); - - if (!gAgent.mLookAt.isNull() && dataId == gAgent.mLookAt->getID()) - { - return; - } - - LLHUDEffect::unpackData(mesgsys, blocknum); - LLUUID source_id; - LLUUID target_id; - S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); - if (size != PKT_SIZE) - { - llwarns << "LookAt effect with bad size " << size << llendl; - return; - } - mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum); - - htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16); - - LLViewerObject *objp = gObjectList.findObject(source_id); - if (objp && objp->isAvatar()) - { - setSourceObject(objp); - } - else - { - //llwarns << "Could not find source avatar for lookat effect" << llendl; - return; - } - - htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16); - - objp = gObjectList.findObject(target_id); - - htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24); - - if (objp) - { - setTargetObjectAndOffset(objp, new_target); - } - else if (target_id.isNull()) - { - setTargetPosGlobal(new_target); - } - else - { - //llwarns << "Could not find target object for lookat effect" << llendl; - } - - U8 lookAtTypeUnpacked = 0; - htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1); - mTargetType = (ELookAtType)lookAtTypeUnpacked; - - if (mTargetType == LOOKAT_TARGET_NONE) - { - clearLookAtTarget(); - } -} - -//----------------------------------------------------------------------------- -// setTargetObjectAndOffset() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset) -{ - mTargetObject = objp; - mTargetOffsetGlobal = offset; -} - -//----------------------------------------------------------------------------- -// setTargetPosGlobal() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::setTargetPosGlobal(const LLVector3d &target_pos_global) -{ - mTargetObject = NULL; - mTargetOffsetGlobal = target_pos_global; -} - -//----------------------------------------------------------------------------- -// setLookAt() -// called by agent logic to set look at behavior locally, and propagate to sim -//----------------------------------------------------------------------------- -BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) -{ - if (!mSourceObject) - { - return FALSE; - } - - if (target_type >= LOOKAT_NUM_TARGETS) - { - llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl; - return FALSE; - } - - // must be same or higher priority than existing effect - if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) - { - return FALSE; - } - - F32 current_time = mTimer.getElapsedTimeF32(); - - // type of lookat behavior or target object has changed - BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); - - // lookat position has moved a certain amount and we haven't just sent an update - lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && - ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); - - if (lookAtChanged) - { - mLastSentOffsetGlobal = position; - F32 timeout = (*mAttentions)[target_type].mTimeout; - setDuration(timeout); - setNeedsSendToSim(TRUE); - } - - if (target_type == LOOKAT_TARGET_CLEAR) - { - clearLookAtTarget(); - } - else - { - mTargetType = target_type; - mTargetObject = object; - if (object) - { - mTargetOffsetGlobal.setVec(position); - } - else - { - mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); - } - mKillTime = mTimer.getElapsedTimeF32() + mDuration; - - update(); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// clearLookAtTarget() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::clearLookAtTarget() -{ - mTargetObject = NULL; - mTargetOffsetGlobal.clearVec(); - mTargetType = LOOKAT_TARGET_NONE; - if (mSourceObject.notNull()) - { - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->stopMotion(ANIM_AGENT_HEAD_ROT); - } -} - -//----------------------------------------------------------------------------- -// markDead() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::markDead() -{ - if (mSourceObject.notNull()) - { - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("LookAtPoint"); - } - - mSourceObject = NULL; - clearLookAtTarget(); - LLHUDEffect::markDead(); -} - -void LLHUDEffectLookAt::setSourceObject(LLViewerObject* objectp) -{ - // restrict source objects to avatars - if (objectp && objectp->isAvatar()) - { - LLHUDEffect::setSourceObject(objectp); - } -} - -//----------------------------------------------------------------------------- -// render() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::render() -{ - if (gSavedSettings.getBOOL("PrivateLookAt") && - (gAgent.getAvatarObject() == ((LLVOAvatar*)(LLViewerObject*)mSourceObject))) return; - if (sDebugLookAt && mSourceObject.notNull()) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLVector3 target = mTargetPos + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition(); - glMatrixMode(GL_MODELVIEW); - gGL.pushMatrix(); - gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]); - glScalef(0.3f, 0.3f, 0.3f); - gGL.begin(LLRender::LINES); - { - LLColor3 color = (*mAttentions)[mTargetType].mColor; - gGL.color3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); - gGL.vertex3f(-1.f, 0.f, 0.f); - gGL.vertex3f(1.f, 0.f, 0.f); - - gGL.vertex3f(0.f, -1.f, 0.f); - gGL.vertex3f(0.f, 1.f, 0.f); - - gGL.vertex3f(0.f, 0.f, -1.f); - gGL.vertex3f(0.f, 0.f, 1.f); - } gGL.end(); - gGL.popMatrix(); + + +BOOL LLHUDEffectLookAt::sDebugLookAt = FALSE; + +// packet layout +const S32 SOURCE_AVATAR = 0; +const S32 TARGET_OBJECT = 16; +const S32 TARGET_POS = 32; +const S32 LOOKAT_TYPE = 56; +const S32 PKT_SIZE = 57; + +// throttle +const F32 MAX_SENDS_PER_SEC = 4.f; + +const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; +const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; + + +// can't use actual F32_MAX, because we add this to the current frametime +const F32 MAX_TIMEOUT = F32_MAX / 2.f; + +/** + * Simple data class holding values for a particular type of attention. + */ +class LLAttention +{ +public: + LLAttention() + : mTimeout(0.f), + mPriority(0.f) + {} + LLAttention(F32 timeout, F32 priority, const std::string& name, LLColor3 color) : + mTimeout(timeout), mPriority(priority), mName(name), mColor(color) + { + } + F32 mTimeout, mPriority; + std::string mName; + LLColor3 mColor; +}; + +/** + * Simple data class holding a list of attentions, one for every type. + */ +class LLAttentionSet +{ +public: + LLAttentionSet(const LLAttention attentions[]) + { + for(int i=0; igetAttributeString("name", str); + LLAttentionSet& attentions = (str.compare("Masculine") == 0) ? gBoyAttentions : gGirlAttentions; + for (LLXmlTreeNode* attention_node = gender->getChildByName( "param" ); + attention_node; + attention_node = gender->getNextNamedChild()) + { + attention_node->getAttributeString("attention", str); + LLAttention* attention; + if (str == "idle") attention = &attentions[LOOKAT_TARGET_IDLE]; + else if(str == "auto_listen") attention = &attentions[LOOKAT_TARGET_AUTO_LISTEN]; + else if(str == "freelook") attention = &attentions[LOOKAT_TARGET_FREELOOK]; + else if(str == "respond") attention = &attentions[LOOKAT_TARGET_RESPOND]; + else if(str == "hover") attention = &attentions[LOOKAT_TARGET_HOVER]; + else if(str == "conversation") attention = &attentions[LOOKAT_TARGET_CONVERSATION]; + else if(str == "select") attention = &attentions[LOOKAT_TARGET_SELECT]; + else if(str == "focus") attention = &attentions[LOOKAT_TARGET_FOCUS]; + else if(str == "mouselook") attention = &attentions[LOOKAT_TARGET_MOUSELOOK]; + else return FALSE; + + F32 priority, timeout; + attention_node->getAttributeF32("priority", priority); + attention_node->getAttributeF32("timeout", timeout); + if(timeout < 0) timeout = MAX_TIMEOUT; + attention->mPriority = priority; + attention->mTimeout = timeout; + } + return TRUE; +} + +static BOOL loadAttentions() +{ + static BOOL first_time = TRUE; + if( ! first_time) + { + return TRUE; // maybe not ideal but otherwise it can continue to fail forever. + } + first_time = FALSE; + + std::string filename; + filename = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"attentions.xml"); + LLXmlTree xml_tree; + BOOL success = xml_tree.parseFile( filename, FALSE ); + if( !success ) + { + return FALSE; + } + LLXmlTreeNode* root = xml_tree.getRoot(); + if( !root ) + { + return FALSE; + } + + //------------------------------------------------------------------------- + // (root) + //------------------------------------------------------------------------- + if( !root->hasName( "linden_attentions" ) ) + { + llwarns << "Invalid linden_attentions 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") ) + { + llwarns << "Invalid linden_attentions file version: " << version << llendl; + return FALSE; + } + + //------------------------------------------------------------------------- + // + //------------------------------------------------------------------------- + for (LLXmlTreeNode* child = root->getChildByName( "gender" ); + child; + child = root->getNextNamedChild()) + { + if( !loadGender( child ) ) + { + return FALSE; + } + } + + return TRUE; +} + + + + +//----------------------------------------------------------------------------- +// LLHUDEffectLookAt() +//----------------------------------------------------------------------------- +LLHUDEffectLookAt::LLHUDEffectLookAt(const U8 type) : + LLHUDEffect(type), + mKillTime(0.f), + mLastSendTime(0.f) +{ + clearLookAtTarget(); + // parse the default sets + loadAttentions(); + // initialize current attention set. switches when avatar sex changes. + mAttentions = &gGirlAttentions; +} + +//----------------------------------------------------------------------------- +// ~LLHUDEffectLookAt() +//----------------------------------------------------------------------------- +LLHUDEffectLookAt::~LLHUDEffectLookAt() +{ +} + +//----------------------------------------------------------------------------- +// packData() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys) +{ + // Pack the default data + LLHUDEffect::packData(mesgsys); + + // Pack the type-specific data. Uses a fun packed binary format. Whee! + U8 packed_data[PKT_SIZE]; + memset(packed_data, 0, PKT_SIZE); + + if (mSourceObject) + { + htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16); + } + else + { + htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16); + } + + // pack both target object and position + // position interpreted as offset if target object is non-null + if (mTargetObject) + { + htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16); + } + else + { + htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16); + } + + htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24); + + U8 lookAtTypePacked = (U8)mTargetType; + + htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1); + + mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE); + + mLastSendTime = mTimer.getElapsedTimeF32(); +} + +//----------------------------------------------------------------------------- +// unpackData() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum) +{ + LLVector3d new_target; + U8 packed_data[PKT_SIZE]; + + LLUUID dataId; + mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum); + + if (!gAgent.mLookAt.isNull() && dataId == gAgent.mLookAt->getID()) + { + return; + } + + LLHUDEffect::unpackData(mesgsys, blocknum); + LLUUID source_id; + LLUUID target_id; + S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); + if (size != PKT_SIZE) + { + llwarns << "LookAt effect with bad size " << size << llendl; + return; + } + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum); + + htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16); + + LLViewerObject *objp = gObjectList.findObject(source_id); + if (objp && objp->isAvatar()) + { + setSourceObject(objp); + } + else + { + //llwarns << "Could not find source avatar for lookat effect" << llendl; + return; + } + + htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16); + + objp = gObjectList.findObject(target_id); + + htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24); + + if (objp) + { + setTargetObjectAndOffset(objp, new_target); + } + else if (target_id.isNull()) + { + setTargetPosGlobal(new_target); + } + else + { + //llwarns << "Could not find target object for lookat effect" << llendl; + } + + U8 lookAtTypeUnpacked = 0; + htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1); + mTargetType = (ELookAtType)lookAtTypeUnpacked; + + if (mTargetType == LOOKAT_TARGET_NONE) + { + clearLookAtTarget(); + } +} + +//----------------------------------------------------------------------------- +// setTargetObjectAndOffset() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset) +{ + mTargetObject = objp; + mTargetOffsetGlobal = offset; +} + +//----------------------------------------------------------------------------- +// setTargetPosGlobal() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::setTargetPosGlobal(const LLVector3d &target_pos_global) +{ + mTargetObject = NULL; + mTargetOffsetGlobal = target_pos_global; +} + +//----------------------------------------------------------------------------- +// setLookAt() +// called by agent logic to set look at behavior locally, and propagate to sim +//----------------------------------------------------------------------------- +BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) +{ + if (!mSourceObject) + { + return FALSE; + } + + if (target_type >= LOOKAT_NUM_TARGETS) + { + llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl; + return FALSE; + } + + // must be same or higher priority than existing effect + if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) + { + return FALSE; + } + + F32 current_time = mTimer.getElapsedTimeF32(); + + // type of lookat behavior or target object has changed + BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); + + // lookat position has moved a certain amount and we haven't just sent an update + lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); + + if (lookAtChanged) + { + mLastSentOffsetGlobal = position; + F32 timeout = (*mAttentions)[target_type].mTimeout; + setDuration(timeout); + setNeedsSendToSim(TRUE); + } + + if (target_type == LOOKAT_TARGET_CLEAR) + { + clearLookAtTarget(); + } + else + { + mTargetType = target_type; + mTargetObject = object; + if (object) + { + mTargetOffsetGlobal.setVec(position); + } + else + { + mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); + } + mKillTime = mTimer.getElapsedTimeF32() + mDuration; + + update(); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// clearLookAtTarget() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::clearLookAtTarget() +{ + mTargetObject = NULL; + mTargetOffsetGlobal.clearVec(); + mTargetType = LOOKAT_TARGET_NONE; + if (mSourceObject.notNull()) + { + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->stopMotion(ANIM_AGENT_HEAD_ROT); + } +} + +//----------------------------------------------------------------------------- +// markDead() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::markDead() +{ + if (mSourceObject.notNull()) + { + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("LookAtPoint"); + } + + mSourceObject = NULL; + clearLookAtTarget(); + LLHUDEffect::markDead(); +} + +void LLHUDEffectLookAt::setSourceObject(LLViewerObject* objectp) +{ + // restrict source objects to avatars + if (objectp && objectp->isAvatar()) + { + LLHUDEffect::setSourceObject(objectp); + } +} + +//----------------------------------------------------------------------------- +// render() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::render() +{ + if (gSavedSettings.getBOOL("PrivateLookAt") && + (gAgent.getAvatarObject() == ((LLVOAvatar*)(LLViewerObject*)mSourceObject))) return; + if (sDebugLookAt && mSourceObject.notNull()) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector3 target = mTargetPos + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition(); + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]); + glScalef(0.3f, 0.3f, 0.3f); + gGL.begin(LLRender::LINES); + { + LLColor3 color = (*mAttentions)[mTargetType].mColor; + gGL.color3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); + gGL.vertex3f(-1.f, 0.f, 0.f); + gGL.vertex3f(1.f, 0.f, 0.f); + + gGL.vertex3f(0.f, -1.f, 0.f); + gGL.vertex3f(0.f, 1.f, 0.f); + + gGL.vertex3f(0.f, 0.f, -1.f); + gGL.vertex3f(0.f, 0.f, 1.f); + } gGL.end(); + gGL.popMatrix(); // const std::string text = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->getFullname(); LLVector3 offset = gAgent.getCameraPositionAgent() - target; @@ -557,159 +557,159 @@ void LLHUDEffectLookAt::render() FALSE); glPopMatrix(); // - } -} - -//----------------------------------------------------------------------------- -// update() -//----------------------------------------------------------------------------- -void LLHUDEffectLookAt::update() -{ - // If the target object is dead, set the target object to NULL - if (!mTargetObject.isNull() && mTargetObject->isDead()) - { - clearLookAtTarget(); - } - - // if source avatar is null or dead, mark self as dead and return - if (mSourceObject.isNull() || mSourceObject->isDead()) - { - markDead(); - return; - } - - // make sure the proper set of avatar attention are currently being used. - LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; - // for now the first cut will just switch on sex. future development could adjust - // timeouts according to avatar age and/or other features. - mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; - //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); - - F32 time = mTimer.getElapsedTimeF32(); - - // clear out the effect if time is up - if (mKillTime != 0.f && time > mKillTime) - { - if (mTargetType != LOOKAT_TARGET_NONE) - { - clearLookAtTarget(); - // look at timed out (only happens on own avatar), so tell everyone - setNeedsSendToSim(TRUE); - } - } - - if (mTargetType != LOOKAT_TARGET_NONE) - { - if (calcTargetPosition()) - { - LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); - if (!head_motion || head_motion->isStopped()) - { - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); - } - } - } - - if (sDebugLookAt) - { - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); - } -} - -/** - * Initializes the mTargetPos member from the current mSourceObjec and mTargetObject - * (and possibly mTargetOffsetGlobal). - * When mTargetObject is another avatar, it sets mTargetPos to be their eyes. - * - * Has the side-effect of also calling setAnimationData("LookAtPoint") with the new - * mTargetPos on the source object which is assumed to be an avatar. - * - * Returns whether we successfully calculated a finite target position. - */ -bool LLHUDEffectLookAt::calcTargetPosition() -{ - if (gNoRender) - { - return false; - } - - LLViewerObject *target_obj = (LLViewerObject *)mTargetObject; - LLVector3 local_offset; - - if (target_obj) - { - local_offset.setVec(mTargetOffsetGlobal); - } - else - { - local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal); - } - - LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; - - if (target_obj && target_obj->mDrawable.notNull()) - { - LLQuaternion target_rot; - if (target_obj->isAvatar()) - { - LLVOAvatar *target_av = (LLVOAvatar *)target_obj; - - BOOL looking_at_self = source_avatar->isSelf() && target_av->isSelf(); - - // if selecting self, stare forward - if (looking_at_self && mTargetOffsetGlobal.magVecSquared() < MIN_TARGET_OFFSET_SQUARED) - { - //sets the lookat point in front of the avatar - mTargetOffsetGlobal.setVec(5.0, 0.0, 0.0); - local_offset.setVec(mTargetOffsetGlobal); - } - - // look the other avatar in the eye. note: what happens if target is self? -MG - mTargetPos = target_av->mHeadp->getWorldPosition(); - if (mTargetType == LOOKAT_TARGET_MOUSELOOK || mTargetType == LOOKAT_TARGET_FREELOOK) - { - // mouselook and freelook target offsets are absolute - target_rot = LLQuaternion::DEFAULT; - } - else if (looking_at_self && gAgent.cameraCustomizeAvatar()) - { - // *NOTE: We have to do this because animation - // overrides do not set lookat behavior. - // *TODO: animation overrides for lookat behavior. - target_rot = target_av->mPelvisp->getWorldRotation(); - } - else - { - target_rot = target_av->mRoot.getWorldRotation(); - } - } - else // target obj is not an avatar - { - if (target_obj->mDrawable->getGeneration() == -1) - { - mTargetPos = target_obj->getPositionAgent(); - target_rot = target_obj->getWorldRotation(); - } - else - { - mTargetPos = target_obj->getRenderPosition(); - target_rot = target_obj->getRenderRotation(); - } - } - - mTargetPos += (local_offset * target_rot); - } - else // no target obj or it's not drawable - { - mTargetPos = local_offset; - } - - mTargetPos -= source_avatar->mHeadp->getWorldPosition(); - - if (!mTargetPos.isFinite()) - return false; - - source_avatar->setAnimationData("LookAtPoint", (void *)&mTargetPos); - - return true; -} + } +} + +//----------------------------------------------------------------------------- +// update() +//----------------------------------------------------------------------------- +void LLHUDEffectLookAt::update() +{ + // If the target object is dead, set the target object to NULL + if (!mTargetObject.isNull() && mTargetObject->isDead()) + { + clearLookAtTarget(); + } + + // if source avatar is null or dead, mark self as dead and return + if (mSourceObject.isNull() || mSourceObject->isDead()) + { + markDead(); + return; + } + + // make sure the proper set of avatar attention are currently being used. + LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; + // for now the first cut will just switch on sex. future development could adjust + // timeouts according to avatar age and/or other features. + mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; + //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); + + F32 time = mTimer.getElapsedTimeF32(); + + // clear out the effect if time is up + if (mKillTime != 0.f && time > mKillTime) + { + if (mTargetType != LOOKAT_TARGET_NONE) + { + clearLookAtTarget(); + // look at timed out (only happens on own avatar), so tell everyone + setNeedsSendToSim(TRUE); + } + } + + if (mTargetType != LOOKAT_TARGET_NONE) + { + if (calcTargetPosition()) + { + LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); + if (!head_motion || head_motion->isStopped()) + { + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); + } + } + } + + if (sDebugLookAt) + { + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); + } +} + +/** + * Initializes the mTargetPos member from the current mSourceObjec and mTargetObject + * (and possibly mTargetOffsetGlobal). + * When mTargetObject is another avatar, it sets mTargetPos to be their eyes. + * + * Has the side-effect of also calling setAnimationData("LookAtPoint") with the new + * mTargetPos on the source object which is assumed to be an avatar. + * + * Returns whether we successfully calculated a finite target position. + */ +bool LLHUDEffectLookAt::calcTargetPosition() +{ + if (gNoRender) + { + return false; + } + + LLViewerObject *target_obj = (LLViewerObject *)mTargetObject; + LLVector3 local_offset; + + if (target_obj) + { + local_offset.setVec(mTargetOffsetGlobal); + } + else + { + local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal); + } + + LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; + + if (target_obj && target_obj->mDrawable.notNull()) + { + LLQuaternion target_rot; + if (target_obj->isAvatar()) + { + LLVOAvatar *target_av = (LLVOAvatar *)target_obj; + + BOOL looking_at_self = source_avatar->isSelf() && target_av->isSelf(); + + // if selecting self, stare forward + if (looking_at_self && mTargetOffsetGlobal.magVecSquared() < MIN_TARGET_OFFSET_SQUARED) + { + //sets the lookat point in front of the avatar + mTargetOffsetGlobal.setVec(5.0, 0.0, 0.0); + local_offset.setVec(mTargetOffsetGlobal); + } + + // look the other avatar in the eye. note: what happens if target is self? -MG + mTargetPos = target_av->mHeadp->getWorldPosition(); + if (mTargetType == LOOKAT_TARGET_MOUSELOOK || mTargetType == LOOKAT_TARGET_FREELOOK) + { + // mouselook and freelook target offsets are absolute + target_rot = LLQuaternion::DEFAULT; + } + else if (looking_at_self && gAgent.cameraCustomizeAvatar()) + { + // *NOTE: We have to do this because animation + // overrides do not set lookat behavior. + // *TODO: animation overrides for lookat behavior. + target_rot = target_av->mPelvisp->getWorldRotation(); + } + else + { + target_rot = target_av->mRoot.getWorldRotation(); + } + } + else // target obj is not an avatar + { + if (target_obj->mDrawable->getGeneration() == -1) + { + mTargetPos = target_obj->getPositionAgent(); + target_rot = target_obj->getWorldRotation(); + } + else + { + mTargetPos = target_obj->getRenderPosition(); + target_rot = target_obj->getRenderRotation(); + } + } + + mTargetPos += (local_offset * target_rot); + } + else // no target obj or it's not drawable + { + mTargetPos = local_offset; + } + + mTargetPos -= source_avatar->mHeadp->getWorldPosition(); + + if (!mTargetPos.isFinite()) + return false; + + source_avatar->setAnimationData("LookAtPoint", (void *)&mTargetPos); + source_avatar->mIdleTimer.reset(); + return true; +} diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp index 88521df29..0bf863728 100644 --- a/indra/newview/llhudeffectpointat.cpp +++ b/indra/newview/llhudeffectpointat.cpp @@ -449,7 +449,9 @@ bool LLHUDEffectPointAt::calcTargetPosition() if (mSourceObject->isAvatar()) { - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("PointAtPoint", (void *)&mTargetPos); + LLVOAvatar* avatarp = ((LLVOAvatar*)(LLViewerObject*)mSourceObject); + avatarp->setAnimationData("PointAtPoint", (void *)&mTargetPos); + avatarp->mIdleTimer.reset(); } return true; diff --git a/indra/newview/llhudmanager.cpp b/indra/newview/llhudmanager.cpp index 7d0ed57ef..dabd5e597 100644 --- a/indra/newview/llhudmanager.cpp +++ b/indra/newview/llhudmanager.cpp @@ -79,7 +79,10 @@ void LLHUDManager::updateEffects() void LLHUDManager::sendEffects() { - if(!gSavedSettings.getBOOL("BroadcastViewerEffects"))return; + + if(!gSavedSettings.getBOOL("BroadcastViewerEffects")) + return; + S32 i; for (i = 0; i < mHUDEffects.count(); i++) { diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 65f9ebf74..6e3201d68 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -2143,6 +2143,8 @@ void LLFloaterIMPanel::setTyping(BOOL typing) void LLFloaterIMPanel::sendTypingState(BOOL typing) { + if(gSavedSettings.getBOOL("AscentHideTypingNotification")) + return; // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. if (mDialog != IM_NOTHING_SPECIAL) return; diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 619b0cf1b..37f79cf2e 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -118,49 +118,6 @@ bool doToSelected(LLFolderView* folder, std::string action) { LLInventoryClipboard::instance().reset(); } - // - if("save_as" == action) - { - LLInventoryBackup::save(folder); - return true; - } - else if("save_invcache" == action) - { - LLFilePicker& file_picker = LLFilePicker::instance(); - if(file_picker.getSaveFile( LLFilePicker::FFSAVE_INVGZ )) - { - std::string file_name = file_picker.getFirstFile(); - LLLocalInventory::saveInvCache(file_name, folder); - } - return true; - } -/* - else if("acquire_asset_id" == action) - { - if(LLCheats::cheatCodes["AcquireAssetID"].entered) - { - std::set selected_items_set; - folder->getSelectionList(selected_items_set); - - if(selected_items_set.size() > 0) - { - LLAssetIDAcquirer::acquire(selected_items_set); - } - } - return true; - } - else if("magic_get" == action) - { - std::set selected_items_set; - folder->getSelectionList(selected_items_set); - - if(selected_items_set.size() > 0) - { - LLNotecardMagic::acquire(selected_items_set); - } - } -*/ - // std::set selected_items; folder->getSelectionList(selected_items); @@ -202,6 +159,12 @@ bool doToSelected(LLFolderView* folder, std::string action) bridge->performAction(folder, model, action); } + + + + + + LLFloater::setFloaterHost(NULL); if (multi_previewp) { @@ -521,19 +484,163 @@ class LLDoCreateFloater : public inventory_listener_t LLInventoryModel* model = mPtr->getPanel()->getModel(); if(!model) return false; std::string type = userdata.asString(); - // - if(type == "pretend") - { - LLFloaterNewLocalInventory* floater = new LLFloaterNewLocalInventory(); - floater->center(); - } - else - // do_create(model, mPtr->getPanel(), type); return true; } }; +//Handles the search type buttons - RKeast +class SetSearchType : public inventory_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string search_type = userdata.asString(); + if(search_type == "name") + { + mPtr->getActivePanel()->setSearchType(0); + + gSavedPerAccountSettings.setU32("rkeastInventorySearchType",0); + + mPtr->getControl("Inventory.SearchByName")->setValue(TRUE); + mPtr->getControl("Inventory.SearchByCreator")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByDesc")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByAll")->setValue(FALSE); + } + else if(search_type == "creator") + { + mPtr->getActivePanel()->setSearchType(1); + + gSavedPerAccountSettings.setU32("rkeastInventorySearchType",1); + + mPtr->getControl("Inventory.SearchByName")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByCreator")->setValue(TRUE); + mPtr->getControl("Inventory.SearchByDesc")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByAll")->setValue(FALSE); + } + else if(search_type == "desc") + { + mPtr->getActivePanel()->setSearchType(2); + + gSavedPerAccountSettings.setU32("rkeastInventorySearchType",2); + + mPtr->getControl("Inventory.SearchByName")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByCreator")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByDesc")->setValue(TRUE); + mPtr->getControl("Inventory.SearchByAll")->setValue(FALSE); + } + else if(search_type == "all") + { + mPtr->getActivePanel()->setSearchType(3); + + gSavedPerAccountSettings.setU32("rkeastInventorySearchType",3); + + mPtr->getControl("Inventory.SearchByName")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByCreator")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByDesc")->setValue(FALSE); + mPtr->getControl("Inventory.SearchByAll")->setValue(TRUE); + } + + //Clear search when switching modes. + mPtr->getActivePanel()->setFilterSubString(LLStringUtil::null); + mPtr->getActivePanel()->setFilterTypes(0xffffffff); + return true; + } +}; + +//Handles the partial search result button - RKeast +class SetPartialSearch : public inventory_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string data = userdata.asString(); + if(data == "toggle") + { + BOOL current = mPtr->getActivePanel()->getPartialSearch(); + mPtr->getActivePanel()->setPartialSearch(!current); + + if(current == false) + { + mPtr->getActivePanel()->setPartialSearch(true); + mPtr->getControl("Inventory.PartialSearchToggle")->setValue(TRUE); + + gSavedPerAccountSettings.setBOOL("rkeastInventoryPartialSearch",TRUE); + } + else + { + mPtr->getActivePanel()->setPartialSearch(false); + mPtr->getControl("Inventory.PartialSearchToggle")->setValue(FALSE); + + gSavedPerAccountSettings.setBOOL("rkeastInventoryPartialSearch",FALSE); + } + } + + //Clear search when switching modes. + mPtr->getActivePanel()->setFilterSubString(LLStringUtil::null); + mPtr->getActivePanel()->setFilterTypes(0xffffffff); + return true; + } +}; + +class LLSetSortBy : public inventory_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string sort_field = userdata.asString(); + if (sort_field == "name") + { + U32 order = mPtr->getActivePanel()->getSortOrder(); + mPtr->getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE ); + + mPtr->getControl("Inventory.SortByName")->setValue( TRUE ); + mPtr->getControl("Inventory.SortByDate")->setValue( FALSE ); + } + else if (sort_field == "date") + { + U32 order = mPtr->getActivePanel()->getSortOrder(); + mPtr->getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE ); + + mPtr->getControl("Inventory.SortByName")->setValue( FALSE ); + mPtr->getControl("Inventory.SortByDate")->setValue( TRUE ); + } + else if (sort_field == "foldersalwaysbyname") + { + U32 order = mPtr->getActivePanel()->getSortOrder(); + if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME ) + { + order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; + + mPtr->getControl("Inventory.FoldersAlwaysByName")->setValue( FALSE ); + } + else + { + order |= LLInventoryFilter::SO_FOLDERS_BY_NAME; + + mPtr->getControl("Inventory.FoldersAlwaysByName")->setValue( TRUE ); + } + mPtr->getActivePanel()->setSortOrder( order ); + } + else if (sort_field == "systemfolderstotop") + { + U32 order = mPtr->getActivePanel()->getSortOrder(); + if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) + { + order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + + mPtr->getControl("Inventory.SystemFoldersToTop")->setValue( FALSE ); + } + else + { + order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + + mPtr->getControl("Inventory.SystemFoldersToTop")->setValue( TRUE ); + } + mPtr->getActivePanel()->setSortOrder( order ); + } + + return true; + } +}; + // class LLLoadInvCacheFloater : public inventory_listener_t { @@ -562,62 +669,7 @@ class LLRefreshInvModel : public inventory_listener_t return true; } }; -// -class LLSetSortBy : public inventory_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string sort_field = userdata.asString(); - U32 order = mPtr->getActivePanel()->getSortOrder(); - if (sort_field == "name") - { - order &= ~LLInventoryFilter::SO_DATE; - } - else if (sort_field == "date") - { - order |= LLInventoryFilter::SO_DATE; - } - else if (sort_field == "foldersalwaysbyname") - { - if (order & LLInventoryFilter::SO_FOLDERS_BY_NAME) - { - order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - else - { - order |= LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - } - else if (sort_field == "systemfolderstotop") - { - if (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP) - { - order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - else - { - order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - } - mPtr->getActivePanel()->setSortOrder(order); - mPtr->updateSortControls(); - - return true; - } -}; -class LLSetSearchType : public inventory_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string toggle = userdata.asString(); - U32 flags = mPtr->getActivePanel()->getRootFolder()->toggleSearchType(toggle); - mPtr->getControl("Inventory.SearchName")->setValue((BOOL)(flags & 1)); - mPtr->getControl("Inventory.SearchDesc")->setValue((BOOL)(flags & 2)); - mPtr->getControl("Inventory.SearchCreator")->setValue((BOOL)(flags & 4)); - return true; - } -}; class LLBeginIMSession : public inventory_panel_listener_t { @@ -810,7 +862,8 @@ void init_inventory_actions(LLInventoryView *floater) (new LLResetFilter())->registerListener(floater, "Inventory.ResetFilter"); (new LLSetSortBy())->registerListener(floater, "Inventory.SetSortBy"); - (new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType"); + (new SetSearchType())->registerListener(floater, "Inventory.SetSearchBy"); + (new SetPartialSearch())->registerListener(floater, "Inventory.PartialSearch"); } void init_inventory_panel_actions(LLInventoryPanel *panel) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5a2a8ccfc..6a5221199 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -53,6 +53,7 @@ #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfloaterproperties.h" + #include "llfloaterworldmap.h" #include "llfocusmgr.h" #include "llfolderview.h" @@ -72,10 +73,14 @@ #include "llresmgr.h" #include "llscrollcontainer.h" #include "llimview.h" + #include "lltooldraganddrop.h" + #include "llviewerimagelist.h" #include "llviewerinventory.h" + #include "llviewerobjectlist.h" + #include "llviewerwindow.h" #include "llvoavatar.h" #include "llwearable.h" @@ -177,8 +182,10 @@ struct LLWearInfo BOOL mAppend; }; + BOOL gAddToOutfit = FALSE; + // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -223,15 +230,11 @@ BOOL LLInvFVBridge::isItemRemovable() // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; - // - //if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) - //{ - // return TRUE; - //} - // - //return FALSE; + if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) + { return TRUE; - // + } + return FALSE; } // Can be moved to another folder @@ -552,31 +555,20 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector - /* - // + if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) || (flags & FIRST_SELECTED_ITEM) == 0) { disabled_items.push_back(std::string("Copy Asset UUID")); } - // - */ - // } - // - //items.push_back(std::string("Magic Get")); - //items.push_back(std::string("Rez")); - items.push_back(std::string("Open With...")); - // for now, disable reupload - //if(getInventoryType() == LLInventoryType::IT_ANIMATION) - //{ - // items.push_back(std::string("Reupload...")); - //} - items.push_back(std::string("Save As...")); - items.push_back(std::string("Save InvCache...")); - // + + + + + + items.push_back(std::string("Copy Separator")); @@ -626,6 +618,20 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hideContextEntries(menu, items, disabled_items); } + + + + + + + + + + + + + + // *TODO: remove this BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const { @@ -895,6 +901,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) { + if ("open" == action) { openItem(); @@ -954,75 +961,6 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, folder_view_itemp->getListener()->pasteFromClipboard(); return; } - // - else if("open hex" == action) - { - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - DOFloaterHex::show(mUUID); - } - else if("open text" == action) - { - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - HGFloaterTextEditor::show(mUUID); - } - else if ("rez" == action) - { - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - LLViewerRegion* regionp = gAgent.getRegion(); - if (!regionp) - { - llwarns << "Couldn't find region to rez object" << llendl; - return; - } - - //llinfos << "Rezzing object" << llendl; - make_ui_sound("UISndObjectRezIn"); - - if (regionp - && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)) - { - LLFirstUse::useSandbox(); - } - - BOOL remove_from_inventory = !item->getPermissions().allowCopyBy(gAgent.getID()); - - LLVector3 rezpos = gAgent.getPositionAgent() + (gAgent.getAtAxis() * 5.0f); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezObject); - - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - - msg->nextBlock("RezData"); - // if it's being rezzed from task inventory, we need to enable - // saving it back into the task inventory. - // *FIX: We can probably compress this to a single byte, since I - // think folderid == mSourceID. This will be a later - // optimization. - msg->addUUIDFast(_PREHASH_FromTaskID, LLUUID::null); - msg->addU8Fast(_PREHASH_BypassRaycast, (U8)TRUE); - msg->addVector3Fast(_PREHASH_RayStart, rezpos); - msg->addVector3Fast(_PREHASH_RayEnd, rezpos); - msg->addUUIDFast(_PREHASH_RayTargetID, LLUUID::null); - msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE); - msg->addBOOLFast(_PREHASH_RezSelected, true); - msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory); - - // deal with permissions slam logic - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - - LLUUID folder_id = item->getParentUUID(); - msg->nextBlockFast(_PREHASH_InventoryData); - item->packMessage(msg); - - msg->sendReliable(regionp->getHost()); - } else if("reupload" == action) { LLInventoryItem* item = model->getItem(mUUID); @@ -1173,22 +1111,21 @@ std::string LLItemBridge::getLabelSuffix() const LLInventoryItem* item = getItem(); if(item) { - // it's a bit confusing to put nocopy/nomod/etc on calling cards. - // Not really sheesh - //if(LLAssetType::AT_CALLINGCARD != item->getType() - // && item->getPermissions().getOwner() == gAgent.getID()) - if(item->getPermissions().getOwner() == gAgent.getID()) - // + LLPermissions perm = item->getPermissions(); + // + if(perm.getOwner() == gAgent.getID()) + { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + BOOL copy = perm.allowCopyBy(gAgent.getID()); + BOOL mod = perm.allowModifyBy(gAgent.getID()); + BOOL xfer = perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()); // *TODO: Translate const char* EMPTY = ""; const char* NO_COPY = " (no copy)"; const char* NO_MOD = " (no modify)"; const char* NO_XFER = " (no transfer)"; + const char* TEMPO = " (temporary)"; const char* scopy; if(copy) scopy = EMPTY; else scopy = NO_COPY; @@ -1198,7 +1135,10 @@ std::string LLItemBridge::getLabelSuffix() const const char* sxfer; if(xfer) sxfer = EMPTY; else sxfer = NO_XFER; - suffix = llformat("%s%s%s",scopy,smod,sxfer); + const char* stempo; + if(perm.getGroup() == gAgent.getID())stempo = TEMPO; + else stempo = EMPTY; + suffix = llformat("%s%s%s%s",scopy,smod,sxfer,stempo); } } return suffix; @@ -2119,12 +2059,10 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name) BOOL LLFolderBridge::removeItem() { - // - //if(!isItemRemovable()) - //{ - // return FALSE; - //} - // + if(!isItemRemovable()) + { + return FALSE; + } // move it to the trash LLPreview::hide(mUUID); // derf @@ -2346,6 +2284,12 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + + + + + + if (lost_and_found_id == mUUID) { // This is the lost+found folder. @@ -2448,12 +2392,9 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { - // - //mItems.push_back(std::string("--no options--")); - //mDisabledItems.push_back(std::string("--no options--")); - mItems.push_back(std::string("Save As...")); - mItems.push_back(std::string("Save InvCache...")); - // + mItems.push_back(std::string("--no options--")); + mDisabledItems.push_back(std::string("--no options--")); + } hideContextEntries(menu, mItems, mDisabledItems); } @@ -2889,7 +2830,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // +=================================================+ -// | LLScriptBridge (DEPRECTED) | +// | LLScriptBridge (DEPRECATED) | // +=================================================+ LLUIImagePtr LLScriptBridge::getIcon() const @@ -2915,6 +2856,14 @@ void open_texture(const LLUUID& item_id, const LLUUID& source_id, BOOL take_focus) { + + + + + + + + // See if we can bring an exiting preview to the front if( !LLPreview::show( item_id, take_focus ) ) { @@ -3101,7 +3050,8 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod // because you'll probably arrive at a telehub instead if( gFloaterWorldMap ) { - gFloaterWorldMap->trackLandmark( item->getAssetUUID() ); + //Emerald claims this needs to be the item UUID, rather than the asset UUID. -HgB + gFloaterWorldMap->trackLandmark( item->getUUID() ); } } } @@ -3149,6 +3099,7 @@ static bool open_landmark_callback(const LLSD& notification, const LLSD& respons S32 option = LLNotification::getSelectedOption(notification, response); LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); + LLUUID item_id = notification["payload"]["item_id"].asUUID(); if (option == 0) { // HACK: This is to demonstrate teleport on double click for landmarks @@ -3158,7 +3109,8 @@ static bool open_landmark_callback(const LLSD& notification, const LLSD& respons // because you'll probably arrive at a telehub instead if( gFloaterWorldMap ) { - gFloaterWorldMap->trackLandmark( asset_id ); + //Emerald says this needs to be the item id instead of the asset ID. -HgB + gFloaterWorldMap->trackLandmark( item_id ); } } @@ -3177,6 +3129,7 @@ void LLLandmarkBridge::openItem() // open_landmark(item, std::string(" ") + getPrefix() + item->getName(), FALSE); LLSD payload; payload["asset_id"] = item->getAssetUUID(); + payload["item_id"] = item->getUUID(); LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); } } @@ -3423,6 +3376,14 @@ void open_notecard(LLViewerInventoryItem* inv_item, const LLUUID& source_id, BOOL take_focus) { + + + + + + + + // See if we can bring an existing preview to the front if(!LLPreview::show(inv_item->getUUID(), take_focus)) { @@ -3750,6 +3711,13 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model item = (LLViewerInventoryItem*)gInventory.getItem(object_id); if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) { + + + + + + + rez_attachment(item, NULL); } else if(item && item->isComplete()) @@ -3769,6 +3737,15 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model else if ("detach" == action) { LLInventoryItem* item = gInventory.getItem(mUUID); + + + + + + + + + if( item ) { gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); @@ -3790,6 +3767,55 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model llwarns << "object not found - ignoring" << llendl; } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + else LLItemBridge::performAction(folder, model, action); } @@ -3816,6 +3842,18 @@ void LLObjectBridge::openItem() } } + + + + + + + + + + + + LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const { LLVOAvatar* avatar = gAgent.getAvatarObject(); @@ -3877,10 +3915,32 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach if (attachment && attachment->getObject()) { + + + + + + + LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); } else { + + + + + + + + + + + + + + + LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); } } @@ -3945,6 +4005,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) return; } + if( avatarp->isWearingAttachment( mUUID ) ) { items.push_back(std::string("Detach From Yourself")); @@ -3958,6 +4019,10 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) else // // don't allow attaching objects while importing attachments + + + + //if( !isInTrash() ) if( !isInTrash() && !(LLXmlImport::sImportInProgress && LLXmlImport::sImportHasAttachments)) // @@ -3969,6 +4034,19 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // commented out for DEV-32347 //items.push_back(std::string("Restore to Last Position")); + + + + + + + + + + + + + LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); LLVOAvatar *avatarp = gAgent.getAvatarObject(); @@ -3984,6 +4062,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLMenuItemCallGL *new_item; if (attachment->getIsHUDAttachment()) { + attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), NULL, //&LLObjectBridge::attachToAvatar, NULL, &attach_label, (void*)attachment)); @@ -4085,8 +4164,29 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); } + + + + + + + + + + + + + void LLLSLTextBridge::openItem() { + + + + + + + + // See if we can bring an exiting preview to the front if(!LLPreview::show(mUUID)) { @@ -4130,6 +4230,9 @@ void wear_inventory_item_on_avatar( LLInventoryItem* item ) } } + + + struct LLFoundData { LLFoundData(const LLUUID& item_id, @@ -4163,6 +4266,7 @@ struct LLWearableHoldingPattern }; + class LLOutfitObserver : public LLInventoryFetchObserver { public: @@ -4220,6 +4324,31 @@ private: bool mAppend; }; + + + + + + + + + + + + + + + + + + + + + + + + + void LLOutfitObserver::done() { // We now have an outfit ready to be copied to agent inventory. Do @@ -4503,6 +4632,31 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) is_gesture); S32 gest_count = gest_item_array.count(); + + + + + + + + + + + + + + + + + + + + + + + + + if( !wearable_count && !obj_count && !gest_count) { LLNotifications::instance().add("CouldNotPutOnOutfit"); @@ -4540,6 +4694,9 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) // callback will be called (and this object deleted) // before the final getNextData(). LLWearableHoldingPattern* holder = new LLWearableHoldingPattern; + + + LLFoundData* found; LLDynamicArray found_container; for(i = 0; i < wearable_count; ++i) @@ -4553,8 +4710,10 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) } for(i = 0; i < wearable_count; ++i) { + gAddToOutfit = wear_info->mAppend; + found = found_container.get(i); gWearableList.getAsset(found->mAssetID, found->mName, @@ -4637,6 +4796,8 @@ void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data) LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data; BOOL append= gAddToOutfit; + + if(wearable) { for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin(); @@ -4657,6 +4818,9 @@ void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data) } } + + + void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append) { lldebugs << "wear_inventory_category_on_avatar_step3()" << llendl; @@ -4709,6 +4873,147 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B dec_busy_count(); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void remove_inventory_category_from_avatar( LLInventoryCategory* category ) { if(!category) return; @@ -4791,10 +5096,25 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) } + + + + if (obj_count > 0) { for(i = 0; i < obj_count; ++i) { + + + + + + + + + + + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); @@ -4850,6 +5170,16 @@ BOOL LLWearableBridge::isItemRemovable() return LLInvFVBridge::isItemRemovable(); } + + + + + + + + + + LLFontGL::StyleFlags LLWearableBridge::getLabelStyle() const { if( gAgent.isWearingItem( mUUID ) ) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 8920fcb20..beeb19144 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -120,6 +120,41 @@ public: } }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -253,6 +288,8 @@ public: virtual BOOL hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } + + // override for LLInvFVBridge virtual void clearDisplayName() { mDisplayName.clear(); } @@ -559,6 +596,7 @@ public: virtual const std::string& getPrefix() { return sPrefix; } virtual LLUIImagePtr getIcon() const; + virtual void openItem(); protected: diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index c483a2b49..54826d9a3 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -384,6 +384,28 @@ LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) return LLUUID::null; } +LLUUID LLInventoryModel::findCategoryByName(std::string name) +{ + LLUUID root_id = gAgent.getInventoryRootID(); + if(root_id.notNull()) + { + cat_array_t* cats = NULL; + cats = get_ptr_in_map(mParentChildCategoryTree, root_id); + if(cats) + { + S32 count = cats->count(); + for(S32 i = 0; i < count; ++i) + { + if(cats->get(i)->getName() == name) + { + return cats->get(i)->getUUID(); + } + } + } + } + return LLUUID::null; +} + // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be @@ -404,6 +426,35 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, lldebugs << "Attempt to create simstate category." << llendl; return id; } + else if(preferred_type == LLAssetType::AT_SOUND_WAV) + { + lldebugs << "Attempt to create (wave) uncompressed sound category." << llendl; + return id; + } + else if(preferred_type == LLAssetType::AT_IMAGE_TGA) + { + lldebugs << "Attempt to create a AT_IMAGE_TGA uncompresssed images category." << llendl; + return id; + } + else if(preferred_type == LLAssetType::AT_TEXTURE_TGA) + { + lldebugs << "Attempt to create a AT_TEXTURE_TGA uncompresssed images category." << llendl; + return id; + } + + else if(preferred_type == LLAssetType::AT_IMAGE_JPEG) + { + lldebugs << "Attempt to create a AT_IMAGE_JPEG uncompresssed images category." << llendl; + return id; + }else if(preferred_type == LLAssetType::AT_SCRIPT) + { + lldebugs << "Attempt to create a AT_Script scripts category." << llendl; + return id; + }else if(preferred_type == LLAssetType::AT_LSL_BYTECODE) + { + lldebugs << "Attempt to create a AT_LSL_BYTECODE scripts category." << llendl; + return id; + } id.generate(); std::string name = pname; @@ -846,14 +897,12 @@ void LLInventoryModel::deleteObject(const LLUUID& id) // folders, items, etc in a fairly efficient manner. void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) { - // "Deliberately disobeying you" derf derf - //EHasChildren children = categoryHasChildren(id); - //if(children == CHILDREN_NO) - //{ - // llinfos << "Not purging descendents of " << id << llendl; - // return; - //} - // + EHasChildren children = categoryHasChildren(id); + if(children == CHILDREN_NO) + { + llinfos << "Not purging descendents of " << id << llendl; + return; + } LLPointer cat = getCategory(id); if(cat.notNull()) { @@ -2003,6 +2052,10 @@ bool LLInventoryModel::loadSkeleton( //delete cat; // automatic when cat is reasigned or destroyed } + + + + S32 cached_category_count = 0; S32 cached_item_count = 0; if (!temp_cats.empty()) @@ -3171,6 +3224,14 @@ void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg, } } + + + + + + + + struct InventoryCallbackInfo { InventoryCallbackInfo(U32 callback, const LLUUID& inv_id) : @@ -3207,6 +3268,23 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // << llendl; if(tfolder->getUUID().notNull()) { + + + + + + + + + + + + + + + + + folders.push_back(tfolder); LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); if(folderp) diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index fe02b1d46..187ac795d 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -312,6 +312,8 @@ public: LLAssetType::EType preferred_type, const std::string& name); + LLUUID findCategoryByName(std::string name); + // methods to load up inventory skeleton & meat. These are used // during authentication. return true if everything parsed. typedef std::map response_t; diff --git a/indra/newview/llinventoryview.cpp b/indra/newview/llinventoryview.cpp index 4f9cd6068..7c239fae1 100644 --- a/indra/newview/llinventoryview.cpp +++ b/indra/newview/llinventoryview.cpp @@ -45,6 +45,7 @@ #include "llradiogroup.h" #include "llspinctrl.h" #include "lltextbox.h" + #include "llui.h" #include "llfirstuse.h" @@ -84,6 +85,7 @@ #include "llselectmgr.h" #include "llsdserialize.h" + // #include "llbuildnewviewsscheduler.h" // @@ -489,15 +491,27 @@ void LLInventoryView::init(LLInventoryModel* inventory) BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE ); BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME ); BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ); + addBoolControl("Inventory.ShowFilters", FALSE); addBoolControl("Inventory.SortByName", sort_by_name ); addBoolControl("Inventory.SortByDate", ! sort_by_name ); addBoolControl("Inventory.FoldersAlwaysByName", sort_folders_by_name ); addBoolControl("Inventory.SystemFoldersToTop", sort_system_folders_to_top ); - addBoolControl("Inventory.SearchName", TRUE); - addBoolControl("Inventory.SearchDesc", FALSE); - addBoolControl("Inventory.SearchCreator", FALSE); + + U32 search_type = gSavedPerAccountSettings.getU32("rkeastInventorySearchType"); + BOOL search_by_name = (search_type == 0); + + addBoolControl("Inventory.SearchByName", search_by_name); + addBoolControl("Inventory.SearchByCreator", !search_by_name); + addBoolControl("Inventory.SearchByDesc", !search_by_name); + + addBoolControl("Inventory.SearchByAll", !search_by_name); + + //Bool for toggling the partial search results - RKeast + BOOL partial_search = gSavedPerAccountSettings.getBOOL("rkeastInventoryPartialSearch"); + + addBoolControl("Inventory.PartialSearchToggle", partial_search); mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); @@ -511,6 +525,11 @@ void LLInventoryView::init(LLInventoryModel* inventory) if (mActivePanel) { // "All Items" is the previous only view, so it gets the InventorySortOrder + + //Fix for gSavedSettings use - rkeast + mActivePanel->getFilter()->setSearchType(search_type); + mActivePanel->getFilter()->setPartialSearch(partial_search); + mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder")); mActivePanel->getFilter()->markDefault(); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -520,15 +539,16 @@ void LLInventoryView::init(LLInventoryModel* inventory) if (recent_items_panel) { recent_items_panel->setSinceLogoff(TRUE); - recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); + recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); recent_items_panel->getFilter()->markDefault(); recent_items_panel->setSelectCallback(onSelectionChange, recent_items_panel); } + LLInventoryPanel* worn_items_panel = getChild("Worn Items"); if (worn_items_panel) { - worn_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::WORNITEMS_SORT_ORDER)); + worn_items_panel->setSortOrder(gSavedSettings.getU32("InventorySortOrder")); worn_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); worn_items_panel->getFilter()->markDefault(); worn_items_panel->setFilterWorn(true); @@ -560,11 +580,22 @@ void LLInventoryView::init(LLInventoryModel* inventory) } + //Initialize item count - rkeast + mItemCount = gSavedPerAccountSettings.getS32("rkeastInventoryPreviousCount"); + + mSearchEditor = getChild("inventory search editor"); if (mSearchEditor) { mSearchEditor->setSearchCallback(onSearchEdit, this); } + + mQuickFilterCombo = getChild("Quick Filter"); + + if (mQuickFilterCombo) + { + mQuickFilterCombo->setCommitCallback(onQuickFilterCommit); + } sActiveViews.put(this); @@ -576,6 +607,7 @@ BOOL LLInventoryView::postBuild() childSetTabChangeCallback("inventory filter tabs", "All Items", onFilterSelected, this); childSetTabChangeCallback("inventory filter tabs", "Recent Items", onFilterSelected, this); childSetTabChangeCallback("inventory filter tabs", "Worn Items", onFilterSelected, this); + //panel->getFilter()->markDefault(); return TRUE; } @@ -644,6 +676,12 @@ void LLInventoryView::draw() { mSearchEditor->setText(mActivePanel->getFilterSubString()); } + + if (mActivePanel && mQuickFilterCombo) + { + refreshQuickFilter( mQuickFilterCombo ); + } + LLFloater::draw(); } @@ -793,8 +831,24 @@ void LLInventoryView::changed(U32 mask) LLLocale locale(LLLocale::USER_LOCALE); std::string item_count_string; LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount()); - title << " (Fetched " << item_count_string << " items...)"; + + //Displays a progress indication for loading the inventory, but not if it hasn't been loaded before on this PC, or we load more than expected - rkeast + if(mItemCount == -1) + { + title << " (Fetched " << item_count_string << " items...)"; + } + else + { + S32 remaining = mItemCount - gInventory.getItemCount(); + std::string total_items; + std::string items_remaining; + LLResMgr::getInstance()->getIntegerString(total_items, mItemCount); + LLResMgr::getInstance()->getIntegerString(items_remaining, remaining); + if(remaining < 0) title << " (Fetched " << item_count_string << " items...)"; + else title << " (Fetched " << item_count_string << " items of ~" << total_items << " - ~" << items_remaining << " remaining...)"; + } } + else gSavedPerAccountSettings.setS32("rkeastInventoryPreviousCount", gInventory.getItemCount()); title << mFilterText; setTitle(title.str()); @@ -1020,6 +1074,236 @@ void LLInventoryView::onSearchEdit(const std::string& search_string, void* user_ self->mActivePanel->setFilterSubString(uppercase_search_string); } +//static +void LLInventoryView::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data) +{ + + LLComboBox* quickfilter = (LLComboBox*)ctrl; + + + LLInventoryView* view = (LLInventoryView*)(quickfilter->getParent()); + if (!view->mActivePanel) + { + return; + } + + + std::string item_type = quickfilter->getSimple(); + U32 filter_type; + + if (view->getString("filter_type_animation") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_ANIMATION; + } + + else if (view->getString("filter_type_callingcard") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_CALLINGCARD; + } + + else if (view->getString("filter_type_wearable") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_WEARABLE; + } + + else if (view->getString("filter_type_gesture") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_GESTURE; + } + + else if (view->getString("filter_type_landmark") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_LANDMARK; + } + + else if (view->getString("filter_type_notecard") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_NOTECARD; + } + + else if (view->getString("filter_type_object") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_OBJECT; + } + + else if (view->getString("filter_type_script") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_LSL; + } + + else if (view->getString("filter_type_sound") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_SOUND; + } + + else if (view->getString("filter_type_texture") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_TEXTURE; + } + + else if (view->getString("filter_type_snapshot") == item_type) + { + filter_type = 0x1 << LLInventoryType::IT_SNAPSHOT; + } + + else if (view->getString("filter_type_custom") == item_type) + { + // When they select custom, show the floater then return + if( !(view->filtersVisible(view)) ) + { + view->toggleFindOptions(); + } + return; + } + + else if (view->getString("filter_type_all") == item_type) + { + // Show all types + filter_type = 0xffffffff; + } + + else + { + llwarns << "Ignoring unknown filter: " << item_type << llendl; + return; + } + + view->mActivePanel->setFilterTypes( filter_type ); + + + // Force the filters window to update itself, if it's open. + LLInventoryViewFinder* finder = view->getFinder(); + if( finder ) + { + finder->updateElementsFromFilter(); + } + + // llinfos << "Quick Filter: " << item_type << llendl; + +} + + + +//static +void LLInventoryView::refreshQuickFilter(LLUICtrl* ctrl) +{ + + LLInventoryView* view = (LLInventoryView*)(ctrl->getParent()); + if (!view->mActivePanel) + { + return; + } + + LLComboBox* quickfilter = view->getChild("Quick Filter"); + if (!quickfilter) + { + return; + } + + + U32 filter_type = view->mActivePanel->getFilterTypes(); + + + // Mask to extract only the bit fields we care about. + // *TODO: There's probably a cleaner way to construct this mask. + U32 filter_mask = 0; + filter_mask |= (0x1 << LLInventoryType::IT_ANIMATION); + filter_mask |= (0x1 << LLInventoryType::IT_CALLINGCARD); + filter_mask |= (0x1 << LLInventoryType::IT_WEARABLE); + filter_mask |= (0x1 << LLInventoryType::IT_GESTURE); + filter_mask |= (0x1 << LLInventoryType::IT_LANDMARK); + filter_mask |= (0x1 << LLInventoryType::IT_NOTECARD); + filter_mask |= (0x1 << LLInventoryType::IT_OBJECT); + filter_mask |= (0x1 << LLInventoryType::IT_LSL); + filter_mask |= (0x1 << LLInventoryType::IT_SOUND); + filter_mask |= (0x1 << LLInventoryType::IT_TEXTURE); + filter_mask |= (0x1 << LLInventoryType::IT_SNAPSHOT); + + + filter_type &= filter_mask; + + + //llinfos << "filter_type: " << filter_type << llendl; + + std::string selection; + + + if (filter_type == filter_mask) + { + selection = view->getString("filter_type_all"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_ANIMATION)) + { + selection = view->getString("filter_type_animation"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_CALLINGCARD)) + { + selection = view->getString("filter_type_callingcard"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_WEARABLE)) + { + selection = view->getString("filter_type_wearable"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_GESTURE)) + { + selection = view->getString("filter_type_gesture"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_LANDMARK)) + { + selection = view->getString("filter_type_landmark"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_NOTECARD)) + { + selection = view->getString("filter_type_notecard"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_OBJECT)) + { + selection = view->getString("filter_type_object"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_LSL)) + { + selection = view->getString("filter_type_script"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_SOUND)) + { + selection = view->getString("filter_type_sound"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_TEXTURE)) + { + selection = view->getString("filter_type_texture"); + } + + else if (filter_type == (0x1 << LLInventoryType::IT_SNAPSHOT)) + { + selection = view->getString("filter_type_snapshot"); + } + + else + { + selection = view->getString("filter_type_custom"); + } + + + // Select the chosen item by label text + BOOL result = quickfilter->setSimple( (selection) ); + + if( !result ) + { + llinfos << "The item didn't exist: " << selection << llendl; + } + +} + // static // BOOL LLInventoryView::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward) @@ -1400,6 +1684,30 @@ void LLInventoryPanel::draw() LLPanel::draw(); } +//fix to get rid of gSavedSettings use - rkeast +void LLInventoryPanel::setPartialSearch(bool toggle) +{ + mFolders->getFilter()->setPartialSearch(toggle); +} + +//fix to get rid of gSavedSettings use - rkeast +bool LLInventoryPanel::getPartialSearch() +{ + return mFolders->getFilter()->getPartialSearch(); +} + +//fix to get rid of gSavedSettings use - rkeast +void LLInventoryPanel::setSearchType(U32 type) +{ + mFolders->getFilter()->setSearchType(type); +} + +//fix to get rid of gSavedSettings use - rkeast +U32 LLInventoryPanel::getSearchType() +{ + return mFolders->getFilter()->getSearchType(); +} + void LLInventoryPanel::setFilterTypes(U32 filter_types) { mFolders->getFilter()->setFilterTypes(filter_types); @@ -1590,6 +1898,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) { llwarns << "LLInventoryPanel::buildNewViews called with objectp->mType == " << ((S32) objectp->getType()) + << " for object " << objectp->getName() << " (shouldn't happen)" << llendl; } else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category diff --git a/indra/newview/llinventoryview.h b/indra/newview/llinventoryview.h index ea015d52d..48afb16d5 100644 --- a/indra/newview/llinventoryview.h +++ b/indra/newview/llinventoryview.h @@ -59,6 +59,7 @@ class LLCheckBoxCtrl; class LLSpinCtrl; class LLScrollableContainerView; class LLTextBox; +class LLComboBox; class LLIconCtrl; class LLSaveFolderState; class LLSearchEditor; @@ -100,6 +101,12 @@ public: EAcceptance* accept, std::string& tooltip_msg); + //fix to get rid of gSavedSettings use - rkeast + void setPartialSearch(bool toggle); + bool getPartialSearch(); + void setSearchType(U32 type); + U32 getSearchType(); + // Call this method to set the selection. void openAllFolders(); void closeAllFolders(); @@ -229,7 +236,35 @@ public: static void toggleVisibility(); static void toggleVisibility(void*) { toggleVisibility(); } - // Final cleanup, destroy all open inventory views. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Final cleanup, destroy all open inventory views. static void cleanup(); // LLView & LLFloater functionality @@ -253,6 +288,10 @@ public: static void onFoldersByName(void *user_data); static BOOL checkFoldersByName(void *user_data); static void onSearchEdit(const std::string& search_string, void* user_data ); + + static void onQuickFilterCommit(LLUICtrl* ctrl, void* user_data); + static void refreshQuickFilter(LLUICtrl* ctrl); + static void onFilterSelected(void* userdata, bool from_click); static void onSelectionChange(const std::deque &items, BOOL user_action, void* data); @@ -274,13 +313,16 @@ protected: protected: LLSearchEditor* mSearchEditor; + LLComboBox* mQuickFilterCombo; LLTabContainer* mFilterTabs; - LLHandle mFinderHandle; + LLHandle mFinderHandle; LLInventoryPanel* mActivePanel; LLSaveFolderState* mSavedFolderState; std::string mFilterText; + S32 mItemCount; + // This container is used to hold all active inventory views. This // is here to support the inventory toggle show button. diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 8a8d76648..a0b60f57f 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -379,7 +379,7 @@ void LLNetMap::draw() avColor, pos_map.mV[VZ], mDotRadius); - // + F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist) { diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 0d6b757cc..b8d2a2b1a 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -538,7 +538,7 @@ void LLNotifyBox::format(std::string& msg, const LLStringUtil::format_map_t& arg // XUI:translate! LLStringUtil::format_map_t targs = args; targs["[SECOND_LIFE]"] = "Second Life"; - targs["[VIEWER_NAME]"] = "Snowglobe"; + targs["[VIEWER_NAME]"] = "Ascent"; LLStringUtil::format(msg, targs); } diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp index ddd3781a9..ed07d1825 100644 --- a/indra/newview/llpanelgeneral.cpp +++ b/indra/newview/llpanelgeneral.cpp @@ -66,7 +66,7 @@ BOOL LLPanelGeneral::postBuild() childSetValue("afk_timeout_spinner", gSavedSettings.getF32("AFKTimeout")); childSetValue("notify_money_change_checkbox", gSavedSettings.getBOOL("NotifyMoneyChange")); - getChild("effect_color_swatch")->set(gSavedSettings.getColor4("EffectColor")); + childSetValue("ui_scale_slider", gSavedSettings.getF32("UIScaleFactor")); childSetValue("ui_auto_scale", gSavedSettings.getBOOL("UIAutoScale")); @@ -126,7 +126,8 @@ void LLPanelGeneral::apply() gSavedSettings.setBOOL("RenderHideGroupTitle", childGetValue("show_my_title_checkbox")); gSavedSettings.setF32("AFKTimeout", childGetValue("afk_timeout_spinner").asReal()); gSavedSettings.setBOOL("NotifyMoneyChange", childGetValue("notify_money_change_checkbox")); - gSavedSettings.setColor4("EffectColor", childGetValue("effect_color_swatch")); + + gSavedSettings.setF32("UIScaleFactor", childGetValue("ui_scale_slider").asReal()); gSavedSettings.setBOOL("UIAutoScale", childGetValue("ui_auto_scale")); gSavedSettings.setString("Language", childGetValue("language_combobox")); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index cbf4a8740..962ab5d47 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -48,11 +48,13 @@ #include "lllineeditor.h" #include "llnamebox.h" #include "llnamelistctrl.h" +#include "llnameeditor.h" #include "llspinctrl.h" #include "llstatusbar.h" // can_afford_transaction() #include "lltextbox.h" #include "lltexteditor.h" #include "lltexturectrl.h" +#include "llviewercontrol.h" #include "llviewerwindow.h" // consts @@ -75,9 +77,9 @@ LLPanelGroupGeneral::LLPanelGroupGeneral(const std::string& name, mChanged(FALSE), mFirstUse(TRUE), mGroupNameEditor(NULL), - mGroupName(NULL), mFounderName(NULL), mInsignia(NULL), + mGroupName(NULL), mEditCharter(NULL), mBtnJoinGroup(NULL), mListVisibleMembers(NULL), @@ -255,6 +257,9 @@ BOOL LLPanelGroupGeneral::postBuild() mGroupName->setVisible(FALSE); } + + + return LLPanelGroupTab::postBuild(); } @@ -757,6 +762,12 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if (mGroupName) mGroupName->setText(gdatap->mName); if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE); if (mFounderName) mFounderName->setNameID(gdatap->mFounderID,FALSE); + + + + + + if (mInsignia) { if (gdatap->mInsigniaID.notNull()) @@ -843,16 +854,19 @@ void LLPanelGroupGeneral::updateMembers() row["columns"][0]["column"] = "name"; row["columns"][0]["font-style"] = style; + // value is filled in by name list control row["columns"][1]["column"] = "title"; row["columns"][1]["value"] = member->getTitle(); row["columns"][1]["font-style"] = style; + row["columns"][2]["column"] = "online"; row["columns"][2]["value"] = member->getOnlineStatus(); row["columns"][2]["font-style"] = style; + sSDTime += sd_timer.getElapsedTimeF32(); element_timer.reset(); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 5b370e99b..d196a5c23 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -366,142 +366,45 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, refreshLocation( false ); #endif - // - std::string specified_channel = gSavedSettings.getString("SpecifiedChannel"); - getChild("channel_edit")->setText(specified_channel); - - bool specify_mac = gSavedSettings.getBOOL("SpecifyMAC"); - bool specify_id0 = gSavedSettings.getBOOL("SpecifyID0"); - std::string specified_mac = gSavedSettings.getString("SpecifiedMAC"); - std::string specified_id0 = gSavedSettings.getString("SpecifiedID0"); - - // Don't allow specify for empty strings (just in case) - if(specified_mac.length() == 0) specify_mac = false; - if(specified_id0.length() == 0) specify_id0 = false; - - gSavedSettings.setBOOL("SpecifyMAC", specify_mac); - gSavedSettings.setBOOL("SpecifyID0", specify_id0); - - getChild("mac_check")->setValue(specify_mac); - getChild("mac_edit")->setEnabled(specify_mac); - getChild("id0_check")->setValue(specify_id0); - getChild("id0_edit")->setEnabled(specify_id0); - - childSetEnabled("mac_random_btn",specify_mac); - childSetEnabled("id0_random_btn",specify_id0); - - fillMAC(); - fillID0(); - fillVer(); - - childSetCommitCallback("mac_check", onCheckMAC, this); - childSetCommitCallback("id0_check", onCheckID0, this); - childSetAction("mac_random_btn", onClickMACRandom, this); - childSetAction("id0_random_btn", onClickID0Random, this); - // } // void LLPanelLogin::fillMAC() { - if(gSavedSettings.getBOOL("SpecifyMAC")) - { - getChild("mac_edit")->setText(gSavedSettings.getString("SpecifiedMAC")); - } - else - { - char hashed_mac_string[MD5HEX_STR_SIZE]; - LLMD5 hashed_mac; - hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); - hashed_mac.finalize(); - hashed_mac.hex_digest(hashed_mac_string); - getChild("mac_edit")->setText(std::string(hashed_mac_string)); - } + } void LLPanelLogin::fillID0() { - if(gSavedSettings.getBOOL("SpecifyID0")) - { - getChild("id0_edit")->setText(gSavedSettings.getString("SpecifiedID0")); - } - else - { - getChild("id0_edit")->setText(LLAppViewer::instance()->getSerialNumber()); - } + } void LLPanelLogin::fillVer() { - getChild("vermaj_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionMaj")); - getChild("vermin_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionMin")); - getChild("verpatch_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionPatch")); - - //simple hack to stop bans based on specific versions, 257 is a reasonable upper limit for a build number. - if(gSavedSettings.getU32("SpecifiedVersionBuild") == 100000) - gSavedSettings.setU32("SpecifiedVersionBuild", ll_rand(257)); - - getChild("verbuild_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionBuild")); } // static void LLPanelLogin::onCheckMAC(LLUICtrl* ctrl, void* userData) { - LLPanelLogin* panel = (LLPanelLogin*)userData; - bool enabled = ((LLCheckBoxCtrl*)ctrl)->getValue(); - gSavedSettings.setBOOL("SpecifyMAC", enabled); - panel->getChild("mac_edit")->setEnabled(enabled); - panel->childSetEnabled("mac_random_btn",enabled); - panel->fillMAC(); + } // static void LLPanelLogin::onCheckID0(LLUICtrl* ctrl, void* userData) { - LLPanelLogin* panel = (LLPanelLogin*)userData; - bool enabled = ((LLCheckBoxCtrl*)ctrl)->getValue(); - gSavedSettings.setBOOL("SpecifyID0", enabled); - panel->getChild("id0_edit")->setEnabled(enabled); - panel->childSetEnabled("id0_random_btn",enabled); - panel->fillID0(); + } // static void LLPanelLogin::onClickMACRandom(void* userData) { - LLPanelLogin* panel = (LLPanelLogin*)userData; - unsigned char seed[16]; /* Flawfinder: ignore */ - LLUUID::getNodeID(&seed[0]); - seed[6]='U'; - seed[7]='W'; - LLUUID::getSystemTime((uuid_time_t *)(&seed[8])); - char hash_string[MD5HEX_STR_SIZE]; - LLMD5 hash; - hash.update( seed , 16 ); - hash.finalize(); - hash.hex_digest(hash_string); - gSavedSettings.setString("SpecifiedMAC",std::string(hash_string)); - panel->fillMAC(); } // static void LLPanelLogin::onClickID0Random(void* userData) { - LLPanelLogin* panel = (LLPanelLogin*)userData; - unsigned char seed[16]; /* Flawfinder: ignore */ - LLUUID::getNodeID(&seed[0]); - seed[6]='W'; - seed[7]='U'; - LLUUID::getSystemTime((uuid_time_t *)(&seed[8])); - char hash_string[MD5HEX_STR_SIZE]; - LLMD5 hash; - hash.update( seed , 16 ); - hash.finalize(); - hash.hex_digest(hash_string); - gSavedSettings.setString("SpecifiedID0",std::string(hash_string)); - panel->fillID0(); } // @@ -1234,58 +1137,7 @@ void LLPanelLogin::onClickConnect(void *) { if (sInstance && sInstance->mCallback) { - // - if(gMessageSystem) - { - //IP spoofing protection only really works on the LL's grids - if(LLViewerLogin::getInstance()->getGridChoice() < GRID_INFO_LOCAL) - gMessageSystem->startSpoofProtection(gSavedSettings.getU32("SpoofProtectionLevel")); - else - gMessageSystem->startSpoofProtection(0); - gMessageSystem->setSpoofDroppedCallback(spoof_dropped_callback); - } - - // save identity settings for login - bool specify_mac = sInstance->getChild("mac_check")->getValue(); - bool specify_id0 = sInstance->getChild("id0_check")->getValue(); - - gSavedSettings.setBOOL("SpecifyMAC", specify_mac); - gSavedSettings.setBOOL("SpecifyID0", specify_id0); - - if(specify_mac) - { - std::string specified_mac = sInstance->getChild("mac_edit")->getText(); - gSavedSettings.setString("SpecifiedMAC", specified_mac); - } - - if(specify_id0) - { - std::string specified_id0 = sInstance->getChild("id0_edit")->getText(); - gSavedSettings.setString("SpecifiedID0", specified_id0); - } - - std::string specified_channel = sInstance->getChild("channel_edit")->getText(); - - //make sure they aren't using one of using Emerald's channels (or one that they think is) - std::string test_channel = specified_channel; - - std::transform(test_channel.begin(), test_channel.end(), test_channel.begin(), toupper); - - if(test_channel.find( "EMERALD", 0 ) != std::string::npos - || test_channel.find( "GREENLIFE", 0 ) != std::string::npos) - { - LLSD args; - args["MESSAGE"] = std::string("Normally one changes the channel to avoid detection.\n\n") + - std::string("A lot of the people working on client detection also work on Emerald in some capacity\n\n") + - std::string("They can detect people spoofing Emerald. Choose another channel name."); - - LLNotifications::instance().add("GenericAlert", args); - - return; - } - - gSavedSettings.setString("SpecifiedChannel", specified_channel); U32 specified_ver_maj = (U32)sInstance->getChild("vermaj_spin")->getValue().asInteger(); gSavedSettings.setU32("SpecifiedVersionMaj", specified_ver_maj); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 2e750759c..bc103b913 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -47,6 +47,7 @@ // project includes #include "llagent.h" #include "llbutton.h" +#include "llcalc.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" #include "llcombobox.h" @@ -75,6 +76,10 @@ #include "lldrawpool.h" + + + + // // Constants // @@ -104,6 +109,15 @@ enum { MI_VOLUME_COUNT }; + + + + + + + + + enum { MI_HOLE_SAME, MI_HOLE_CIRCLE, @@ -115,6 +129,12 @@ enum { //*TODO:translate (depricated, so very low priority) static const std::string LEGACY_FULLBRIGHT_DESC("Fullbright (Legacy)"); +LLVector3 LLPanelObject::mClipboardPos; +LLVector3 LLPanelObject::mClipboardSize; +LLVector3 LLPanelObject::mClipboardRot; +LLVolumeParams LLPanelObject::mClipboardVolumeParams; +BOOL LLPanelObject::hasParamClipboard = FALSE; + BOOL LLPanelObject::postBuild() { setMouseOpaque(FALSE); @@ -131,12 +151,6 @@ BOOL LLPanelObject::postBuild() mCheckPhysics = getChild("Physical Checkbox Ctrl"); childSetCommitCallback("Physical Checkbox Ctrl",onCommitPhysics,this); - //Blink [SimmanFederal] Inspired by VLife/Oynx - mClickBlink = getChild("button blink"); - childSetAction("button blink",&onClickBlink,this); - mClickHardBlink = getChild("button blink hard"); - childSetAction("button blink hard",&onClickHardBlink,this); - // Temporary checkbox mCheckTemporary = getChild("Temporary Checkbox Ctrl"); childSetCommitCallback("Temporary Checkbox Ctrl",onCommitTemporary,this); @@ -176,6 +190,32 @@ BOOL LLPanelObject::postBuild() mCtrlRotZ = getChild("Rot Z"); childSetCommitCallback("Rot Z",onCommitRotation,this); + mBtnCopyPos = getChild("copypos"); + childSetAction("copypos",onCopyPos, this); + mBtnPastePos = getChild("pastepos"); + childSetAction("pastepos",onPastePos, this); + mBtnPastePosClip = getChild("pasteposclip"); + childSetAction("pasteposclip",onPastePosClip, this); + + mBtnCopySize = getChild("copysize"); + childSetAction("copysize",onCopySize, this); + mBtnPasteSize = getChild("pastesize"); + childSetAction("pastesize",onPasteSize, this); + mBtnPasteSizeClip = getChild("pastesizeclip"); + childSetAction("pastesizeclip",onPasteSizeClip, this); + + mBtnCopyRot = getChild("copyrot"); + childSetAction("copyrot",onCopyRot, this); + mBtnPasteRot = getChild("pasterot"); + childSetAction("pasterot",onPasteRot, this); + mBtnPasteRotClip = getChild("pasterotclip"); + childSetAction("pasterotclip",onPasteRotClip, this); + + mBtnCopyParams = getChild("copyparams"); + childSetAction("copyparams",onCopyParams, this); + mBtnPasteParams = getChild("pasteparams"); + childSetAction("pasteparams",onPasteParams, this); + //-------------------------------------------------------- // material type popup @@ -324,6 +364,11 @@ BOOL LLPanelObject::postBuild() mCtrlSculptInvert = getChild("sculpt invert control"); childSetCommitCallback("sculpt invert control", onCommitSculptType, this); + + + + + // Start with everyone disabled clearCtrls(); @@ -346,6 +391,33 @@ LLPanelObject::~LLPanelObject() // Children all cleaned up by default view destructor. } +const LLUUID& LLPanelObject::findItemID(const LLUUID& asset_id) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(asset_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + if (items.count()) + { + // search for copyable version first + for (S32 i = 0; i < items.count(); i++) + { + LLInventoryItem* itemp = items[i]; + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + { + return itemp->getUUID(); + } + } + } + return LLUUID::null; +} + void LLPanelObject::getState( ) { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); @@ -369,6 +441,8 @@ void LLPanelObject::getState( ) } } + LLCalc* calcp = LLCalc::getInstance(); + LLVOVolume *volobjp = NULL; if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) { @@ -385,30 +459,14 @@ void LLPanelObject::getState( ) // Disable all text input fields clearCtrls(); + calcp->clearAllVariables(); return; } // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - // - // Enables position, size, and rotation textboxes - // but they're also editable - // No arrow crap though - /* BOOL enable_move = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); BOOL enable_scale = objectp->permMove() && objectp->permModify(); BOOL enable_rotate = objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); - */ - BOOL enable_move = TRUE; - BOOL enable_scale = TRUE; - BOOL enable_rotate = TRUE; - // - - //[SimmanFederal]: Adding permission check to see if we can even BLINK anything not just atempting to blink even no mod sheit. - //Also a link check. (lol from the orginal enable_move bool <3) - BOOL sfBlinkOk = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); - childSetEnabled("button blink", sfBlinkOk); - childSetEnabled("button blink hard", sfBlinkOk); - //[/SimmanFederal] S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) @@ -421,6 +479,15 @@ void LLPanelObject::getState( ) enable_rotate = FALSE; } + + + + + + + + + LLVector3 vec; if (enable_move) { @@ -428,12 +495,18 @@ void LLPanelObject::getState( ) mCtrlPosX->set( vec.mV[VX] ); mCtrlPosY->set( vec.mV[VY] ); mCtrlPosZ->set( vec.mV[VZ] ); + calcp->setVar(LLCalc::X_POS, vec.mV[VX]); + calcp->setVar(LLCalc::Y_POS, vec.mV[VY]); + calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]); } else { mCtrlPosX->clear(); mCtrlPosY->clear(); mCtrlPosZ->clear(); + calcp->clearVar(LLCalc::X_POS); + calcp->clearVar(LLCalc::Y_POS); + calcp->clearVar(LLCalc::Z_POS); } @@ -441,6 +514,9 @@ void LLPanelObject::getState( ) mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); mCtrlPosZ->setEnabled(enable_move); + mBtnCopyPos->setEnabled(enable_move); + mBtnPastePos->setEnabled(enable_move); + mBtnPastePosClip->setEnabled(enable_move); if (enable_scale) { @@ -448,18 +524,27 @@ void LLPanelObject::getState( ) mCtrlScaleX->set( vec.mV[VX] ); mCtrlScaleY->set( vec.mV[VY] ); mCtrlScaleZ->set( vec.mV[VZ] ); + calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]); + calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]); + calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]); } else { mCtrlScaleX->clear(); mCtrlScaleY->clear(); mCtrlScaleZ->clear(); + calcp->setVar(LLCalc::X_SCALE, 0.f); + calcp->setVar(LLCalc::Y_SCALE, 0.f); + calcp->setVar(LLCalc::Z_SCALE, 0.f); } mLabelSize->setEnabled( enable_scale ); mCtrlScaleX->setEnabled( enable_scale ); mCtrlScaleY->setEnabled( enable_scale ); mCtrlScaleZ->setEnabled( enable_scale ); + mBtnCopySize->setEnabled( enable_scale ); + mBtnPasteSize->setEnabled( enable_scale ); + mBtnPasteSizeClip->setEnabled( enable_scale ); LLQuaternion object_rot = objectp->getRotationEdit(); object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ])); @@ -473,18 +558,30 @@ void LLPanelObject::getState( ) mCtrlRotX->set( mCurEulerDegrees.mV[VX] ); mCtrlRotY->set( mCurEulerDegrees.mV[VY] ); mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] ); + calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]); + calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]); + calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]); } else { mCtrlRotX->clear(); mCtrlRotY->clear(); mCtrlRotZ->clear(); + calcp->clearVar(LLCalc::X_ROT); + calcp->clearVar(LLCalc::Y_ROT); + calcp->clearVar(LLCalc::Z_ROT); } mLabelRotation->setEnabled( enable_rotate ); mCtrlRotX->setEnabled( enable_rotate ); mCtrlRotY->setEnabled( enable_rotate ); mCtrlRotZ->setEnabled( enable_rotate ); + mBtnCopyRot->setEnabled( enable_rotate ); + mBtnPasteRot->setEnabled( enable_rotate ); + mBtnPasteRotClip->setEnabled( enable_rotate ); + + mBtnCopyParams->setEnabled( single_volume ); + mBtnPasteParams->setEnabled( single_volume ); BOOL owners_identical; LLUUID owner_id; @@ -493,15 +590,7 @@ void LLPanelObject::getState( ) // BUG? Check for all objects being editable? S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); - // - // Makes status and material available - // I would like it if they were semi-gray, you could copy the value, - // but not editable - - //BOOL editable = root_objectp->permModify(); - BOOL editable = TRUE; - - // + BOOL editable = root_objectp->permModify(); // Select Single Message childSetVisible("select_single", FALSE); @@ -807,7 +896,7 @@ void LLPanelObject::getState( ) // Hollowness F32 hollow = volume_params.getHollow(); mSpinHollow->set( 100.f * hollow ); - + calcp->setVar(LLCalc::HOLLOW, hollow); // All hollow objects allow a shape to be selected. if (hollow > 0.f) { @@ -862,6 +951,10 @@ void LLPanelObject::getState( ) mSpinCutEnd ->set( cut_end ); mCtrlPathBegin ->set( adv_cut_begin ); mCtrlPathEnd ->set( adv_cut_end ); + calcp->setVar(LLCalc::CUT_BEGIN, cut_begin); + calcp->setVar(LLCalc::CUT_END, cut_end); + calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin); + calcp->setVar(LLCalc::PATH_END, adv_cut_end); // Twist F32 twist = volume_params.getTwist(); @@ -883,22 +976,29 @@ void LLPanelObject::getState( ) mSpinTwist ->set( twist ); mSpinTwistBegin ->set( twist_begin ); + calcp->setVar(LLCalc::TWIST_END, twist); + calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin); // Shear F32 shear_x = volume_params.getShearX(); F32 shear_y = volume_params.getShearY(); mSpinShearX->set( shear_x ); mSpinShearY->set( shear_y ); + calcp->setVar(LLCalc::X_SHEAR, shear_x); + calcp->setVar(LLCalc::Y_SHEAR, shear_y); // Taper F32 taper_x = volume_params.getTaperX(); F32 taper_y = volume_params.getTaperY(); mSpinTaperX->set( taper_x ); mSpinTaperY->set( taper_y ); + calcp->setVar(LLCalc::X_TAPER, taper_x); + calcp->setVar(LLCalc::Y_TAPER, taper_y); // Radius offset. F32 radius_offset = volume_params.getRadiusOffset(); // Limit radius offset, based on taper and hole size y. + /* DISREGARD THAT LET'S GET CRAZY -HgB F32 radius_mag = fabs(radius_offset); F32 hole_y_mag = fabs(scale_y); F32 taper_y_mag = fabs(taper_y); @@ -923,15 +1023,19 @@ void LLPanelObject::getState( ) radius_offset = max_radius_mag; } } + */ mSpinRadiusOffset->set( radius_offset); + calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset); // Revolutions F32 revolutions = volume_params.getRevolutions(); mSpinRevolutions->set( revolutions ); + calcp->setVar(LLCalc::REVOLUTIONS, revolutions); // Skew F32 skew = volume_params.getSkew(); // Limit skew, based on revolutions hole size x. + /* SUCKS... NEVER MIND -HgB F32 skew_mag= fabs(skew); F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); // Discontinuity; A revolution of 1 allows skews below 0.5. @@ -951,7 +1055,9 @@ void LLPanelObject::getState( ) skew = min_skew_mag; } } + */ mSpinSkew->set( skew ); + calcp->setVar(LLCalc::SKEW, skew); } // Compute control visibility, label names, and twist range. @@ -1092,6 +1198,8 @@ void LLPanelObject::getState( ) case MI_RING: mSpinScaleX->set( scale_x ); mSpinScaleY->set( scale_y ); + calcp->setVar(LLCalc::X_HOLE, scale_x); + calcp->setVar(LLCalc::Y_HOLE, scale_y); mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE); mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X); mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE); @@ -1100,17 +1208,32 @@ void LLPanelObject::getState( ) default: if (editable) { + + + + + + + mSpinScaleX->set( 1.f - scale_x ); mSpinScaleY->set( 1.f - scale_y ); mSpinScaleX->setMinValue(-1.f); mSpinScaleX->setMaxValue(1.f); mSpinScaleY->setMinValue(-1.f); mSpinScaleY->setMaxValue(1.f); + // Torus' Hole Size is Box/Cyl/Prism's Taper + calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x); + calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y); + + // Box/Cyl/Prism have no hole size + calcp->setVar(LLCalc::X_HOLE, scale_x); + calcp->setVar(LLCalc::Y_HOLE, scale_y); } break; } // Check if we need to limit the hollow based on the hole type. + /* NO, GO NUTS -HgB if ( selected_hole == MI_HOLE_SQUARE && ( selected_item == MI_CYLINDER || selected_item == MI_TORUS || selected_item == MI_PRISM || selected_item == MI_RING || @@ -1119,10 +1242,11 @@ void LLPanelObject::getState( ) mSpinHollow->setMinValue(0.f); mSpinHollow->setMaxValue(70.f); } - else + else + */ { mSpinHollow->setMinValue(0.f); - mSpinHollow->setMaxValue(95.f); + mSpinHollow->setMaxValue(95.f); //Not that nuts. -HgB } // Update field enablement @@ -1255,6 +1379,9 @@ void LLPanelObject::getState( ) mCtrlSculptInvert->setVisible(sculpt_texture_visible); + + + // sculpt texture if (selected_item == MI_SCULPT) @@ -1282,6 +1409,9 @@ void LLPanelObject::getState( ) mTextureCtrl->setImageAssetID(LLUUID::null); } + + + U8 sculpt_type = sculpt_params->getSculptType(); U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; @@ -1311,6 +1441,11 @@ void LLPanelObject::getState( ) } } } + + + + + else { mSculptTextureRevert = LLUUID::null; @@ -1474,10 +1609,91 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) // Figure out what type of volume to make S32 was_selected_type = mSelectedType; S32 selected_type = mComboBaseType->getCurrentIndex(); + mComboBaseType->getValue(); U8 profile; U8 path; switch ( selected_type ) { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + case MI_CYLINDER: profile = LL_PCODE_PROFILE_CIRCLE; path = LL_PCODE_PATH_LINE; @@ -1653,6 +1869,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) // Hollowness F32 hollow = mSpinHollow->get() / 100.f; + /* DUTCH PORN MODE -HgB if ( selected_hole == MI_HOLE_SQUARE && ( selected_type == MI_CYLINDER || selected_type == MI_TORUS || selected_type == MI_PRISM || selected_type == MI_RING || @@ -1660,6 +1877,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) { if (hollow > 0.7f) hollow = 0.7f; } + */ volume_params.setHollow( hollow ); @@ -1718,6 +1936,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) // Revolutions F32 revolutions = mSpinRevolutions->get(); + if ( selected_type == MI_SPHERE ) { // Snap values to valid sphere parameters. @@ -1887,6 +2106,7 @@ void LLPanelObject::sendScale(BOOL btn_down) LLVector3 newscale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); LLVector3 delta = newscale - mObject->getScale(); + //Saw this changed in some viewers to be more touchy than this, but it would likely cause more updates and higher lag for the client. -HgB if (delta.magVec() >= 0.0005f) { // scale changed by more than 1/2 millimeter @@ -1961,6 +2181,7 @@ void LLPanelObject::sendPosition(BOOL btn_down) LLVector3d old_pos_global = mObject->getPositionGlobal(); LLVector3d delta = new_pos_global - old_pos_global; // moved more than 1/2 millimeter + //Saw this changed in some viewers to be more touchy than this, but it would likely cause more updates and higher lag for the client. -HgB if (delta.magVec() >= 0.0005f) { if (mRootObject != mObject) @@ -2195,6 +2416,9 @@ void LLPanelObject::onCommitRotation( LLUICtrl* ctrl, void* userdata ) LLPanelObject* self = (LLPanelObject*) userdata; BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ; self->sendRotation(btn_down); + + // Needed to ensure all rotations are shown consistently in range + self->refresh(); } // static @@ -2249,42 +2473,6 @@ void LLPanelObject::onCommitSculpt( LLUICtrl* ctrl, void* userdata ) self->sendSculpt(); } -//moved the Blink code below the Commit voids, Sorry about that. ~[SimmanFederal] -//[SimmanFederal] Blinking function. Inspired by VLife/Oynx. -void LLPanelObject::onClickBlink(void* data) -{ - LLViewerObject* objpos = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); - if(objpos) - { - //printchat("Blinking...");//yes I'm too lasy to add the system chat set up to a header - LLVector3 pos = objpos->getPosition();//get the x and the y - pos.mV[VZ] = 340282346638528859811704183484516925440.0f;//create the z - objpos->setPositionParent(pos);//set the x y z - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);//send the data - } -} - -//[SimmanFederal] HARD-Blinking function. I thought about it while fapping. -void LLPanelObject::onClickHardBlink(void* data) -{ - LLViewerObject* objpos = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); - if(objpos) - { - //printchat("Hard blinking...");//yes I'm too lasy to add the system chat set up to a header - /* - NOTE: Temporary objects, when thrown off world/put off world, - do not report back to the viewer, nor go to lost and found. - - So we do selectionUpdateTemporary(1) - */ - LLSelectMgr::getInstance()->selectionUpdateTemporary(1);//set temp to TRUE - LLVector3 pos = objpos->getPosition();//get the x and the y - pos.mV[VZ] = 340282346638528859811704183484516925440.0f;//create the z - objpos->setPositionParent(pos);//set the x y z - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);//send the data - } -} - // static BOOL LLPanelObject::onDropSculpt(LLUICtrl*, LLInventoryItem* item, void* userdata) { @@ -2325,3 +2513,218 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } + +std::string shortfloat(F32 in) +{ + std::string out = llformat("%f", in); + int i = out.size(); + while(out[--i] == '0') out.erase(i, 1); + return out; +} + +void LLPanelObject::onCopyPos(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLVector3 newpos(self->mCtrlPosX->get(), self->mCtrlPosY->get(), self->mCtrlPosZ->get()); + self->mClipboardPos = newpos; + + std::string stringVec = "<"; + stringVec.append(shortfloat(newpos.mV[VX])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VY])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VZ])); + stringVec.append(">"); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(stringVec)); +} + +void LLPanelObject::onCopySize(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLVector3 newpos(self->mCtrlScaleX->get(), self->mCtrlScaleY->get(), self->mCtrlScaleZ->get()); + self->mClipboardSize = newpos; + + std::string stringVec = "<"; + stringVec.append(shortfloat(newpos.mV[VX])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VY])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VZ])); + stringVec.append(">"); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(stringVec)); +} + +void LLPanelObject::onCopyRot(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLVector3 newpos(self->mCtrlRotX->get(), self->mCtrlRotY->get(), self->mCtrlRotZ->get()); + self->mClipboardRot = newpos; + + std::string stringVec = "<"; + stringVec.append(shortfloat(newpos.mV[VX])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VY])); + stringVec.append(", "); + stringVec.append(shortfloat(newpos.mV[VZ])); + stringVec.append(">"); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(stringVec)); +} + +void LLPanelObject::onCopyParams(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + self->getVolumeParams(mClipboardVolumeParams); + hasParamClipboard = TRUE; +} + +void LLPanelObject::onPasteParams(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + if(hasParamClipboard) + self->mObject->updateVolume(mClipboardVolumeParams); +} + +void LLPanelObject::onPastePos(void* user_data) +{ + if(mClipboardPos.isNull()) return; + + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, 256.f); + mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, 256.f); + mClipboardPos.mV[VZ] = llclamp( mClipboardPos.mV[VZ], 0.f, 4096.f); + + self->mCtrlPosX->set( mClipboardPos.mV[VX] ); + self->mCtrlPosY->set( mClipboardPos.mV[VY] ); + self->mCtrlPosZ->set( mClipboardPos.mV[VZ] ); + + calcp->setVar(LLCalc::X_POS, mClipboardPos.mV[VX]); + calcp->setVar(LLCalc::Y_POS, mClipboardPos.mV[VY]); + calcp->setVar(LLCalc::Z_POS, mClipboardPos.mV[VZ]); + self->sendPosition(FALSE); +} + +void LLPanelObject::onPasteSize(void* user_data) +{ + if(mClipboardSize.isNull()) return; + + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], 0.01f, 10.f); + mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], 0.01f, 10.f); + mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], 0.01f, 10.f); + + self->mCtrlScaleX->set( mClipboardSize.mV[VX] ); + self->mCtrlScaleY->set( mClipboardSize.mV[VY] ); + self->mCtrlScaleZ->set( mClipboardSize.mV[VZ] ); + + calcp->setVar(LLCalc::X_SCALE, mClipboardSize.mV[VX]); + calcp->setVar(LLCalc::Y_SCALE, mClipboardSize.mV[VY]); + calcp->setVar(LLCalc::Z_SCALE, mClipboardSize.mV[VZ]); + self->sendScale(FALSE); +} + +void LLPanelObject::onPasteRot(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + + self->mCtrlRotX->set( mClipboardRot.mV[VX] ); + self->mCtrlRotY->set( mClipboardRot.mV[VY] ); + self->mCtrlRotZ->set( mClipboardRot.mV[VZ] ); + + calcp->setVar(LLCalc::X_ROT, mClipboardRot.mV[VX]); + calcp->setVar(LLCalc::Y_ROT, mClipboardRot.mV[VY]); + calcp->setVar(LLCalc::Z_ROT, mClipboardRot.mV[VZ]); + self->sendRotation(FALSE); +} + +BOOL getvectorfromclip(const std::string& buf, LLVector3* value) +{ + if( buf.empty() || value == NULL) + { + return FALSE; + } + + LLVector3 v; + S32 count = sscanf( buf.c_str(), "<%f, %f, %f>", v.mV + 0, v.mV + 1, v.mV + 2 ); + if( 3 == count ) + { + value->setVec( v ); + return TRUE; + } + + return FALSE; +} + + +void LLPanelObject::onPastePosClip(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + + LLWString temp_string; + LLView::getWindow()->pasteTextFromClipboard(temp_string); + + std::string stringVec = wstring_to_utf8str(temp_string); + if(!getvectorfromclip(stringVec, &mClipboardPos)) return; + + mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, 256.f); + mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, 256.f); + mClipboardPos.mV[VZ] = llclamp(mClipboardPos.mV[VZ], 0.f, 4096.f); + + self->mCtrlPosX->set( mClipboardPos.mV[VX] ); + self->mCtrlPosY->set( mClipboardPos.mV[VY] ); + self->mCtrlPosZ->set( mClipboardPos.mV[VZ] ); + calcp->setVar(LLCalc::X_POS, mClipboardPos.mV[VX]); + calcp->setVar(LLCalc::Y_POS, mClipboardPos.mV[VY]); + calcp->setVar(LLCalc::Z_POS, mClipboardPos.mV[VZ]); + self->sendPosition(FALSE); +} + +void LLPanelObject::onPasteSizeClip(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + + LLWString temp_string; + LLView::getWindow()->pasteTextFromClipboard(temp_string); + + std::string stringVec = wstring_to_utf8str(temp_string); + if(!getvectorfromclip(stringVec, &mClipboardSize)) return; + + mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], 0.01f, 10.f); + mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], 0.01f, 10.f); + mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], 0.01f, 10.f); + + self->mCtrlScaleX->set( mClipboardSize.mV[VX] ); + self->mCtrlScaleY->set( mClipboardSize.mV[VY] ); + self->mCtrlScaleZ->set( mClipboardSize.mV[VZ] ); + calcp->setVar(LLCalc::X_SCALE, mClipboardSize.mV[VX]); + calcp->setVar(LLCalc::Y_SCALE, mClipboardSize.mV[VY]); + calcp->setVar(LLCalc::Z_SCALE, mClipboardSize.mV[VZ]); + self->sendScale(FALSE); +} + +void LLPanelObject::onPasteRotClip(void* user_data) +{ + LLPanelObject* self = (LLPanelObject*) user_data; + LLCalc* calcp = LLCalc::getInstance(); + + LLWString temp_string; + LLView::getWindow()->pasteTextFromClipboard(temp_string); + + std::string stringVec = wstring_to_utf8str(temp_string); + if(!getvectorfromclip(stringVec, &mClipboardRot)) return; + + self->mCtrlRotX->set( mClipboardRot.mV[VX] ); + self->mCtrlRotY->set( mClipboardRot.mV[VY] ); + self->mCtrlRotZ->set( mClipboardRot.mV[VZ] ); + calcp->setVar(LLCalc::X_ROT, mClipboardRot.mV[VX]); + calcp->setVar(LLCalc::Y_ROT, mClipboardRot.mV[VY]); + calcp->setVar(LLCalc::Z_ROT, mClipboardRot.mV[VZ]); + self->sendRotation(FALSE); +} \ No newline at end of file diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 1f191e91b..e20867113 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -64,9 +64,6 @@ public: void refresh(); static BOOL precommitValidate(LLUICtrl* ctrl,void* userdata); - - static void onClickBlink(void* userdata);//[SimmanFederal] Blinking - static void onClickHardBlink(void* userdata);//[SimmanFederal] Griefer Blinking static void onCommitLock(LLUICtrl *ctrl, void *data); static void onCommitPosition( LLUICtrl* ctrl, void* userdata); @@ -77,7 +74,19 @@ public: static void onCommitPhantom( LLUICtrl* ctrl, void* userdata); static void onCommitCastShadows( LLUICtrl* ctrl, void* userdata); - static void onCommitParametric(LLUICtrl* ctrl, void* userdata); + static void onCopyPos( void* user_data); + static void onPastePos( void* user_data); + static void onPastePosClip( void* user_data); + static void onCopySize( void* user_data); + static void onPasteSize( void* user_data); + static void onPasteSizeClip( void* user_data); + static void onCopyRot( void* user_data); + static void onPasteRot( void* user_data); + static void onPasteRotClip( void* user_data); + static void onCopyParams( void* user_data); + static void onPasteParams( void* user_data); + + static void onCommitParametric( LLUICtrl* ctrl, void* userdata); static void onCommitMaterial( LLUICtrl* ctrl, void* userdata); @@ -87,7 +96,9 @@ public: static BOOL onDropSculpt( LLUICtrl* ctrl, LLInventoryItem* item, void* ud); static void onCommitSculptType( LLUICtrl *ctrl, void* userdata); - + + static const LLUUID& findItemID(const LLUUID& asset_id); + protected: void getState(); @@ -103,6 +114,13 @@ protected: void getVolumeParams(LLVolumeParams& volume_params); protected: + + static LLVector3 mClipboardPos; + static LLVector3 mClipboardSize; + static LLVector3 mClipboardRot; + static LLVolumeParams mClipboardVolumeParams; + static BOOL hasParamClipboard; + S32 mComboMaterialItemCount; LLTextBox* mLabelMaterial; @@ -154,9 +172,6 @@ protected: LLSpinCtrl* mCtrlPosX; LLSpinCtrl* mCtrlPosY; LLSpinCtrl* mCtrlPosZ; - //VLife/Oynx Inspriation. IT BLINKS PRIMS TO 340282346638528859811704183484516925440.0f METERS. HERP. - LLButton* mClickBlink;//[SimmanFederal] - LLButton* mClickHardBlink;//[SimmanFederal] LLTextBox* mLabelSize; LLSpinCtrl* mCtrlScaleX; @@ -168,6 +183,21 @@ protected: LLSpinCtrl* mCtrlRotY; LLSpinCtrl* mCtrlRotZ; + LLButton *mBtnCopyPos; + LLButton *mBtnPastePos; + LLButton *mBtnPastePosClip; + + LLButton *mBtnCopySize; + LLButton *mBtnPasteSize; + LLButton *mBtnPasteSizeClip; + + LLButton *mBtnCopyRot; + LLButton *mBtnPasteRot; + LLButton *mBtnPasteRotClip; + + LLButton *mBtnCopyParams; + LLButton *mBtnPasteParams; + LLCheckBoxCtrl *mCheckLock; LLCheckBoxCtrl *mCheckPhysics; LLCheckBoxCtrl *mCheckTemporary; @@ -180,6 +210,9 @@ protected: LLCheckBoxCtrl *mCtrlSculptMirror; LLCheckBoxCtrl *mCtrlSculptInvert; + + + LLVector3 mCurEulerDegrees; // to avoid sending rotation when not changed BOOL mIsPhysical; // to avoid sending "physical" when not changed BOOL mIsTemporary; // to avoid sending "temporary" when not changed diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 32f831a95..d107e65c2 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -65,6 +65,10 @@ #include "lluictrlfactory.h" #include "roles_constants.h" + + + + ///---------------------------------------------------------------------------- /// Class llpanelpermissions ///---------------------------------------------------------------------------- @@ -85,14 +89,18 @@ BOOL LLPanelPermissions::postBuild() this->childSetAction("button owner profile",LLPanelPermissions::onClickOwner,this); + this->childSetAction("button last owner profile",LLPanelPermissions::onClickLastOwner,this); this->childSetAction("button creator profile",LLPanelPermissions::onClickCreator,this); this->childSetAction("button set group",LLPanelPermissions::onClickGroup,this); + this->childSetAction("button open group",LLPanelPermissions::onClickOpenGroup,this); this->childSetCommitCallback("checkbox share with group",LLPanelPermissions::onCommitGroupShare,this); this->childSetAction("button deed",LLPanelPermissions::onClickDeedToGroup,this); + this->childSetAction("button cpy_key",LLPanelPermissions::onClickCopyObjKey,this); + this->childSetCommitCallback("checkbox allow everyone move",LLPanelPermissions::onCommitEveryoneMove,this); this->childSetCommitCallback("checkbox allow everyone copy",LLPanelPermissions::onCommitEveryoneCopy,this); @@ -178,10 +186,16 @@ void LLPanelPermissions::refresh() childSetEnabled("Owner Name",false); childSetEnabled("button owner profile",false); + childSetEnabled("Last Owner:",false); + childSetText("Last Owner Name",LLStringUtil::null); + childSetEnabled("Last Owner Name",false); + childSetEnabled("button last owner profile",false); + childSetEnabled("Group:",false); childSetText("Group Name",LLStringUtil::null); childSetEnabled("Group Name",false); childSetEnabled("button set group",false); + childSetEnabled("button open group",false); childSetText("Object Name",LLStringUtil::null); childSetEnabled("Object Name",false); @@ -297,6 +311,8 @@ void LLPanelPermissions::refresh() owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); // llinfos << "owners_identical " << (owners_identical ? "TRUE": "FALSE") << llendl; + std::string last_owner_name; + LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); if (mOwnerID.isNull()) { @@ -320,10 +336,42 @@ void LLPanelPermissions::refresh() } } + + + + + + + + + + + + + + + + + + + + + childSetText("Owner Name",owner_name); childSetEnabled("Owner Name",TRUE); childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); + + + + + childSetText("Last Owner Name",last_owner_name); + childSetEnabled("Last Owner Name",TRUE); + childSetEnabled("button last owner profile",owners_identical && mLastOwnerID.notNull()); + + + + // update group text field childSetEnabled("Group:",true); childSetText("Group Name",LLStringUtil::null); @@ -348,6 +396,7 @@ void LLPanelPermissions::refresh() } childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID())); + childSetEnabled("button open group", group_id.notNull()); // figure out the contents of the name, description, & category BOOL edit_name_desc = FALSE; @@ -843,6 +892,19 @@ void LLPanelPermissions::onClickOwner(void *data) } } + + + + + + +void LLPanelPermissions::onClickLastOwner(void *data) +{ + LLPanelPermissions *self = (LLPanelPermissions *)data; + if(self->mLastOwnerID.notNull()) + LLFloaterAvatarInfo::showFromObject(self->mLastOwnerID); +} + void LLPanelPermissions::onClickGroup(void* data) { LLPanelPermissions* panelp = (LLPanelPermissions*)data; @@ -866,6 +928,14 @@ void LLPanelPermissions::onClickGroup(void* data) } } +void LLPanelPermissions::onClickOpenGroup(void* data) +{ + LLUUID group_id; + LLSelectMgr::getInstance()->selectGetGroup(group_id); + + LLFloaterGroupInfo::showFromUUID(group_id); +} + // static void LLPanelPermissions::cbGroupID(LLUUID group_id, void* userdata) { @@ -898,6 +968,28 @@ void LLPanelPermissions::onClickDeedToGroup(void* data) LLNotifications::instance().add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group); } +void LLPanelPermissions::onClickCopyObjKey(void* data) +{ + //NAMESHORT - Was requested on the forums, was going to integrate a textbox with the ID, but due to lack of room on the floater, + //We now have a copy button :> + //Madgeek - Hacked together method to copy more than one key, separated by comma. + //At some point the separator was changed to read from the xml settings - I'll probably try to make this openly changable from settings. -HgB + std::string output; + std::string separator = gSavedSettings.getString("AscentDataSeparator"); + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + if (object) + { + if (!output.empty()) output.append(separator); + output.append(object->getID().asString()); + } + } + if (!output.empty()) gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(output)); +} + ///---------------------------------------------------------------------------- /// Permissions checkboxes ///---------------------------------------------------------------------------- diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h index bb816acd0..85ac41831 100644 --- a/indra/newview/llpanelpermissions.h +++ b/indra/newview/llpanelpermissions.h @@ -69,9 +69,12 @@ protected: static void onClickRelease(void*); static void onClickCreator(void*); static void onClickOwner(void*); + static void onClickLastOwner(void*); static void onClickGroup(void*); + static void onClickOpenGroup(void*); static void cbGroupID(LLUUID group_id, void* userdata); static void onClickDeedToGroup(void*); + static void onClickCopyObjKey(void*); static void onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm); diff --git a/indra/newview/llpanelskins.cpp b/indra/newview/llpanelskins.cpp index 26de35682..4b810568a 100644 --- a/indra/newview/llpanelskins.cpp +++ b/indra/newview/llpanelskins.cpp @@ -67,37 +67,73 @@ BOOL LLPanelSkins::postBuild() void LLPanelSkins::refresh() { + mSkin = gSavedSettings.getString("SkinCurrent"); getChild("skin_selection")->setValue(mSkin); } void LLPanelSkins::apply() { - if (mSkin != gSavedSettings.getString("SkinCurrent")) + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) { - LLNotifications::instance().add("ChangeSkin"); - refresh(); + if (mSkin != gSavedSettings.getString("SkinCurrent")) + { + LLNotifications::instance().add("ChangeSkin"); + refresh(); + } } + else + { + if (mSkin != gSavedPerAccountSettings.getString("SkinCurrent")) + { + LLNotifications::instance().add("ChangeSkin"); + refresh(); + } + } + } void LLPanelSkins::cancel() { // reverts any changes to current skin - gSavedSettings.setString("SkinCurrent", mSkin); + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + gSavedSettings.setString("SkinCurrent", mSkin); + } + else + { + gSavedPerAccountSettings.setString("SkinCurrent", mSkin); + } + } //static void LLPanelSkins::onSelectSkin(LLUICtrl* ctrl, void* data) { std::string skin_selection = ctrl->getValue().asString(); - gSavedSettings.setString("SkinCurrent", skin_selection); + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + gSavedSettings.setString("SkinCurrent", skin_selection); + } + else + { + gSavedPerAccountSettings.setString("SkinCurrent", skin_selection); + } + } //static void LLPanelSkins::onClickClassic(void* data) { LLPanelSkins* self = (LLPanelSkins*)data; - gSavedSettings.setString("SkinCurrent", "default"); + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + gSavedSettings.setString("SkinCurrent", "default"); + } + else + { + gSavedPerAccountSettings.setString("SkinCurrent", "default"); + } self->getChild("skin_selection")->setValue("default"); } @@ -105,6 +141,13 @@ void LLPanelSkins::onClickClassic(void* data) void LLPanelSkins::onClickSilver(void* data) { LLPanelSkins* self = (LLPanelSkins*)data; - gSavedSettings.setString("SkinCurrent", "silver"); + if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + gSavedSettings.setString("SkinCurrent", "silver"); + } + else + { + gSavedPerAccountSettings.setString("SkinCurrent", "silver"); + } self->getChild("skin_selection")->setValue("silver"); } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 70d8c5b37..24d9e2d96 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1,6519 +1,6519 @@ -/** - * @file llselectmgr.cpp - * @brief A manager for selected objects and faces. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -// file include -#include "llselectmgr.h" - -// library includes -#include "llcachename.h" -#include "lldbstrings.h" -#include "lleconomy.h" -#include "llgl.h" -#include "llrender.h" -#include "llpermissions.h" -#include "llpermissionsflags.h" -#include "llundo.h" -#include "lluuid.h" -#include "llvolume.h" -#include "message.h" -#include "object_flags.h" -#include "llquaternion.h" - -// viewer includes -#include "llagent.h" -#include "llviewerwindow.h" -#include "lldrawable.h" -#include "llfloaterinspect.h" -#include "llfloaterproperties.h" -#include "llfloaterreporter.h" -#include "llfloatertools.h" -#include "llframetimer.h" -#include "llfocusmgr.h" -#include "llhudeffecttrail.h" -#include "llhudmanager.h" -#include "llinventorymodel.h" -#include "llmenugl.h" -#include "llmutelist.h" -#include "llstatusbar.h" -#include "llsurface.h" -#include "lltool.h" -#include "lltooldraganddrop.h" -#include "lltoolmgr.h" -#include "lltoolpie.h" -#include "llui.h" -#include "llviewercamera.h" -#include "llviewercontrol.h" -#include "llviewerimagelist.h" -#include "llviewermedia.h" -#include "llviewermediafocus.h" -#include "llviewermenu.h" -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llvoavatar.h" -#include "llvovolume.h" -#include "pipeline.h" +/** + * @file llselectmgr.cpp + * @brief A manager for selected objects and faces. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// file include +#include "llselectmgr.h" + +// library includes +#include "llcachename.h" +#include "lldbstrings.h" +#include "lleconomy.h" +#include "llgl.h" +#include "llrender.h" +#include "llpermissions.h" +#include "llpermissionsflags.h" +#include "llundo.h" +#include "lluuid.h" +#include "llvolume.h" +#include "message.h" +#include "object_flags.h" +#include "llquaternion.h" + +// viewer includes +#include "llagent.h" +#include "llviewerwindow.h" +#include "lldrawable.h" +#include "llfloaterinspect.h" +#include "llfloaterproperties.h" +#include "llfloaterreporter.h" +#include "llfloatertools.h" +#include "llframetimer.h" +#include "llfocusmgr.h" +#include "llhudeffecttrail.h" +#include "llhudmanager.h" +#include "llinventorymodel.h" +#include "llmenugl.h" +#include "llmutelist.h" +#include "llstatusbar.h" +#include "llsurface.h" +#include "lltool.h" +#include "lltooldraganddrop.h" +#include "lltoolmgr.h" +#include "lltoolpie.h" +#include "llui.h" +#include "llviewercamera.h" +#include "llviewercontrol.h" +#include "llviewerimagelist.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" +#include "llviewermenu.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llvoavatar.h" +#include "llvovolume.h" +#include "pipeline.h" // #include "llfloaterexport.h" // - -#include "llglheaders.h" - -LLViewerObject* getSelectedParentObject(LLViewerObject *object) ; -// -// Consts -// - -const S32 NUM_SELECTION_UNDO_ENTRIES = 200; -const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f; -const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constants.price_object_claim in the database. -const S32 MAX_ACTION_QUEUE_SIZE = 20; -const S32 MAX_SILS_PER_FRAME = 50; -const S32 MAX_OBJECTS_PER_PACKET = 254; - -// -// Globals -// - -BOOL gDebugSelectMgr = FALSE; - -BOOL gHideSelectedObjects = FALSE; -BOOL gAllowSelectAvatar = FALSE; - -BOOL LLSelectMgr::sRectSelectInclusive = TRUE; -BOOL LLSelectMgr::sRenderSelectionHighlights = TRUE; -BOOL LLSelectMgr::sRenderHiddenSelections = TRUE; -BOOL LLSelectMgr::sRenderLightRadius = FALSE; -F32 LLSelectMgr::sHighlightThickness = 0.f; -F32 LLSelectMgr::sHighlightUScale = 0.f; -F32 LLSelectMgr::sHighlightVScale = 0.f; -F32 LLSelectMgr::sHighlightAlpha = 0.f; -F32 LLSelectMgr::sHighlightAlphaTest = 0.f; -F32 LLSelectMgr::sHighlightUAnim = 0.f; -F32 LLSelectMgr::sHighlightVAnim = 0.f; -LLColor4 LLSelectMgr::sSilhouetteParentColor; -LLColor4 LLSelectMgr::sSilhouetteChildColor; -LLColor4 LLSelectMgr::sHighlightInspectColor; -LLColor4 LLSelectMgr::sHighlightParentColor; -LLColor4 LLSelectMgr::sHighlightChildColor; -LLColor4 LLSelectMgr::sContextSilhouetteColor; -std::set LLSelectMgr::sObjectPropertiesFamilyRequests; - -static LLObjectSelection *get_null_object_selection(); -template<> - const LLSafeHandle::NullFunc - LLSafeHandle::sNullFunc = get_null_object_selection; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// struct LLDeRezInfo -// -// Used to keep track of important derez info. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -struct LLDeRezInfo -{ - EDeRezDestination mDestination; - LLUUID mDestinationID; - LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) : - mDestination(dest), mDestinationID(dest_id) {} -}; - -// -// Imports -// - - -static LLPointer sNullSelection; - -// -// Functions -// - -void LLSelectMgr::cleanupGlobals() -{ - sNullSelection = NULL; - LLSelectMgr::getInstance()->clearSelections(); -} - -LLObjectSelection *get_null_object_selection() -{ - if (sNullSelection.isNull()) - { - sNullSelection = new LLObjectSelection; - } - return sNullSelection; -} - - -//----------------------------------------------------------------------------- -// LLSelectMgr() -//----------------------------------------------------------------------------- -LLSelectMgr::LLSelectMgr() -{ - mTEMode = FALSE; - mLastCameraPos.clearVec(); - - sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness"); - sHighlightUScale = gSavedSettings.getF32("SelectionHighlightUScale"); - sHighlightVScale = gSavedSettings.getF32("SelectionHighlightVScale"); - sHighlightAlpha = gSavedSettings.getF32("SelectionHighlightAlpha"); - sHighlightAlphaTest = gSavedSettings.getF32("SelectionHighlightAlphaTest"); - sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim"); - sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim"); - - sSilhouetteParentColor = gColors.getColor("SilhouetteParentColor"); - sSilhouetteChildColor = gColors.getColor("SilhouetteChildColor"); - sHighlightParentColor = gColors.getColor("HighlightParentColor"); - sHighlightChildColor = gColors.getColor("HighlightChildColor"); - sHighlightInspectColor = gColors.getColor("HighlightInspectColor"); - sContextSilhouetteColor = gColors.getColor("ContextSilhouetteColor")*0.5f; - - sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); - - mRenderSilhouettes = TRUE; - - mGridMode = GRID_MODE_WORLD; - gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); - mGridValid = FALSE; - - mSelectedObjects = new LLObjectSelection(); - mHoverObjects = new LLObjectSelection(); - mHighlightedObjects = new LLObjectSelection(); -} - - -//----------------------------------------------------------------------------- -// ~LLSelectMgr() -//----------------------------------------------------------------------------- -LLSelectMgr::~LLSelectMgr() -{ - clearSelections(); -} - -void LLSelectMgr::clearSelections() -{ - mHoverObjects->deleteAllNodes(); - mSelectedObjects->deleteAllNodes(); - mHighlightedObjects->deleteAllNodes(); - mRectSelectedObjects.clear(); - mGridObjects.deleteAllNodes(); -} - -void LLSelectMgr::update() -{ - mSelectedObjects->cleanupNodes(); -} - -void LLSelectMgr::updateEffects() -{ - //keep reference grid objects active - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - gPipeline.markMoved(drawable); - } - return true; - } - } func; - mGridObjects.applyToObjects(&func); - - if (mEffectsTimer.getElapsedTimeF32() > 1.f) - { - mSelectedObjects->updateEffects(); - mEffectsTimer.reset(); - } -} - -void LLSelectMgr::overrideObjectUpdates() -{ - //override any position updates from simulator on objects being edited - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* selectNode) - { - LLViewerObject* object = selectNode->getObject(); - if (object && object->permMove()) - { - if (!selectNode->mLastPositionLocal.isExactlyZero()) - { - object->setPosition(selectNode->mLastPositionLocal); - } - if (selectNode->mLastRotation != LLQuaternion()) - { - object->setRotation(selectNode->mLastRotation); - } - if (!selectNode->mLastScale.isExactlyZero()) - { - object->setScale(selectNode->mLastScale); - } - } - return true; - } - } func; - getSelection()->applyToNodes(&func); -} - -//----------------------------------------------------------------------------- -// Select just the object, not any other group members. -//----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) -{ - llassert( object ); - - //remember primary object - mSelectedObjects->mPrimaryObject = object; - - // Don't add an object that is already in the list - if (object->isSelected() ) { - // make sure point at position is updated - updatePointAt(); - gEditMenuHandler = this; - return NULL; - } - - if (!canSelectObject(object)) - { - //make_ui_sound("UISndInvalidOp"); - return NULL; - } - - // llinfos << "Adding object to selected object list" << llendl; - - // Place it in the list and tag it. - // This will refresh dialogs. - addAsIndividual(object, face); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - // *FIX: shouldn't zero out these either - object->setVelocity(LLVector3::zero); - object->setAcceleration(LLVector3::zero); - //object->setAngularVelocity(LLVector3::zero); - object->resetRot(); - - // Always send to simulator, so you get a copy of the - // permissions structure back. - gMessageSystem->newMessageFast(_PREHASH_ObjectSelect); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - LLViewerRegion* regionp = object->getRegion(); - gMessageSystem->sendReliable( regionp->getHost()); - - updatePointAt(); - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; -} - -//----------------------------------------------------------------------------- -// Select the object, parents and children. -//----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) -{ - llassert( obj ); - - //remember primary object - mSelectedObjects->mPrimaryObject = obj; - - // This may be incorrect if things weren't family selected before... - djs 07/08/02 - // Don't add an object that is already in the list - if (obj->isSelected() ) - { - // make sure pointat position is updated - updatePointAt(); - gEditMenuHandler = this; - return NULL; - } - - if (!canSelectObject(obj)) - { - //make_ui_sound("UISndInvalidOp"); - return NULL; - } - - // Since we're selecting a family, start at the root, but - // don't include an avatar. - LLViewerObject* root = obj; - - while(!root->isAvatar() && root->getParent() && !root->isJointChild()) - { - LLViewerObject* parent = (LLViewerObject*)root->getParent(); - if (parent->isAvatar()) - { - break; - } - root = parent; - } - - // Collect all of the objects - LLDynamicArray objects; - - root->addThisAndNonJointChildren(objects); - addAsFamily(objects, add_to_end); - - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); - - dialog_refresh_all(); - - // Always send to simulator, so you get a copy of the permissions - // structure back. - sendSelect(); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - root->setVelocity(LLVector3::zero); - root->setAcceleration(LLVector3::zero); - //root->setAngularVelocity(LLVector3::zero); - root->resetRot(); - - // leave component mode - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - gSavedSettings.setBOOL("EditLinkedParts", FALSE); - promoteSelectionToRoot(); - } - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; -} - -//----------------------------------------------------------------------------- -// Select the object, parents and children. -//----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector& object_list, - BOOL send_to_sim) -{ - // Collect all of the objects, children included - LLDynamicArray objects; - - //clear primary object (no primary object) - mSelectedObjects->mPrimaryObject = NULL; - - if (object_list.size() < 1) - { - return NULL; - } - - // NOTE -- we add the objects in REVERSE ORDER - // to preserve the order in the mSelectedObjects list - for (std::vector::const_reverse_iterator riter = object_list.rbegin(); - riter != object_list.rend(); ++riter) - { - LLViewerObject *object = *riter; - - llassert( object ); - - if (!canSelectObject(object)) continue; - - object->addThisAndNonJointChildren(objects); - addAsFamily(objects); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - object->setVelocity(LLVector3::zero); - object->setAcceleration(LLVector3::zero); - //object->setAngularVelocity(LLVector3::zero); - object->resetRot(); - } - - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); - dialog_refresh_all(); - - // Almost always send to simulator, so you get a copy of the permissions - // structure back. - // JC: The one case where you don't want to do this is if you're selecting - // all the objects on a sim. - if (send_to_sim) - { - sendSelect(); - } - - // leave component mode - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - gSavedSettings.setBOOL("EditLinkedParts", FALSE); - promoteSelectionToRoot(); - } - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; -} - -// Use for when the simulator kills an object. This version also -// handles informing the current tool of the object's deletion. -// -// Caller needs to call dialog_refresh_all if necessary. -BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) -{ - BOOL object_found = FALSE; - LLTool *tool = NULL; - if (!gNoRender) - { - tool = LLToolMgr::getInstance()->getCurrentTool(); - - // It's possible that the tool is editing an object that is not selected - LLViewerObject* tool_editing_object = tool->getEditingObject(); - if( tool_editing_object && tool_editing_object->mID == id) - { - tool->stopEditing(); - object_found = TRUE; - } - } - - // Iterate through selected objects list and kill the object - if( !object_found ) - { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - LLViewerObject* object = (*curiter)->getObject(); - if (object->mID == id) - { - if (tool) - { - tool->stopEditing(); - } - - // lose the selection, don't tell simulator, it knows - deselectObjectAndFamily(object, FALSE); - object_found = TRUE; - break; // must break here, may have removed multiple objects from list - } - else if (object->isAvatar()) - { - // It's possible the item being removed has an avatar sitting on it - // So remove the avatar that is sitting on the object. - deselectObjectAndFamily(object, FALSE); - break; // must break here, may have removed multiple objects from list - } - } - } - - return object_found; -} - -void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object) -{ - // bail if nothing selected or if object wasn't selected in the first place - if(!object) return; - if(!object->isSelected()) return; - - // Collect all of the objects, and remove them - LLDynamicArray objects; - - if (include_entire_object) - { - // Since we're selecting a family, start at the root, but - // don't include an avatar. - LLViewerObject* root = object; - - while(!root->isAvatar() && root->getParent() && !root->isJointChild()) - { - LLViewerObject* parent = (LLViewerObject*)root->getParent(); - if (parent->isAvatar()) - { - break; - } - root = parent; - } - - object = root; - } - else - { - object = (LLViewerObject*)object->getRoot(); - } - - object->addThisAndAllChildren(objects); - remove(objects); - - if (!send_to_sim) return; - - //----------------------------------------------------------- - // Inform simulator of deselection - //----------------------------------------------------------- - LLViewerRegion* regionp = object->getRegion(); - - BOOL start_new_message = TRUE; - S32 select_count = 0; - - LLMessageSystem* msg = gMessageSystem; - for (U32 i = 0; i < objects.size(); i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_ObjectDeselect); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - select_count++; - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID()); - select_count++; - - // Zap the angular velocity, as the sim will set it to zero - objects[i]->setAngularVelocity( 0,0,0 ); - objects[i]->setVelocity( 0,0,0 ); - - if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET) - { - msg->sendReliable(regionp->getHost() ); - select_count = 0; - start_new_message = TRUE; - } - } - - if (!start_new_message) - { - msg->sendReliable(regionp->getHost() ); - } - - updatePointAt(); - updateSelectionCenter(); -} - -void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim) -{ - // bail if nothing selected or if object wasn't selected in the first place - if (!object) return; - if (!object->isSelected() ) return; - - // Zap the angular velocity, as the sim will set it to zero - object->setAngularVelocity( 0,0,0 ); - object->setVelocity( 0,0,0 ); - - if (send_to_sim) - { - LLViewerRegion* region = object->getRegion(); - gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->sendReliable(region->getHost()); - } - - // This will refresh dialogs. - remove( object ); - - updatePointAt(); - updateSelectionCenter(); -} - - -//----------------------------------------------------------------------------- -// addAsFamily -//----------------------------------------------------------------------------- - -void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to_end) -{ - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - - // Can't select yourself - if (objectp->mID == gAgentID - && !gAllowSelectAvatar) - { - continue; - } - - if (!objectp->isSelected()) - { - LLSelectNode *nodep = new LLSelectNode(objectp, TRUE); - if (add_to_end) - { - mSelectedObjects->addNodeAtEnd(nodep); - } - else - { - mSelectedObjects->addNode(nodep); - } - objectp->setSelected(TRUE); - - if (objectp->getNumTEs() > 0) - { - nodep->selectAllTEs(TRUE); - } - else - { - // object has no faces, so don't mess with faces - } - } - else - { - // we want this object to be selected for real - // so clear transient flag - LLSelectNode* select_node = mSelectedObjects->findNode(objectp); - if (select_node) - { - select_node->setTransient(FALSE); - } - } - } - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); -} - -//----------------------------------------------------------------------------- -// addAsIndividual() - a single object, face, etc -//----------------------------------------------------------------------------- -void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable) -{ - // check to see if object is already in list - LLSelectNode *nodep = mSelectedObjects->findNode(objectp); - - // if not in list, add it - if (!nodep) - { - nodep = new LLSelectNode(objectp, TRUE); - mSelectedObjects->addNode(nodep); - llassert_always(nodep->getObject()); - } - else - { - // make this a full-fledged selection - nodep->setTransient(FALSE); - // Move it to the front of the list - mSelectedObjects->moveNodeToFront(nodep); - } - - // Make sure the object is tagged as selected - objectp->setSelected( TRUE ); - - // And make sure we don't consider it as part of a family - nodep->mIndividualSelection = TRUE; - - // Handle face selection - if (objectp->getNumTEs() <= 0) - { - // object has no faces, so don't do anything - } - else if (face == SELECT_ALL_TES) - { - nodep->selectAllTEs(TRUE); - } - else if (0 <= face && face < SELECT_MAX_TES) - { - nodep->selectTE(face, TRUE); - } - else - { - llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl; - return; - } - - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updateSelectionCenter(); - dialog_refresh_all(); -} - - -LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face) -{ - // Always blitz hover list when setting - mHoverObjects->deleteAllNodes(); - - if (!objectp) - { - return NULL; - } - - // Can't select yourself - if (objectp->mID == gAgentID) - { - return NULL; - } - - // Can't select land - if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) - { - return NULL; - } - - // Collect all of the objects - LLDynamicArray objects; - objectp = objectp->getRootEdit(); - objectp->addThisAndNonJointChildren(objects); - - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* cur_objectp = *iter; - LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); - nodep->selectTE(face, TRUE); - mHoverObjects->addNodeAtEnd(nodep); - } - - requestObjectPropertiesFamily(objectp); - return mHoverObjects; -} - -LLSelectNode *LLSelectMgr::getHoverNode() -{ - return getHoverObjects()->getFirstRootNode(); -} - -void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) -{ - if (!objectp) - { - return; - } - - if (objectp->getPCode() != LL_PCODE_VOLUME) - { - return; - } - - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove())) - { - // only select my own objects - return; - } - - mRectSelectedObjects.insert(objectp); -} - -void LLSelectMgr::highlightObjectAndFamily(LLViewerObject* objectp) -{ - if (!objectp) - { - return; - } - - LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); - - highlightObjectOnly(root_obj); - - LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - highlightObjectOnly(child); - } -} - -// Note that this ignores the "select owned only" flag -// It's also more efficient than calling the single-object version over and over. -void LLSelectMgr::highlightObjectAndFamily(const std::vector& objects) -{ - for (std::vector::const_iterator iter1 = objects.begin(); - iter1 != objects.end(); ++iter1) - { - LLViewerObject* object = *iter1; - - if (!object) - { - continue; - } - if (object->getPCode() != LL_PCODE_VOLUME) - { - continue; - } - - LLViewerObject* root = (LLViewerObject*)object->getRoot(); - mRectSelectedObjects.insert(root); - - LLViewerObject::const_child_list_t& child_list = root->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter2 = child_list.begin(); - iter2 != child_list.end(); iter2++) - { - LLViewerObject* child = *iter2; - mRectSelectedObjects.insert(child); - } - } -} - -void LLSelectMgr::unhighlightObjectOnly(LLViewerObject* objectp) -{ - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - - mRectSelectedObjects.erase(objectp); -} - -void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp) -{ - if (!objectp) - { - return; - } - - LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); - - unhighlightObjectOnly(root_obj); - - LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - unhighlightObjectOnly(child); - } -} - - -void LLSelectMgr::unhighlightAll() -{ - mRectSelectedObjects.clear(); - mHighlightedObjects->deleteAllNodes(); -} - -LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects() -{ - if (!mHighlightedObjects->getNumNodes()) - { - return NULL; - } - - //clear primary object - mSelectedObjects->mPrimaryObject = NULL; - - for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin(); - iter != getHighlightedObjects()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - - LLSelectNode *nodep = *curiter; - LLViewerObject* objectp = nodep->getObject(); - - if (!canSelectObject(objectp)) - { - continue; - } - - // already selected - if (objectp->isSelected()) - { - continue; - } - - LLSelectNode* new_nodep = new LLSelectNode(*nodep); - mSelectedObjects->addNode(new_nodep); - - // flag this object as selected - objectp->setSelected(TRUE); - - mSelectedObjects->mSelectType = getSelectTypeForObject(objectp); - - // request properties on root objects - if (objectp->isRootEdit()) - { - requestObjectPropertiesFamily(objectp); - } - } - - // pack up messages to let sim know these objects are selected - sendSelect(); - unhighlightAll(); - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); - - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; -} - -void LLSelectMgr::deselectHighlightedObjects() -{ - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - for (std::set >::iterator iter = mRectSelectedObjects.begin(); - iter != mRectSelectedObjects.end(); iter++) - { - LLViewerObject *objectp = *iter; - if (!select_linked_set) - { - deselectObjectOnly(objectp); - } - else - { - LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot(); - if (root_object->isSelected()) - { - deselectObjectAndFamily(root_object); - } - } - } - - unhighlightAll(); -} - -void LLSelectMgr::addGridObject(LLViewerObject* objectp) -{ - LLSelectNode* nodep = new LLSelectNode(objectp, FALSE); - mGridObjects.addNodeAtEnd(nodep); - - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - nodep = new LLSelectNode(child, FALSE); - mGridObjects.addNodeAtEnd(nodep); - } -} - -void LLSelectMgr::clearGridObjects() -{ - mGridObjects.deleteAllNodes(); -} - -void LLSelectMgr::setGridMode(EGridMode mode) -{ - mGridMode = mode; - gSavedSettings.setS32("GridMode", mode); - updateSelectionCenter(); - mGridValid = FALSE; -} - -void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale) -{ - mGridObjects.cleanupNodes(); - - LLViewerObject* first_grid_object = mGridObjects.getFirstObject(); - - if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) - { - //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject()); - LLBBox bbox = mSavedSelectionBBox; - mGridOrigin = mSavedSelectionBBox.getCenterAgent(); - mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f; - - // DEV-12570 Just taking the saved selection box rotation prevents - // wild rotations of linked sets while in local grid mode - //if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull()) - { - mGridRotation = mSavedSelectionBBox.getRotation(); - } - /*else //set to the root object - { - mGridRotation = root->getRenderRotation(); - }*/ - } - else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull()) - { - mGridRotation = first_grid_object->getRenderRotation(); - LLVector3 first_grid_obj_pos = first_grid_object->getRenderPosition(); - - LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 max_extents(-F32_MAX, -F32_MAX, -F32_MAX); - BOOL grid_changed = FALSE; - for (LLObjectSelection::iterator iter = mGridObjects.begin(); - iter != mGridObjects.end(); ++iter) - { - LLViewerObject* object = (*iter)->getObject(); - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - const LLVector3* ext = drawable->getSpatialExtents(); - update_min_max(min_extents, max_extents, ext[0]); - update_min_max(min_extents, max_extents, ext[1]); - grid_changed = TRUE; - } - } - if (grid_changed) - { - mGridOrigin = lerp(min_extents, max_extents, 0.5f); - LLDrawable* drawable = first_grid_object->mDrawable; - if (drawable && drawable->isActive()) - { - mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); - } - mGridScale = (max_extents - min_extents) * 0.5f; - } - } - else // GRID_MODE_WORLD or just plain default - { - const BOOL non_root_ok = TRUE; - LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok); - - mGridOrigin.clearVec(); - mGridRotation.loadIdentity(); - - mSelectedObjects->mSelectType = getSelectTypeForObject( first_object ); - - switch (mSelectedObjects->mSelectType) - { - case SELECT_TYPE_ATTACHMENT: - if (first_object && first_object->getRootEdit()->mDrawable.notNull()) - { - // this means this object *has* to be an attachment - LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent(); - mGridOrigin = attachment_point_xform->getWorldPosition(); - mGridRotation = attachment_point_xform->getWorldRotation(); - mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); - } - break; - case SELECT_TYPE_HUD: - // use HUD-scaled grid - mGridScale = LLVector3(0.25f, 0.25f, 0.25f); - break; - case SELECT_TYPE_WORLD: - mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); - break; - } - } - llassert(mGridOrigin.isFinite()); - - origin = mGridOrigin; - rotation = mGridRotation; - scale = mGridScale; - mGridValid = TRUE; -} - -//----------------------------------------------------------------------------- -// remove() - an array of objects -//----------------------------------------------------------------------------- - -void LLSelectMgr::remove(std::vector& objects) -{ - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - LLSelectNode* nodep = mSelectedObjects->findNode(objectp); - if (nodep) - { - objectp->setSelected(FALSE); - mSelectedObjects->removeNode(nodep); - nodep = NULL; - } - } - updateSelectionCenter(); - dialog_refresh_all(); -} - - -//----------------------------------------------------------------------------- -// remove() - a single object -//----------------------------------------------------------------------------- -void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) -{ - // get object node (and verify it is in the selected list) - LLSelectNode *nodep = mSelectedObjects->findNode(objectp); - if (!nodep) - { - return; - } - - // if face = all, remove object from list - if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES)) - { - // Remove all faces (or the object doesn't have faces) so remove the node - mSelectedObjects->removeNode(nodep); - nodep = NULL; - objectp->setSelected( FALSE ); - } - else if (0 <= te && te < SELECT_MAX_TES) - { - // ...valid face, check to see if it was on - if (nodep->isTESelected(te)) - { - nodep->selectTE(te, FALSE); - } - else - { - llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; - return; - } - - // ...check to see if this operation turned off all faces - BOOL found = FALSE; - for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++) - { - found = found || nodep->isTESelected(i); - } - - // ...all faces now turned off, so remove - if (!found) - { - mSelectedObjects->removeNode(nodep); - nodep = NULL; - objectp->setSelected( FALSE ); - // *FIXME: Doesn't update simulator that object is no longer selected - } - } - else - { - // ...out of range face - llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; - } - - updateSelectionCenter(); - dialog_refresh_all(); -} - - -//----------------------------------------------------------------------------- -// removeAll() -//----------------------------------------------------------------------------- -void LLSelectMgr::removeAll() -{ - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setSelected( FALSE ); - } - - mSelectedObjects->deleteAllNodes(); - - updateSelectionCenter(); - dialog_refresh_all(); -} - -//----------------------------------------------------------------------------- -// promoteSelectionToRoot() -//----------------------------------------------------------------------------- -void LLSelectMgr::promoteSelectionToRoot() -{ - std::set selection_set; - - BOOL selection_changed = FALSE; - - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - LLSelectNode* nodep = *curiter; - LLViewerObject* object = nodep->getObject(); - - if (nodep->mIndividualSelection) - { - selection_changed = TRUE; - } - - LLViewerObject* parentp = object; - while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild())) - { - parentp = (LLViewerObject*)parentp->getParent(); - } - - selection_set.insert(parentp); - } - - if (selection_changed) - { - deselectAll(); - - std::set::iterator set_iter; - for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter) - { - selectObjectAndFamily(*set_iter); - } - } -} - -//----------------------------------------------------------------------------- -// demoteSelectionToIndividuals() -//----------------------------------------------------------------------------- -void LLSelectMgr::demoteSelectionToIndividuals() -{ - LLDynamicArray objects; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLViewerObject* object = (*iter)->getObject(); - object->addThisAndNonJointChildren(objects); - } - - if (objects.getLength()) - { - deselectAll(); - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - selectObjectOnly(objectp); - } - } -} - -//----------------------------------------------------------------------------- -// dump() -//----------------------------------------------------------------------------- -void LLSelectMgr::dump() -{ - llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl; - - llinfos << "TE mode " << mTEMode << llendl; - - S32 count = 0; - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLViewerObject* objectp = (*iter)->getObject(); - llinfos << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl; - llinfos << " hasLSL " << objectp->flagScripted() << llendl; - llinfos << " hasTouch " << objectp->flagHandleTouch() << llendl; - llinfos << " hasMoney " << objectp->flagTakesMoney() << llendl; - llinfos << " getposition " << objectp->getPosition() << llendl; - llinfos << " getpositionAgent " << objectp->getPositionAgent() << llendl; - llinfos << " getpositionRegion " << objectp->getPositionRegion() << llendl; - llinfos << " getpositionGlobal " << objectp->getPositionGlobal() << llendl; - LLDrawable* drawablep = objectp->mDrawable; - llinfos << " " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << llendl; - llinfos << " " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << llendl; - count++; - } - - // Face iterator - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - for (S32 te = 0; te < objectp->getNumTEs(); ++te ) - { - if (node->isTESelected(te)) - { - llinfos << "Object " << objectp << " te " << te << llendl; - } - } - } - - llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl; - - llinfos << "Center global " << mSelectionCenterGlobal << llendl; -} - -//----------------------------------------------------------------------------- -// cleanup() -//----------------------------------------------------------------------------- -void LLSelectMgr::cleanup() -{ - mSilhouetteImagep = NULL; -} - - -//--------------------------------------------------------------------------- -// Manipulate properties of selected objects -//--------------------------------------------------------------------------- - -struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor -{ - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } -}; - -//----------------------------------------------------------------------------- -// selectionSetImage() -//----------------------------------------------------------------------------- -// *TODO: re-arch texture applying out of lltooldraganddrop -void LLSelectMgr::selectionSetImage(const LLUUID& imageid) -{ - // First for (no copy) textures and multiple object selection - LLViewerInventoryItem* item = gInventory.getItem(imageid); + +#include "llglheaders.h" + +LLViewerObject* getSelectedParentObject(LLViewerObject *object) ; +// +// Consts +// + +const S32 NUM_SELECTION_UNDO_ENTRIES = 200; +const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f; +const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constants.price_object_claim in the database. +const S32 MAX_ACTION_QUEUE_SIZE = 20; +const S32 MAX_SILS_PER_FRAME = 50; +const S32 MAX_OBJECTS_PER_PACKET = 254; + +// +// Globals +// + +BOOL gDebugSelectMgr = FALSE; + +BOOL gHideSelectedObjects = FALSE; +BOOL gAllowSelectAvatar = FALSE; + +BOOL LLSelectMgr::sRectSelectInclusive = TRUE; +BOOL LLSelectMgr::sRenderSelectionHighlights = TRUE; +BOOL LLSelectMgr::sRenderHiddenSelections = TRUE; +BOOL LLSelectMgr::sRenderLightRadius = FALSE; +F32 LLSelectMgr::sHighlightThickness = 0.f; +F32 LLSelectMgr::sHighlightUScale = 0.f; +F32 LLSelectMgr::sHighlightVScale = 0.f; +F32 LLSelectMgr::sHighlightAlpha = 0.f; +F32 LLSelectMgr::sHighlightAlphaTest = 0.f; +F32 LLSelectMgr::sHighlightUAnim = 0.f; +F32 LLSelectMgr::sHighlightVAnim = 0.f; +LLColor4 LLSelectMgr::sSilhouetteParentColor; +LLColor4 LLSelectMgr::sSilhouetteChildColor; +LLColor4 LLSelectMgr::sHighlightInspectColor; +LLColor4 LLSelectMgr::sHighlightParentColor; +LLColor4 LLSelectMgr::sHighlightChildColor; +LLColor4 LLSelectMgr::sContextSilhouetteColor; +std::set LLSelectMgr::sObjectPropertiesFamilyRequests; + +static LLObjectSelection *get_null_object_selection(); +template<> + const LLSafeHandle::NullFunc + LLSafeHandle::sNullFunc = get_null_object_selection; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// struct LLDeRezInfo +// +// Used to keep track of important derez info. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +struct LLDeRezInfo +{ + EDeRezDestination mDestination; + LLUUID mDestinationID; + LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) : + mDestination(dest), mDestinationID(dest_id) {} +}; + +// +// Imports +// + + +static LLPointer sNullSelection; + +// +// Functions +// + +void LLSelectMgr::cleanupGlobals() +{ + sNullSelection = NULL; + LLSelectMgr::getInstance()->clearSelections(); +} + +LLObjectSelection *get_null_object_selection() +{ + if (sNullSelection.isNull()) + { + sNullSelection = new LLObjectSelection; + } + return sNullSelection; +} + + +//----------------------------------------------------------------------------- +// LLSelectMgr() +//----------------------------------------------------------------------------- +LLSelectMgr::LLSelectMgr() +{ + mTEMode = FALSE; + mLastCameraPos.clearVec(); + + sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness"); + sHighlightUScale = gSavedSettings.getF32("SelectionHighlightUScale"); + sHighlightVScale = gSavedSettings.getF32("SelectionHighlightVScale"); + sHighlightAlpha = gSavedSettings.getF32("SelectionHighlightAlpha"); + sHighlightAlphaTest = gSavedSettings.getF32("SelectionHighlightAlphaTest"); + sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim"); + sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim"); + + sSilhouetteParentColor = gColors.getColor("SilhouetteParentColor"); + sSilhouetteChildColor = gColors.getColor("SilhouetteChildColor"); + sHighlightParentColor = gColors.getColor("HighlightParentColor"); + sHighlightChildColor = gColors.getColor("HighlightChildColor"); + sHighlightInspectColor = gColors.getColor("HighlightInspectColor"); + sContextSilhouetteColor = gColors.getColor("ContextSilhouetteColor")*0.5f; + + sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); + + mRenderSilhouettes = TRUE; + + mGridMode = GRID_MODE_WORLD; + gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); + mGridValid = FALSE; + + mSelectedObjects = new LLObjectSelection(); + mHoverObjects = new LLObjectSelection(); + mHighlightedObjects = new LLObjectSelection(); +} + + +//----------------------------------------------------------------------------- +// ~LLSelectMgr() +//----------------------------------------------------------------------------- +LLSelectMgr::~LLSelectMgr() +{ + clearSelections(); +} + +void LLSelectMgr::clearSelections() +{ + mHoverObjects->deleteAllNodes(); + mSelectedObjects->deleteAllNodes(); + mHighlightedObjects->deleteAllNodes(); + mRectSelectedObjects.clear(); + mGridObjects.deleteAllNodes(); +} + +void LLSelectMgr::update() +{ + mSelectedObjects->cleanupNodes(); +} + +void LLSelectMgr::updateEffects() +{ + //keep reference grid objects active + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + gPipeline.markMoved(drawable); + } + return true; + } + } func; + mGridObjects.applyToObjects(&func); + + if (mEffectsTimer.getElapsedTimeF32() > 1.f) + { + mSelectedObjects->updateEffects(); + mEffectsTimer.reset(); + } +} + +void LLSelectMgr::overrideObjectUpdates() +{ + //override any position updates from simulator on objects being edited + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* selectNode) + { + LLViewerObject* object = selectNode->getObject(); + if (object && object->permMove()) + { + if (!selectNode->mLastPositionLocal.isExactlyZero()) + { + object->setPosition(selectNode->mLastPositionLocal); + } + if (selectNode->mLastRotation != LLQuaternion()) + { + object->setRotation(selectNode->mLastRotation); + } + if (!selectNode->mLastScale.isExactlyZero()) + { + object->setScale(selectNode->mLastScale); + } + } + return true; + } + } func; + getSelection()->applyToNodes(&func); +} + +//----------------------------------------------------------------------------- +// Select just the object, not any other group members. +//----------------------------------------------------------------------------- +LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) +{ + llassert( object ); + + //remember primary object + mSelectedObjects->mPrimaryObject = object; + + // Don't add an object that is already in the list + if (object->isSelected() ) { + // make sure point at position is updated + updatePointAt(); + gEditMenuHandler = this; + return NULL; + } + + if (!canSelectObject(object)) + { + //make_ui_sound("UISndInvalidOp"); + return NULL; + } + + // llinfos << "Adding object to selected object list" << llendl; + + // Place it in the list and tag it. + // This will refresh dialogs. + addAsIndividual(object, face); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + // *FIX: shouldn't zero out these either + object->setVelocity(LLVector3::zero); + object->setAcceleration(LLVector3::zero); + //object->setAngularVelocity(LLVector3::zero); + object->resetRot(); + + // Always send to simulator, so you get a copy of the + // permissions structure back. + gMessageSystem->newMessageFast(_PREHASH_ObjectSelect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + LLViewerRegion* regionp = object->getRegion(); + gMessageSystem->sendReliable( regionp->getHost()); + + updatePointAt(); + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; +} + +//----------------------------------------------------------------------------- +// Select the object, parents and children. +//----------------------------------------------------------------------------- +LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) +{ + llassert( obj ); + + //remember primary object + mSelectedObjects->mPrimaryObject = obj; + + // This may be incorrect if things weren't family selected before... - djs 07/08/02 + // Don't add an object that is already in the list + if (obj->isSelected() ) + { + // make sure pointat position is updated + updatePointAt(); + gEditMenuHandler = this; + return NULL; + } + + if (!canSelectObject(obj)) + { + //make_ui_sound("UISndInvalidOp"); + return NULL; + } + + // Since we're selecting a family, start at the root, but + // don't include an avatar. + LLViewerObject* root = obj; + + while(!root->isAvatar() && root->getParent() && !root->isJointChild()) + { + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) + { + break; + } + root = parent; + } + + // Collect all of the objects + LLDynamicArray objects; + + root->addThisAndNonJointChildren(objects); + addAsFamily(objects, add_to_end); + + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); + + dialog_refresh_all(); + + // Always send to simulator, so you get a copy of the permissions + // structure back. + sendSelect(); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + root->setVelocity(LLVector3::zero); + root->setAcceleration(LLVector3::zero); + //root->setAngularVelocity(LLVector3::zero); + root->resetRot(); + + // leave component mode + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + gSavedSettings.setBOOL("EditLinkedParts", FALSE); + promoteSelectionToRoot(); + } + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; +} + +//----------------------------------------------------------------------------- +// Select the object, parents and children. +//----------------------------------------------------------------------------- +LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector& object_list, + BOOL send_to_sim) +{ + // Collect all of the objects, children included + LLDynamicArray objects; + + //clear primary object (no primary object) + mSelectedObjects->mPrimaryObject = NULL; + + if (object_list.size() < 1) + { + return NULL; + } + + // NOTE -- we add the objects in REVERSE ORDER + // to preserve the order in the mSelectedObjects list + for (std::vector::const_reverse_iterator riter = object_list.rbegin(); + riter != object_list.rend(); ++riter) + { + LLViewerObject *object = *riter; + + llassert( object ); + + if (!canSelectObject(object)) continue; + + object->addThisAndNonJointChildren(objects); + addAsFamily(objects); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + object->setVelocity(LLVector3::zero); + object->setAcceleration(LLVector3::zero); + //object->setAngularVelocity(LLVector3::zero); + object->resetRot(); + } + + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); + dialog_refresh_all(); + + // Almost always send to simulator, so you get a copy of the permissions + // structure back. + // JC: The one case where you don't want to do this is if you're selecting + // all the objects on a sim. + if (send_to_sim) + { + sendSelect(); + } + + // leave component mode + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + gSavedSettings.setBOOL("EditLinkedParts", FALSE); + promoteSelectionToRoot(); + } + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; +} + +// Use for when the simulator kills an object. This version also +// handles informing the current tool of the object's deletion. +// +// Caller needs to call dialog_refresh_all if necessary. +BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) +{ + BOOL object_found = FALSE; + LLTool *tool = NULL; + if (!gNoRender) + { + tool = LLToolMgr::getInstance()->getCurrentTool(); + + // It's possible that the tool is editing an object that is not selected + LLViewerObject* tool_editing_object = tool->getEditingObject(); + if( tool_editing_object && tool_editing_object->mID == id) + { + tool->stopEditing(); + object_found = TRUE; + } + } + + // Iterate through selected objects list and kill the object + if( !object_found ) + { + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; + LLViewerObject* object = (*curiter)->getObject(); + if (object->mID == id) + { + if (tool) + { + tool->stopEditing(); + } + + // lose the selection, don't tell simulator, it knows + deselectObjectAndFamily(object, FALSE); + object_found = TRUE; + break; // must break here, may have removed multiple objects from list + } + else if (object->isAvatar()) + { + // It's possible the item being removed has an avatar sitting on it + // So remove the avatar that is sitting on the object. + deselectObjectAndFamily(object, FALSE); + break; // must break here, may have removed multiple objects from list + } + } + } + + return object_found; +} + +void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object) +{ + // bail if nothing selected or if object wasn't selected in the first place + if(!object) return; + if(!object->isSelected()) return; + + // Collect all of the objects, and remove them + LLDynamicArray objects; + + if (include_entire_object) + { + // Since we're selecting a family, start at the root, but + // don't include an avatar. + LLViewerObject* root = object; + + while(!root->isAvatar() && root->getParent() && !root->isJointChild()) + { + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) + { + break; + } + root = parent; + } + + object = root; + } + else + { + object = (LLViewerObject*)object->getRoot(); + } + + object->addThisAndAllChildren(objects); + remove(objects); + + if (!send_to_sim) return; + + //----------------------------------------------------------- + // Inform simulator of deselection + //----------------------------------------------------------- + LLViewerRegion* regionp = object->getRegion(); + + BOOL start_new_message = TRUE; + S32 select_count = 0; + + LLMessageSystem* msg = gMessageSystem; + for (U32 i = 0; i < objects.size(); i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_ObjectDeselect); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + select_count++; + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID()); + select_count++; + + // Zap the angular velocity, as the sim will set it to zero + objects[i]->setAngularVelocity( 0,0,0 ); + objects[i]->setVelocity( 0,0,0 ); + + if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET) + { + msg->sendReliable(regionp->getHost() ); + select_count = 0; + start_new_message = TRUE; + } + } + + if (!start_new_message) + { + msg->sendReliable(regionp->getHost() ); + } + + updatePointAt(); + updateSelectionCenter(); +} + +void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim) +{ + // bail if nothing selected or if object wasn't selected in the first place + if (!object) return; + if (!object->isSelected() ) return; + + // Zap the angular velocity, as the sim will set it to zero + object->setAngularVelocity( 0,0,0 ); + object->setVelocity( 0,0,0 ); + + if (send_to_sim) + { + LLViewerRegion* region = object->getRegion(); + gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->sendReliable(region->getHost()); + } + + // This will refresh dialogs. + remove( object ); + + updatePointAt(); + updateSelectionCenter(); +} + + +//----------------------------------------------------------------------------- +// addAsFamily +//----------------------------------------------------------------------------- + +void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to_end) +{ + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + + // Can't select yourself + if (objectp->mID == gAgentID + && !gAllowSelectAvatar) + { + continue; + } + + if (!objectp->isSelected()) + { + LLSelectNode *nodep = new LLSelectNode(objectp, TRUE); + if (add_to_end) + { + mSelectedObjects->addNodeAtEnd(nodep); + } + else + { + mSelectedObjects->addNode(nodep); + } + objectp->setSelected(TRUE); + + if (objectp->getNumTEs() > 0) + { + nodep->selectAllTEs(TRUE); + } + else + { + // object has no faces, so don't mess with faces + } + } + else + { + // we want this object to be selected for real + // so clear transient flag + LLSelectNode* select_node = mSelectedObjects->findNode(objectp); + if (select_node) + { + select_node->setTransient(FALSE); + } + } + } + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); +} + +//----------------------------------------------------------------------------- +// addAsIndividual() - a single object, face, etc +//----------------------------------------------------------------------------- +void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable) +{ + // check to see if object is already in list + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); + + // if not in list, add it + if (!nodep) + { + nodep = new LLSelectNode(objectp, TRUE); + mSelectedObjects->addNode(nodep); + llassert_always(nodep->getObject()); + } + else + { + // make this a full-fledged selection + nodep->setTransient(FALSE); + // Move it to the front of the list + mSelectedObjects->moveNodeToFront(nodep); + } + + // Make sure the object is tagged as selected + objectp->setSelected( TRUE ); + + // And make sure we don't consider it as part of a family + nodep->mIndividualSelection = TRUE; + + // Handle face selection + if (objectp->getNumTEs() <= 0) + { + // object has no faces, so don't do anything + } + else if (face == SELECT_ALL_TES) + { + nodep->selectAllTEs(TRUE); + } + else if (0 <= face && face < SELECT_MAX_TES) + { + nodep->selectTE(face, TRUE); + } + else + { + llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl; + return; + } + + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updateSelectionCenter(); + dialog_refresh_all(); +} + + +LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face) +{ + // Always blitz hover list when setting + mHoverObjects->deleteAllNodes(); + + if (!objectp) + { + return NULL; + } + + // Can't select yourself + if (objectp->mID == gAgentID) + { + return NULL; + } + + // Can't select land + if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) + { + return NULL; + } + + // Collect all of the objects + LLDynamicArray objects; + objectp = objectp->getRootEdit(); + objectp->addThisAndNonJointChildren(objects); + + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* cur_objectp = *iter; + LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); + nodep->selectTE(face, TRUE); + mHoverObjects->addNodeAtEnd(nodep); + } + + requestObjectPropertiesFamily(objectp); + return mHoverObjects; +} + +LLSelectNode *LLSelectMgr::getHoverNode() +{ + return getHoverObjects()->getFirstRootNode(); +} + +void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) +{ + if (!objectp) + { + return; + } + + if (objectp->getPCode() != LL_PCODE_VOLUME) + { + return; + } + + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) || + (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove())) + { + // only select my own objects + return; + } + + mRectSelectedObjects.insert(objectp); +} + +void LLSelectMgr::highlightObjectAndFamily(LLViewerObject* objectp) +{ + if (!objectp) + { + return; + } + + LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); + + highlightObjectOnly(root_obj); + + LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + highlightObjectOnly(child); + } +} + +// Note that this ignores the "select owned only" flag +// It's also more efficient than calling the single-object version over and over. +void LLSelectMgr::highlightObjectAndFamily(const std::vector& objects) +{ + for (std::vector::const_iterator iter1 = objects.begin(); + iter1 != objects.end(); ++iter1) + { + LLViewerObject* object = *iter1; + + if (!object) + { + continue; + } + if (object->getPCode() != LL_PCODE_VOLUME) + { + continue; + } + + LLViewerObject* root = (LLViewerObject*)object->getRoot(); + mRectSelectedObjects.insert(root); + + LLViewerObject::const_child_list_t& child_list = root->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter2 = child_list.begin(); + iter2 != child_list.end(); iter2++) + { + LLViewerObject* child = *iter2; + mRectSelectedObjects.insert(child); + } + } +} + +void LLSelectMgr::unhighlightObjectOnly(LLViewerObject* objectp) +{ + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + + mRectSelectedObjects.erase(objectp); +} + +void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp) +{ + if (!objectp) + { + return; + } + + LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); + + unhighlightObjectOnly(root_obj); + + LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + unhighlightObjectOnly(child); + } +} + + +void LLSelectMgr::unhighlightAll() +{ + mRectSelectedObjects.clear(); + mHighlightedObjects->deleteAllNodes(); +} + +LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects() +{ + if (!mHighlightedObjects->getNumNodes()) + { + return NULL; + } + + //clear primary object + mSelectedObjects->mPrimaryObject = NULL; + + for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin(); + iter != getHighlightedObjects()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; + + LLSelectNode *nodep = *curiter; + LLViewerObject* objectp = nodep->getObject(); + + if (!canSelectObject(objectp)) + { + continue; + } + + // already selected + if (objectp->isSelected()) + { + continue; + } + + LLSelectNode* new_nodep = new LLSelectNode(*nodep); + mSelectedObjects->addNode(new_nodep); + + // flag this object as selected + objectp->setSelected(TRUE); + + mSelectedObjects->mSelectType = getSelectTypeForObject(objectp); + + // request properties on root objects + if (objectp->isRootEdit()) + { + requestObjectPropertiesFamily(objectp); + } + } + + // pack up messages to let sim know these objects are selected + sendSelect(); + unhighlightAll(); + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); + + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; +} + +void LLSelectMgr::deselectHighlightedObjects() +{ + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + for (std::set >::iterator iter = mRectSelectedObjects.begin(); + iter != mRectSelectedObjects.end(); iter++) + { + LLViewerObject *objectp = *iter; + if (!select_linked_set) + { + deselectObjectOnly(objectp); + } + else + { + LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot(); + if (root_object->isSelected()) + { + deselectObjectAndFamily(root_object); + } + } + } + + unhighlightAll(); +} + +void LLSelectMgr::addGridObject(LLViewerObject* objectp) +{ + LLSelectNode* nodep = new LLSelectNode(objectp, FALSE); + mGridObjects.addNodeAtEnd(nodep); + + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + nodep = new LLSelectNode(child, FALSE); + mGridObjects.addNodeAtEnd(nodep); + } +} + +void LLSelectMgr::clearGridObjects() +{ + mGridObjects.deleteAllNodes(); +} + +void LLSelectMgr::setGridMode(EGridMode mode) +{ + mGridMode = mode; + gSavedSettings.setS32("GridMode", mode); + updateSelectionCenter(); + mGridValid = FALSE; +} + +void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale) +{ + mGridObjects.cleanupNodes(); + + LLViewerObject* first_grid_object = mGridObjects.getFirstObject(); + + if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) + { + //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject()); + LLBBox bbox = mSavedSelectionBBox; + mGridOrigin = mSavedSelectionBBox.getCenterAgent(); + mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f; + + // DEV-12570 Just taking the saved selection box rotation prevents + // wild rotations of linked sets while in local grid mode + //if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull()) + { + mGridRotation = mSavedSelectionBBox.getRotation(); + } + /*else //set to the root object + { + mGridRotation = root->getRenderRotation(); + }*/ + } + else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull()) + { + mGridRotation = first_grid_object->getRenderRotation(); + LLVector3 first_grid_obj_pos = first_grid_object->getRenderPosition(); + + LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX); + LLVector3 max_extents(-F32_MAX, -F32_MAX, -F32_MAX); + BOOL grid_changed = FALSE; + for (LLObjectSelection::iterator iter = mGridObjects.begin(); + iter != mGridObjects.end(); ++iter) + { + LLViewerObject* object = (*iter)->getObject(); + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + const LLVector3* ext = drawable->getSpatialExtents(); + update_min_max(min_extents, max_extents, ext[0]); + update_min_max(min_extents, max_extents, ext[1]); + grid_changed = TRUE; + } + } + if (grid_changed) + { + mGridOrigin = lerp(min_extents, max_extents, 0.5f); + LLDrawable* drawable = first_grid_object->mDrawable; + if (drawable && drawable->isActive()) + { + mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); + } + mGridScale = (max_extents - min_extents) * 0.5f; + } + } + else // GRID_MODE_WORLD or just plain default + { + const BOOL non_root_ok = TRUE; + LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok); + + mGridOrigin.clearVec(); + mGridRotation.loadIdentity(); + + mSelectedObjects->mSelectType = getSelectTypeForObject( first_object ); + + switch (mSelectedObjects->mSelectType) + { + case SELECT_TYPE_ATTACHMENT: + if (first_object && first_object->getRootEdit()->mDrawable.notNull()) + { + // this means this object *has* to be an attachment + LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent(); + mGridOrigin = attachment_point_xform->getWorldPosition(); + mGridRotation = attachment_point_xform->getWorldRotation(); + mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); + } + break; + case SELECT_TYPE_HUD: + // use HUD-scaled grid + mGridScale = LLVector3(0.25f, 0.25f, 0.25f); + break; + case SELECT_TYPE_WORLD: + mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); + break; + } + } + llassert(mGridOrigin.isFinite()); + + origin = mGridOrigin; + rotation = mGridRotation; + scale = mGridScale; + mGridValid = TRUE; +} + +//----------------------------------------------------------------------------- +// remove() - an array of objects +//----------------------------------------------------------------------------- + +void LLSelectMgr::remove(std::vector& objects) +{ + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + LLSelectNode* nodep = mSelectedObjects->findNode(objectp); + if (nodep) + { + objectp->setSelected(FALSE); + mSelectedObjects->removeNode(nodep); + nodep = NULL; + } + } + updateSelectionCenter(); + dialog_refresh_all(); +} + + +//----------------------------------------------------------------------------- +// remove() - a single object +//----------------------------------------------------------------------------- +void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) +{ + // get object node (and verify it is in the selected list) + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); + if (!nodep) + { + return; + } + + // if face = all, remove object from list + if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES)) + { + // Remove all faces (or the object doesn't have faces) so remove the node + mSelectedObjects->removeNode(nodep); + nodep = NULL; + objectp->setSelected( FALSE ); + } + else if (0 <= te && te < SELECT_MAX_TES) + { + // ...valid face, check to see if it was on + if (nodep->isTESelected(te)) + { + nodep->selectTE(te, FALSE); + } + else + { + llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; + return; + } + + // ...check to see if this operation turned off all faces + BOOL found = FALSE; + for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++) + { + found = found || nodep->isTESelected(i); + } + + // ...all faces now turned off, so remove + if (!found) + { + mSelectedObjects->removeNode(nodep); + nodep = NULL; + objectp->setSelected( FALSE ); + // *FIXME: Doesn't update simulator that object is no longer selected + } + } + else + { + // ...out of range face + llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; + } + + updateSelectionCenter(); + dialog_refresh_all(); +} + + +//----------------------------------------------------------------------------- +// removeAll() +//----------------------------------------------------------------------------- +void LLSelectMgr::removeAll() +{ + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setSelected( FALSE ); + } + + mSelectedObjects->deleteAllNodes(); + + updateSelectionCenter(); + dialog_refresh_all(); +} + +//----------------------------------------------------------------------------- +// promoteSelectionToRoot() +//----------------------------------------------------------------------------- +void LLSelectMgr::promoteSelectionToRoot() +{ + std::set selection_set; + + BOOL selection_changed = FALSE; + + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; + LLSelectNode* nodep = *curiter; + LLViewerObject* object = nodep->getObject(); + + if (nodep->mIndividualSelection) + { + selection_changed = TRUE; + } + + LLViewerObject* parentp = object; + while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild())) + { + parentp = (LLViewerObject*)parentp->getParent(); + } + + selection_set.insert(parentp); + } + + if (selection_changed) + { + deselectAll(); + + std::set::iterator set_iter; + for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter) + { + selectObjectAndFamily(*set_iter); + } + } +} + +//----------------------------------------------------------------------------- +// demoteSelectionToIndividuals() +//----------------------------------------------------------------------------- +void LLSelectMgr::demoteSelectionToIndividuals() +{ + LLDynamicArray objects; + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLViewerObject* object = (*iter)->getObject(); + object->addThisAndNonJointChildren(objects); + } + + if (objects.getLength()) + { + deselectAll(); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + selectObjectOnly(objectp); + } + } +} + +//----------------------------------------------------------------------------- +// dump() +//----------------------------------------------------------------------------- +void LLSelectMgr::dump() +{ + llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl; + + llinfos << "TE mode " << mTEMode << llendl; + + S32 count = 0; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLViewerObject* objectp = (*iter)->getObject(); + llinfos << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl; + llinfos << " hasLSL " << objectp->flagScripted() << llendl; + llinfos << " hasTouch " << objectp->flagHandleTouch() << llendl; + llinfos << " hasMoney " << objectp->flagTakesMoney() << llendl; + llinfos << " getposition " << objectp->getPosition() << llendl; + llinfos << " getpositionAgent " << objectp->getPositionAgent() << llendl; + llinfos << " getpositionRegion " << objectp->getPositionRegion() << llendl; + llinfos << " getpositionGlobal " << objectp->getPositionGlobal() << llendl; + LLDrawable* drawablep = objectp->mDrawable; + llinfos << " " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << llendl; + llinfos << " " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << llendl; + count++; + } + + // Face iterator + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + for (S32 te = 0; te < objectp->getNumTEs(); ++te ) + { + if (node->isTESelected(te)) + { + llinfos << "Object " << objectp << " te " << te << llendl; + } + } + } + + llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl; + + llinfos << "Center global " << mSelectionCenterGlobal << llendl; +} + +//----------------------------------------------------------------------------- +// cleanup() +//----------------------------------------------------------------------------- +void LLSelectMgr::cleanup() +{ + mSilhouetteImagep = NULL; +} + + +//--------------------------------------------------------------------------- +// Manipulate properties of selected objects +//--------------------------------------------------------------------------- + +struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor +{ + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } +}; + +//----------------------------------------------------------------------------- +// selectionSetImage() +//----------------------------------------------------------------------------- +// *TODO: re-arch texture applying out of lltooldraganddrop +void LLSelectMgr::selectionSetImage(const LLUUID& imageid) +{ + // First for (no copy) textures and multiple object selection + LLViewerInventoryItem* item = gInventory.getItem(imageid); // fffff - /* + /* // - if(item - && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) - && (mSelectedObjects->getNumNodes() > 1) ) - { - llwarns << "Attempted to apply no-copy texture to multiple objects" - << llendl; - return; - } + if(item + && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) + && (mSelectedObjects->getNumNodes() > 1) ) + { + llwarns << "Attempted to apply no-copy texture to multiple objects" + << llendl; + return; + } // */ - // - - struct f : public LLSelectedTEFunctor - { - LLViewerInventoryItem* mItem; - LLUUID mImageID; - f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} - bool apply(LLViewerObject* objectp, S32 te) - { - if (mItem) - { - if (te == -1) // all faces - { - LLToolDragAndDrop::dropTextureAllFaces(objectp, - mItem, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } - else // one face - { - LLToolDragAndDrop::dropTextureOneFace(objectp, - te, - mItem, - LLToolDragAndDrop::SOURCE_AGENT, - LLUUID::null); - } - } - else // not an inventory item - { - // Texture picker defaults aren't inventory items - // * Don't need to worry about permissions for them - // * Can just apply the texture and be done with it. - objectp->setTEImage(te, gImageList.getImage(mImageID, TRUE, FALSE)); - } - return true; - } - } setfunc(item, imageid); - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - LLViewerInventoryItem* mItem; - g(LLViewerInventoryItem* item) : mItem(item) {} - virtual bool apply(LLViewerObject* object) - { - if (!mItem) - { - object->sendTEUpdate(); + // + + struct f : public LLSelectedTEFunctor + { + LLViewerInventoryItem* mItem; + LLUUID mImageID; + f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} + bool apply(LLViewerObject* objectp, S32 te) + { + if (mItem) + { + if (te == -1) // all faces + { + LLToolDragAndDrop::dropTextureAllFaces(objectp, + mItem, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + else // one face + { + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + mItem, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + } + else // not an inventory item + { + // Texture picker defaults aren't inventory items + // * Don't need to worry about permissions for them + // * Can just apply the texture and be done with it. + objectp->setTEImage(te, gImageList.getImage(mImageID, TRUE, FALSE)); + } + return true; + } + } setfunc(item, imageid); + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + LLViewerInventoryItem* mItem; + g(LLViewerInventoryItem* item) : mItem(item) {} + virtual bool apply(LLViewerObject* object) + { + if (!mItem) + { + object->sendTEUpdate(); // 1 particle effect per object // if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { // - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setTargetObject(object); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setTargetObject(object); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); // } // - } - return true; - } - } sendfunc(item); - getSelection()->applyToObjects(&sendfunc); -} - -//----------------------------------------------------------------------------- -// selectionSetColor() -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionSetColor(const LLColor4 &color) -{ - struct f : public LLSelectedTEFunctor - { - LLColor4 mColor; - f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - object->setTEColor(te, mColor); - } - return true; - } - } setfunc(color); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -//----------------------------------------------------------------------------- -// selectionSetColorOnly() -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) -{ - struct f : public LLSelectedTEFunctor - { - LLColor4 mColor; - f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLColor4 prev_color = object->getTE(te)->getColor(); - mColor.mV[VALPHA] = prev_color.mV[VALPHA]; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, mColor); - } - return true; - } - } setfunc(color); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -//----------------------------------------------------------------------------- -// selectionSetAlphaOnly() -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) -{ - struct f : public LLSelectedTEFunctor - { - F32 mAlpha; - f(const F32& a) : mAlpha(a) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLColor4 prev_color = object->getTE(te)->getColor(); - prev_color.mV[VALPHA] = mAlpha; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, prev_color); - } - return true; - } - } setfunc(alpha); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -void LLSelectMgr::selectionRevertColors() -{ - struct f : public LLSelectedTEFunctor - { - LLObjectSelectionHandle mSelectedObjects; - f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLSelectNode* nodep = mSelectedObjects->findNode(object); - if (nodep && te < (S32)nodep->mSavedColors.size()) - { - LLColor4 color = nodep->mSavedColors[te]; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, color); - } - } - return true; - } - } setfunc(mSelectedObjects); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -BOOL LLSelectMgr::selectionRevertTextures() -{ - struct f : public LLSelectedTEFunctor - { - LLObjectSelectionHandle mSelectedObjects; - f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLSelectNode* nodep = mSelectedObjects->findNode(object); - if (nodep && te < (S32)nodep->mSavedTextures.size()) - { - LLUUID id = nodep->mSavedTextures[te]; - // update textures on viewer side - if (id.isNull()) - { - // this was probably a no-copy texture, leave image as-is - return FALSE; - } - else - { - object->setTEImage(te, gImageList.getImage(id)); - } - } - } - return true; - } - } setfunc(mSelectedObjects); - BOOL revert_successful = getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); - - return revert_successful; -} - -void LLSelectMgr::selectionSetBumpmap(U8 bumpmap) -{ - struct f : public LLSelectedTEFunctor - { - U8 mBump; - f(const U8& b) : mBump(b) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEBumpmap(te, mBump); - } - return true; - } - } setfunc(bumpmap); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -void LLSelectMgr::selectionSetTexGen(U8 texgen) -{ - struct f : public LLSelectedTEFunctor - { - U8 mTexgen; - f(const U8& t) : mTexgen(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTETexGen(te, mTexgen); - } - return true; - } - } setfunc(texgen); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - - -void LLSelectMgr::selectionSetShiny(U8 shiny) -{ - struct f : public LLSelectedTEFunctor - { - U8 mShiny; - f(const U8& t) : mShiny(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEShiny(te, mShiny); - } - return true; - } - } setfunc(shiny); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - -void LLSelectMgr::selectionSetFullbright(U8 fullbright) -{ - struct f : public LLSelectedTEFunctor - { - U8 mFullbright; - f(const U8& t) : mFullbright(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEFullbright(te, mFullbright); - } - return true; - } - } setfunc(fullbright); - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - U8 mFullbright; - g(const U8& t) : mFullbright(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - if (mFullbright) - { - U8 material = object->getMaterial(); - U8 mcode = material & LL_MCODE_MASK; - if (mcode == LL_MCODE_LIGHT) - { - mcode = LL_MCODE_GLASS; - material = (material & ~LL_MCODE_MASK) | mcode; - object->setMaterial(material); - object->sendMaterialUpdate(); - } - } - } - return true; - } - } sendfunc(fullbright); - getSelection()->applyToObjects(&sendfunc); -} - -void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url) -{ - U8 media_flags = LLTextureEntry::MF_NONE; - if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE) - { - media_flags = LLTextureEntry::MF_WEB_PAGE; - } - - struct f : public LLSelectedTEFunctor - { - U8 mMediaFlags; - f(const U8& t) : mMediaFlags(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEMediaFlags(te, mMediaFlags); - } - return true; - } - } setfunc(media_flags); - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - U8 media_type; - const std::string& media_url ; - g(U8 a, const std::string& b) : media_type(a), media_url(b) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - object->setMediaType(media_type); - object->setMediaURL(media_url); - } - return true; - } - } sendfunc(media_type, media_url); - getSelection()->applyToObjects(&sendfunc); -} - -void LLSelectMgr::selectionSetGlow(F32 glow) -{ - struct f1 : public LLSelectedTEFunctor - { - F32 mGlow; - f1(F32 glow) : mGlow(glow) {}; - bool apply(LLViewerObject* object, S32 face) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEGlow(face, mGlow); - } - return true; - } - } func1(glow); - mSelectedObjects->applyToTEs( &func1 ); - - struct f2 : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } - } func2; - mSelectedObjects->applyToObjects( &func2 ); -} - - -//----------------------------------------------------------------------------- -// findObjectPermissions() -//----------------------------------------------------------------------------- -LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object) -{ - for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); - iter != getSelection()->valid_end(); iter++ ) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object) - { - return nodep->mPermissions; - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// selectionGetGlow() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectionGetGlow(F32 *glow) -{ - BOOL identical; - F32 lglow = 0.f; - struct f1 : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - return object->getTE(face)->getGlow(); - } - } func; - identical = mSelectedObjects->getSelectedTEValue( &func, lglow ); - - *glow = lglow; - return identical; -} - -//----------------------------------------------------------------------------- -// selectionSetMaterial() -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionSetMaterial(U8 material) -{ - struct f : public LLSelectedObjectFunctor - { - U8 mMaterial; - f(const U8& t) : mMaterial(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - U8 cur_material = object->getMaterial(); - U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK); - object->setMaterial(material); - object->sendMaterialUpdate(); - } - return true; - } - } sendfunc(material); - getSelection()->applyToObjects(&sendfunc); -} - -// TRUE if all selected objects have this PCode -BOOL LLSelectMgr::selectionAllPCode(LLPCode code) -{ - struct f : public LLSelectedObjectFunctor - { - LLPCode mCode; - f(const LLPCode& t) : mCode(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->getPCode() != mCode) - { - return FALSE; - } - return true; - } - } func(code); - BOOL res = getSelection()->applyToObjects(&func); - return res; -} - -bool LLSelectMgr::selectionGetIncludeInSearch(bool* include_in_search_out) -{ - LLViewerObject *object = mSelectedObjects->getFirstRootObject(); - if (!object) return FALSE; - - bool include_in_search = object->getIncludeInSearch(); - - bool identical = true; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLViewerObject* object = (*iter)->getObject(); - - if ( include_in_search != object->getIncludeInSearch()) - { - identical = false; - break; - } - } - - *include_in_search_out = include_in_search; - return identical; -} - -void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search) -{ - LLViewerObject* object = NULL; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - object = (*iter)->getObject(); - object->setIncludeInSearch(include_in_search); - } - sendListToRegions( - "ObjectIncludeInSearch", - packAgentAndSessionID, - packObjectIncludeInSearch, - &include_in_search, - SEND_ONLY_ROOTS); -} - -BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) -{ - LLViewerObject *object = mSelectedObjects->getFirstObject(); - if (!object) - { - return FALSE; - } - - U8 action = object->getClickAction(); - *out_action = action; - - struct f : public LLSelectedObjectFunctor - { - U8 mAction; - f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) - { - if ( mAction != object->getClickAction()) - { - return false; - } - return true; - } - } func(action); - BOOL res = getSelection()->applyToObjects(&func); - return res; -} - -void LLSelectMgr::selectionSetClickAction(U8 action) -{ - struct f : public LLSelectedObjectFunctor - { - U8 mAction; - f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) - { - object->setClickAction(mAction); - return true; - } - } func(action); - getSelection()->applyToObjects(&func); - - sendListToRegions("ObjectClickAction", - packAgentAndSessionID, - packObjectClickAction, - &action, - SEND_INDIVIDUALS); -} - - -//----------------------------------------------------------------------------- -// godlike requests -//----------------------------------------------------------------------------- - -typedef std::pair godlike_request_t; - -void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::string& param) -{ - // If the agent is neither godlike nor an estate owner, the server - // will reject the request. - std::string message_type; - if (gAgent.isGodlike()) - { - message_type = "GodlikeMessage"; - } - else - { - message_type = "EstateOwnerMessage"; - } - - godlike_request_t data(request, param); - if(!mSelectedObjects->getRootObjectCount()) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage(message_type.c_str()); - LLSelectMgr::packGodlikeHead(&data); - gAgent.sendReliableMessage(); - } - else - { - sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS); - } -} - -void LLSelectMgr::packGodlikeHead(void* user_data) -{ - LLMessageSystem* msg = gMessageSystem; - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUID("TransactionID", LLUUID::null); - godlike_request_t* data = (godlike_request_t*)user_data; - msg->nextBlock("MethodData"); - msg->addString("Method", data->first); - msg->addUUID("Invoice", LLUUID::null); - - // The parameters used to be restricted to either string or - // integer. This mimics that behavior under the new 'string-only' - // parameter list by not packing a string if there wasn't one - // specified. The object ids will be packed in the - // packObjectIDAsParam() method. - if(data->second.size() > 0) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", data->second); - } -} - -// static -void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) -{ - std::string buf = llformat("%u", node->getObject()->getLocalID()); - gMessageSystem->nextBlock("ParamList"); - gMessageSystem->addString("Parameter", buf); -} - -//----------------------------------------------------------------------------- -// Rotation options -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionResetRotation() -{ - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLQuaternion identity(0.f, 0.f, 0.f, 1.f); - object->setRotation(identity); - if (object->mDrawable.notNull()) - { - gPipeline.markMoved(object->mDrawable, TRUE); - } - object->sendRotationUpdate(); - return true; - } - } func; - getSelection()->applyToRootObjects(&func); -} - -void LLSelectMgr::selectionRotateAroundZ(F32 degrees) -{ - LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) ); - struct f : public LLSelectedObjectFunctor - { - LLQuaternion mRot; - f(const LLQuaternion& rot) : mRot(rot) {} - virtual bool apply(LLViewerObject* object) - { - object->setRotation( object->getRotationEdit() * mRot ); - if (object->mDrawable.notNull()) - { - gPipeline.markMoved(object->mDrawable, TRUE); - } - object->sendRotationUpdate(); - return true; - } - } func(rot); - getSelection()->applyToRootObjects(&func); -} - - -//----------------------------------------------------------------------------- -// selectionTexScaleAutofit() -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) -{ - struct f : public LLSelectedTEFunctor - { - F32 mRepeatsPerMeter; - f(const F32& t) : mRepeatsPerMeter(t) {} - bool apply(LLViewerObject* object, S32 te) - { - - if (object->permModify()) - { - // Compute S,T to axis mapping - U32 s_axis, t_axis; - if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) - { - return TRUE; - } - - F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter; - F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter; - - object->setTEScale(te, new_s, new_t); - } - return true; - } - } setfunc(repeats_per_meter); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - - - -// Called at the end of a scale operation, this adjusts the textures to attempt to -// maintain a constant repeats per meter. -// BUG: Only works for flex boxes. -//----------------------------------------------------------------------------- -// adjustTexturesByScale() -//----------------------------------------------------------------------------- -void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) -{ - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - - if (!object) - { - continue; - } - - if (!object->permModify()) - { - continue; - } - - if (object->getNumTEs() == 0) - { - continue; - } - - BOOL send = FALSE; - - for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++) - { - const LLTextureEntry* tep = object->getTE(te_num); - - BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR; - if (planar == stretch) - { - // Figure out how S,T changed with scale operation - U32 s_axis, t_axis; - if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis)) - { - continue; - } - - LLVector3 scale_ratio = selectNode->mTextureScaleRatios[te_num]; - LLVector3 object_scale = object->getScale(); - - // Apply new scale to face - if (planar) - { - object->setTEScale(te_num, 1.f/object_scale.mV[s_axis]*scale_ratio.mV[s_axis], - 1.f/object_scale.mV[t_axis]*scale_ratio.mV[t_axis]); - } - else - { - object->setTEScale(te_num, scale_ratio.mV[s_axis]*object_scale.mV[s_axis], - scale_ratio.mV[t_axis]*object_scale.mV[t_axis]); - } - send = send_to_sim; - } - } - - if (send) - { - object->sendTEUpdate(); - } - } -} - -//----------------------------------------------------------------------------- -// selectGetAllRootsValid() -// Returns TRUE if the viewer has information on all selected objects -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetAllRootsValid() -{ - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); ++iter ) - { - LLSelectNode* node = *iter; - if( !node->mValid ) - { - return FALSE; - } - } - return TRUE; -} - - -//----------------------------------------------------------------------------- -// selectGetAllValid() -// Returns TRUE if the viewer has information on all selected objects -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetAllValid() -{ - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ++iter ) - { - LLSelectNode* node = *iter; - if( !node->mValid ) - { - return FALSE; - } - } - return TRUE; -} - - -//----------------------------------------------------------------------------- -// selectGetModify() - return TRUE if current agent can modify all -// selected objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetModify() -{ - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( !object->permModify() ) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// selectGetRootsModify() - return TRUE if current agent can modify all -// selected root objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetRootsModify() -{ - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( !object->permModify() ) - { - return FALSE; - } - } - - return TRUE; -} - - -//----------------------------------------------------------------------------- -// selectGetRootsTransfer() - return TRUE if current agent can transfer all -// selected root objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetRootsTransfer() -{ - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if(!object->permTransfer()) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// selectGetRootsCopy() - return TRUE if current agent can copy all -// selected root objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetRootsCopy() -{ - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if(!object->permCopy()) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// selectGetCreator() -// Creator information only applies to root objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) -{ - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - first_id = node->mPermissions->getCreator(); - first = FALSE; - } - else - { - if ( !(first_id == node->mPermissions->getCreator() ) ) - { - identical = FALSE; - break; - } - } - } - if (first_id.isNull()) - { - return FALSE; - } - - result_id = first_id; - - if (identical) - { - gCacheName->getFullName(first_id, name); - } - else - { - name.assign( "(multiple)" ); - } - - return identical; -} - - -//----------------------------------------------------------------------------- -// selectGetOwner() -// Owner information only applies to roots. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) -{ - BOOL identical = TRUE; - BOOL first = TRUE; - BOOL first_group_owned = FALSE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - node->mPermissions->getOwnership(first_id, first_group_owned); - first = FALSE; - } - else - { - LLUUID owner_id; - BOOL is_group_owned = FALSE; - if (!(node->mPermissions->getOwnership(owner_id, is_group_owned)) - || owner_id != first_id || is_group_owned != first_group_owned) - { - identical = FALSE; - break; - } - } - } - if (first_id.isNull()) - { - return FALSE; - } - - result_id = first_id; - - if (identical) - { - BOOL public_owner = (first_id.isNull() && !first_group_owned); - if (first_group_owned) - { - name.assign( "(Group Owned)"); - } - else if(!public_owner) - { - gCacheName->getFullName(first_id, name); - } - else - { - name.assign("Public"); - } - } - else - { - name.assign( "(multiple)" ); - } - - return identical; -} - - -//----------------------------------------------------------------------------- -// selectGetLastOwner() -// Owner information only applies to roots. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) -{ - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - first_id = node->mPermissions->getLastOwner(); - first = FALSE; - } - else - { - if ( !(first_id == node->mPermissions->getLastOwner() ) ) - { - identical = FALSE; - break; - } - } - } - if (first_id.isNull()) - { - return FALSE; - } - - result_id = first_id; - - if (identical) - { - BOOL public_owner = (first_id.isNull()); - if(!public_owner) - { - gCacheName->getFullName(first_id, name); - } - else - { - name.assign("Public or Group"); - } - } - else - { - name.assign( "" ); - } - - return identical; -} - - -//----------------------------------------------------------------------------- -// selectGetGroup() -// Group information only applies to roots. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) -{ - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - first_id = node->mPermissions->getGroup(); - first = FALSE; - } - else - { - if ( !(first_id == node->mPermissions->getGroup() ) ) - { - identical = FALSE; - break; - } - } - } - - result_id = first_id; - - return identical; -} - -//----------------------------------------------------------------------------- -// selectIsGroupOwned() -// Only operates on root nodes. -// Returns TRUE if all have valid data and they are all group owned. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectIsGroupOwned() -{ - BOOL found_one = FALSE; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - found_one = TRUE; - if (!node->mPermissions->isGroupOwned()) - { - return FALSE; - } - } - return found_one ? TRUE : FALSE; -} - -//----------------------------------------------------------------------------- -// selectGetPerm() -// Only operates on root nodes. -// Returns TRUE if all have valid data. -// mask_on has bits set to TRUE where all permissions are TRUE -// mask_off has bits set to TRUE where all permissions are FALSE -// if a bit is off both in mask_on and mask_off, the values differ within -// the selection. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) -{ - U32 mask; - U32 mask_and = 0xffffffff; - U32 mask_or = 0x00000000; - BOOL all_valid = FALSE; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - - if (!node->mValid) - { - all_valid = FALSE; - break; - } - - all_valid = TRUE; - - switch( which_perm ) - { - case PERM_BASE: - mask = node->mPermissions->getMaskBase(); - break; - case PERM_OWNER: - mask = node->mPermissions->getMaskOwner(); - break; - case PERM_GROUP: - mask = node->mPermissions->getMaskGroup(); - break; - case PERM_EVERYONE: - mask = node->mPermissions->getMaskEveryone(); - break; - case PERM_NEXT_OWNER: - mask = node->mPermissions->getMaskNextOwner(); - break; - default: - mask = 0x0; - break; - } - mask_and &= mask; - mask_or |= mask; - } - - if (all_valid) - { - // ...TRUE through all ANDs means all TRUE - *mask_on = mask_and; - - // ...FALSE through all ORs means all FALSE - *mask_off = ~mask_or; - return TRUE; - } - else - { - *mask_on = 0; - *mask_off = 0; - return FALSE; - } -} - - - -BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost) -{ - return mSelectedObjects->getOwnershipCost(*out_cost); -} - -BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm) -{ - BOOL first = TRUE; - LLPermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - perm = *(node->mPermissions); - first = FALSE; - } - else - { - perm.accumulate(*(node->mPermissions)); - } - } - - result_perm = perm; - - return TRUE; -} - - -void LLSelectMgr::selectDelete() -{ - S32 deleteable_count = 0; - - BOOL locked_but_deleteable_object = FALSE; - BOOL no_copy_but_deleteable_object = FALSE; - BOOL all_owned_by_you = TRUE; - - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++) - { - LLViewerObject* obj = (*iter)->getObject(); - - if( obj->isAttachment() ) - { - continue; - } - - deleteable_count++; - - // Check to see if you can delete objects which are locked. - if(!obj->permMove()) - { - locked_but_deleteable_object = TRUE; - } - if(!obj->permCopy()) - { - no_copy_but_deleteable_object = TRUE; - } - if(!obj->permYouOwner()) - { - all_owned_by_you = FALSE; - } - } - - if( 0 == deleteable_count ) - { - make_ui_sound("UISndInvalidOp"); - return; - } - - LLNotification::Params params("ConfirmObjectDeleteLock"); - params.functor(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection())); - - if(locked_but_deleteable_object || - no_copy_but_deleteable_object || - !all_owned_by_you) - { - // convert any transient pie-menu selections to full selection so this operation - // has some context - // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode - // but this is ok, if not ideal - convertTransient(); - - //This is messy, but needed to get all english our of the UI. - if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you) - { - //Locked only - params.name("ConfirmObjectDeleteLock"); - } - else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) - { - //No Copy only - params.name("ConfirmObjectDeleteNoCopy"); - } - else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) - { - //not owned only - params.name("ConfirmObjectDeleteNoOwn"); - } - else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) - { - //locked and no copy - params.name("ConfirmObjectDeleteLockNoCopy"); - } - else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) - { - //locked and not owned - params.name("ConfirmObjectDeleteLockNoOwn"); - } - else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you) - { - //no copy and not owned - params.name("ConfirmObjectDeleteNoCopyNoOwn"); - } - else - { - //locked, no copy and not owned - params.name("ConfirmObjectDeleteLockNoCopyNoOwn"); - } - - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } -} - -// static -bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - if (!handle->getObjectCount()) - { - llwarns << "Nothing to delete!" << llendl; - return false; - } - - switch(option) - { - case 0: - { - // TODO: Make sure you have delete permissions on all of them. - LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); - // attempt to derez into the trash. - LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); - LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", - packDeRezHeader, - packObjectLocalID, - (void*)info, - SEND_ONLY_ROOTS); + } + return true; + } + } sendfunc(item); + getSelection()->applyToObjects(&sendfunc); +} + +//----------------------------------------------------------------------------- +// selectionSetColor() +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionSetColor(const LLColor4 &color) +{ + struct f : public LLSelectedTEFunctor + { + LLColor4 mColor; + f(const LLColor4& c) : mColor(c) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + object->setTEColor(te, mColor); + } + return true; + } + } setfunc(color); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +//----------------------------------------------------------------------------- +// selectionSetColorOnly() +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) +{ + struct f : public LLSelectedTEFunctor + { + LLColor4 mColor; + f(const LLColor4& c) : mColor(c) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLColor4 prev_color = object->getTE(te)->getColor(); + mColor.mV[VALPHA] = prev_color.mV[VALPHA]; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, mColor); + } + return true; + } + } setfunc(color); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +//----------------------------------------------------------------------------- +// selectionSetAlphaOnly() +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) +{ + struct f : public LLSelectedTEFunctor + { + F32 mAlpha; + f(const F32& a) : mAlpha(a) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLColor4 prev_color = object->getTE(te)->getColor(); + prev_color.mV[VALPHA] = mAlpha; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, prev_color); + } + return true; + } + } setfunc(alpha); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionRevertColors() +{ + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedColors.size()) + { + LLColor4 color = nodep->mSavedColors[te]; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, color); + } + } + return true; + } + } setfunc(mSelectedObjects); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +BOOL LLSelectMgr::selectionRevertTextures() +{ + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedTextures.size()) + { + LLUUID id = nodep->mSavedTextures[te]; + // update textures on viewer side + if (id.isNull()) + { + // this was probably a no-copy texture, leave image as-is + return FALSE; + } + else + { + object->setTEImage(te, gImageList.getImage(id)); + } + } + } + return true; + } + } setfunc(mSelectedObjects); + BOOL revert_successful = getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); + + return revert_successful; +} + +void LLSelectMgr::selectionSetBumpmap(U8 bumpmap) +{ + struct f : public LLSelectedTEFunctor + { + U8 mBump; + f(const U8& b) : mBump(b) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEBumpmap(te, mBump); + } + return true; + } + } setfunc(bumpmap); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetTexGen(U8 texgen) +{ + struct f : public LLSelectedTEFunctor + { + U8 mTexgen; + f(const U8& t) : mTexgen(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTETexGen(te, mTexgen); + } + return true; + } + } setfunc(texgen); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + + +void LLSelectMgr::selectionSetShiny(U8 shiny) +{ + struct f : public LLSelectedTEFunctor + { + U8 mShiny; + f(const U8& t) : mShiny(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEShiny(te, mShiny); + } + return true; + } + } setfunc(shiny); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetFullbright(U8 fullbright) +{ + struct f : public LLSelectedTEFunctor + { + U8 mFullbright; + f(const U8& t) : mFullbright(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEFullbright(te, mFullbright); + } + return true; + } + } setfunc(fullbright); + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + U8 mFullbright; + g(const U8& t) : mFullbright(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + if (mFullbright) + { + U8 material = object->getMaterial(); + U8 mcode = material & LL_MCODE_MASK; + if (mcode == LL_MCODE_LIGHT) + { + mcode = LL_MCODE_GLASS; + material = (material & ~LL_MCODE_MASK) | mcode; + object->setMaterial(material); + object->sendMaterialUpdate(); + } + } + } + return true; + } + } sendfunc(fullbright); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url) +{ + U8 media_flags = LLTextureEntry::MF_NONE; + if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE) + { + media_flags = LLTextureEntry::MF_WEB_PAGE; + } + + struct f : public LLSelectedTEFunctor + { + U8 mMediaFlags; + f(const U8& t) : mMediaFlags(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEMediaFlags(te, mMediaFlags); + } + return true; + } + } setfunc(media_flags); + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + U8 media_type; + const std::string& media_url ; + g(U8 a, const std::string& b) : media_type(a), media_url(b) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + object->setMediaType(media_type); + object->setMediaURL(media_url); + } + return true; + } + } sendfunc(media_type, media_url); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetGlow(F32 glow) +{ + struct f1 : public LLSelectedTEFunctor + { + F32 mGlow; + f1(F32 glow) : mGlow(glow) {}; + bool apply(LLViewerObject* object, S32 face) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEGlow(face, mGlow); + } + return true; + } + } func1(glow); + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); +} + + +//----------------------------------------------------------------------------- +// findObjectPermissions() +//----------------------------------------------------------------------------- +LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object) +{ + for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); + iter != getSelection()->valid_end(); iter++ ) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object) + { + return nodep->mPermissions; + } + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// selectionGetGlow() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectionGetGlow(F32 *glow) +{ + BOOL identical; + F32 lglow = 0.f; + struct f1 : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + return object->getTE(face)->getGlow(); + } + } func; + identical = mSelectedObjects->getSelectedTEValue( &func, lglow ); + + *glow = lglow; + return identical; +} + +//----------------------------------------------------------------------------- +// selectionSetMaterial() +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionSetMaterial(U8 material) +{ + struct f : public LLSelectedObjectFunctor + { + U8 mMaterial; + f(const U8& t) : mMaterial(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + U8 cur_material = object->getMaterial(); + U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK); + object->setMaterial(material); + object->sendMaterialUpdate(); + } + return true; + } + } sendfunc(material); + getSelection()->applyToObjects(&sendfunc); +} + +// TRUE if all selected objects have this PCode +BOOL LLSelectMgr::selectionAllPCode(LLPCode code) +{ + struct f : public LLSelectedObjectFunctor + { + LLPCode mCode; + f(const LLPCode& t) : mCode(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->getPCode() != mCode) + { + return FALSE; + } + return true; + } + } func(code); + BOOL res = getSelection()->applyToObjects(&func); + return res; +} + +bool LLSelectMgr::selectionGetIncludeInSearch(bool* include_in_search_out) +{ + LLViewerObject *object = mSelectedObjects->getFirstRootObject(); + if (!object) return FALSE; + + bool include_in_search = object->getIncludeInSearch(); + + bool identical = true; + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLViewerObject* object = (*iter)->getObject(); + + if ( include_in_search != object->getIncludeInSearch()) + { + identical = false; + break; + } + } + + *include_in_search_out = include_in_search; + return identical; +} + +void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search) +{ + LLViewerObject* object = NULL; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + object = (*iter)->getObject(); + object->setIncludeInSearch(include_in_search); + } + sendListToRegions( + "ObjectIncludeInSearch", + packAgentAndSessionID, + packObjectIncludeInSearch, + &include_in_search, + SEND_ONLY_ROOTS); +} + +BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) +{ + LLViewerObject *object = mSelectedObjects->getFirstObject(); + if (!object) + { + return FALSE; + } + + U8 action = object->getClickAction(); + *out_action = action; + + struct f : public LLSelectedObjectFunctor + { + U8 mAction; + f(const U8& t) : mAction(t) {} + virtual bool apply(LLViewerObject* object) + { + if ( mAction != object->getClickAction()) + { + return false; + } + return true; + } + } func(action); + BOOL res = getSelection()->applyToObjects(&func); + return res; +} + +void LLSelectMgr::selectionSetClickAction(U8 action) +{ + struct f : public LLSelectedObjectFunctor + { + U8 mAction; + f(const U8& t) : mAction(t) {} + virtual bool apply(LLViewerObject* object) + { + object->setClickAction(mAction); + return true; + } + } func(action); + getSelection()->applyToObjects(&func); + + sendListToRegions("ObjectClickAction", + packAgentAndSessionID, + packObjectClickAction, + &action, + SEND_INDIVIDUALS); +} + + +//----------------------------------------------------------------------------- +// godlike requests +//----------------------------------------------------------------------------- + +typedef std::pair godlike_request_t; + +void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::string& param) +{ + // If the agent is neither godlike nor an estate owner, the server + // will reject the request. + std::string message_type; + if (gAgent.isGodlike()) + { + message_type = "GodlikeMessage"; + } + else + { + message_type = "EstateOwnerMessage"; + } + + godlike_request_t data(request, param); + if(!mSelectedObjects->getRootObjectCount()) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage(message_type.c_str()); + LLSelectMgr::packGodlikeHead(&data); + gAgent.sendReliableMessage(); + } + else + { + sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS); + } +} + +void LLSelectMgr::packGodlikeHead(void* user_data) +{ + LLMessageSystem* msg = gMessageSystem; + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUID("TransactionID", LLUUID::null); + godlike_request_t* data = (godlike_request_t*)user_data; + msg->nextBlock("MethodData"); + msg->addString("Method", data->first); + msg->addUUID("Invoice", LLUUID::null); + + // The parameters used to be restricted to either string or + // integer. This mimics that behavior under the new 'string-only' + // parameter list by not packing a string if there wasn't one + // specified. The object ids will be packed in the + // packObjectIDAsParam() method. + if(data->second.size() > 0) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", data->second); + } +} + +// static +void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) +{ + std::string buf = llformat("%u", node->getObject()->getLocalID()); + gMessageSystem->nextBlock("ParamList"); + gMessageSystem->addString("Parameter", buf); +} + +//----------------------------------------------------------------------------- +// Rotation options +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionResetRotation() +{ + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLQuaternion identity(0.f, 0.f, 0.f, 1.f); + object->setRotation(identity); + if (object->mDrawable.notNull()) + { + gPipeline.markMoved(object->mDrawable, TRUE); + } + object->sendRotationUpdate(); + return true; + } + } func; + getSelection()->applyToRootObjects(&func); +} + +void LLSelectMgr::selectionRotateAroundZ(F32 degrees) +{ + LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) ); + struct f : public LLSelectedObjectFunctor + { + LLQuaternion mRot; + f(const LLQuaternion& rot) : mRot(rot) {} + virtual bool apply(LLViewerObject* object) + { + object->setRotation( object->getRotationEdit() * mRot ); + if (object->mDrawable.notNull()) + { + gPipeline.markMoved(object->mDrawable, TRUE); + } + object->sendRotationUpdate(); + return true; + } + } func(rot); + getSelection()->applyToRootObjects(&func); +} + + +//----------------------------------------------------------------------------- +// selectionTexScaleAutofit() +//----------------------------------------------------------------------------- +void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) +{ + struct f : public LLSelectedTEFunctor + { + F32 mRepeatsPerMeter; + f(const F32& t) : mRepeatsPerMeter(t) {} + bool apply(LLViewerObject* object, S32 te) + { + + if (object->permModify()) + { + // Compute S,T to axis mapping + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return TRUE; + } + + F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter; + F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter; + + object->setTEScale(te, new_s, new_t); + } + return true; + } + } setfunc(repeats_per_meter); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + + + +// Called at the end of a scale operation, this adjusts the textures to attempt to +// maintain a constant repeats per meter. +// BUG: Only works for flex boxes. +//----------------------------------------------------------------------------- +// adjustTexturesByScale() +//----------------------------------------------------------------------------- +void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + + if (!object) + { + continue; + } + + if (!object->permModify()) + { + continue; + } + + if (object->getNumTEs() == 0) + { + continue; + } + + BOOL send = FALSE; + + for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++) + { + const LLTextureEntry* tep = object->getTE(te_num); + + BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR; + if (planar == stretch) + { + // Figure out how S,T changed with scale operation + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis)) + { + continue; + } + + LLVector3 scale_ratio = selectNode->mTextureScaleRatios[te_num]; + LLVector3 object_scale = object->getScale(); + + // Apply new scale to face + if (planar) + { + object->setTEScale(te_num, 1.f/object_scale.mV[s_axis]*scale_ratio.mV[s_axis], + 1.f/object_scale.mV[t_axis]*scale_ratio.mV[t_axis]); + } + else + { + object->setTEScale(te_num, scale_ratio.mV[s_axis]*object_scale.mV[s_axis], + scale_ratio.mV[t_axis]*object_scale.mV[t_axis]); + } + send = send_to_sim; + } + } + + if (send) + { + object->sendTEUpdate(); + } + } +} + +//----------------------------------------------------------------------------- +// selectGetAllRootsValid() +// Returns TRUE if the viewer has information on all selected objects +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetAllRootsValid() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); ++iter ) + { + LLSelectNode* node = *iter; + if( !node->mValid ) + { + return FALSE; + } + } + return TRUE; +} + + +//----------------------------------------------------------------------------- +// selectGetAllValid() +// Returns TRUE if the viewer has information on all selected objects +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetAllValid() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ++iter ) + { + LLSelectNode* node = *iter; + if( !node->mValid ) + { + return FALSE; + } + } + return TRUE; +} + + +//----------------------------------------------------------------------------- +// selectGetModify() - return TRUE if current agent can modify all +// selected objects. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetModify() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->permModify() ) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsModify() - return TRUE if current agent can modify all +// selected root objects. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsModify() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->permModify() ) + { + return FALSE; + } + } + + return TRUE; +} + + +//----------------------------------------------------------------------------- +// selectGetRootsTransfer() - return TRUE if current agent can transfer all +// selected root objects. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsTransfer() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if(!object->permTransfer()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsCopy() - return TRUE if current agent can copy all +// selected root objects. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsCopy() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if(!object->permCopy()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetCreator() +// Creator information only applies to root objects. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) +{ + BOOL identical = TRUE; + BOOL first = TRUE; + LLUUID first_id; + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + first_id = node->mPermissions->getCreator(); + first = FALSE; + } + else + { + if ( !(first_id == node->mPermissions->getCreator() ) ) + { + identical = FALSE; + break; + } + } + } + if (first_id.isNull()) + { + return FALSE; + } + + result_id = first_id; + + if (identical) + { + gCacheName->getFullName(first_id, name); + } + else + { + name.assign( "(multiple)" ); + } + + return identical; +} + + +//----------------------------------------------------------------------------- +// selectGetOwner() +// Owner information only applies to roots. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) +{ + BOOL identical = TRUE; + BOOL first = TRUE; + BOOL first_group_owned = FALSE; + LLUUID first_id; + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + node->mPermissions->getOwnership(first_id, first_group_owned); + first = FALSE; + } + else + { + LLUUID owner_id; + BOOL is_group_owned = FALSE; + if (!(node->mPermissions->getOwnership(owner_id, is_group_owned)) + || owner_id != first_id || is_group_owned != first_group_owned) + { + identical = FALSE; + break; + } + } + } + if (first_id.isNull()) + { + return FALSE; + } + + result_id = first_id; + + if (identical) + { + BOOL public_owner = (first_id.isNull() && !first_group_owned); + if (first_group_owned) + { + name.assign( "(Group Owned)"); + } + else if(!public_owner) + { + gCacheName->getFullName(first_id, name); + } + else + { + name.assign("Public"); + } + } + else + { + name.assign( "(multiple)" ); + } + + return identical; +} + + +//----------------------------------------------------------------------------- +// selectGetLastOwner() +// Owner information only applies to roots. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) +{ + BOOL identical = TRUE; + BOOL first = TRUE; + LLUUID first_id; + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + first_id = node->mPermissions->getLastOwner(); + first = FALSE; + } + else + { + if ( !(first_id == node->mPermissions->getLastOwner() ) ) + { + identical = FALSE; + break; + } + } + } + if (first_id.isNull()) + { + return FALSE; + } + + result_id = first_id; + + if (identical) + { + BOOL public_owner = (first_id.isNull()); + if(!public_owner) + { + gCacheName->getFullName(first_id, name); + } + else + { + name.assign("Public or Group"); + } + } + else + { + name.assign( "" ); + } + + return identical; +} + + +//----------------------------------------------------------------------------- +// selectGetGroup() +// Group information only applies to roots. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) +{ + BOOL identical = TRUE; + BOOL first = TRUE; + LLUUID first_id; + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + first_id = node->mPermissions->getGroup(); + first = FALSE; + } + else + { + if ( !(first_id == node->mPermissions->getGroup() ) ) + { + identical = FALSE; + break; + } + } + } + + result_id = first_id; + + return identical; +} + +//----------------------------------------------------------------------------- +// selectIsGroupOwned() +// Only operates on root nodes. +// Returns TRUE if all have valid data and they are all group owned. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectIsGroupOwned() +{ + BOOL found_one = FALSE; + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + found_one = TRUE; + if (!node->mPermissions->isGroupOwned()) + { + return FALSE; + } + } + return found_one ? TRUE : FALSE; +} + +//----------------------------------------------------------------------------- +// selectGetPerm() +// Only operates on root nodes. +// Returns TRUE if all have valid data. +// mask_on has bits set to TRUE where all permissions are TRUE +// mask_off has bits set to TRUE where all permissions are FALSE +// if a bit is off both in mask_on and mask_off, the values differ within +// the selection. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) +{ + U32 mask; + U32 mask_and = 0xffffffff; + U32 mask_or = 0x00000000; + BOOL all_valid = FALSE; + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + + if (!node->mValid) + { + all_valid = FALSE; + break; + } + + all_valid = TRUE; + + switch( which_perm ) + { + case PERM_BASE: + mask = node->mPermissions->getMaskBase(); + break; + case PERM_OWNER: + mask = node->mPermissions->getMaskOwner(); + break; + case PERM_GROUP: + mask = node->mPermissions->getMaskGroup(); + break; + case PERM_EVERYONE: + mask = node->mPermissions->getMaskEveryone(); + break; + case PERM_NEXT_OWNER: + mask = node->mPermissions->getMaskNextOwner(); + break; + default: + mask = 0x0; + break; + } + mask_and &= mask; + mask_or |= mask; + } + + if (all_valid) + { + // ...TRUE through all ANDs means all TRUE + *mask_on = mask_and; + + // ...FALSE through all ORs means all FALSE + *mask_off = ~mask_or; + return TRUE; + } + else + { + *mask_on = 0; + *mask_off = 0; + return FALSE; + } +} + + + +BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost) +{ + return mSelectedObjects->getOwnershipCost(*out_cost); +} + +BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm) +{ + BOOL first = TRUE; + LLPermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + perm = *(node->mPermissions); + first = FALSE; + } + else + { + perm.accumulate(*(node->mPermissions)); + } + } + + result_perm = perm; + + return TRUE; +} + + +void LLSelectMgr::selectDelete() +{ + S32 deleteable_count = 0; + + BOOL locked_but_deleteable_object = FALSE; + BOOL no_copy_but_deleteable_object = FALSE; + BOOL all_owned_by_you = TRUE; + + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++) + { + LLViewerObject* obj = (*iter)->getObject(); + + if( obj->isAttachment() ) + { + continue; + } + + deleteable_count++; + + // Check to see if you can delete objects which are locked. + if(!obj->permMove()) + { + locked_but_deleteable_object = TRUE; + } + if(!obj->permCopy()) + { + no_copy_but_deleteable_object = TRUE; + } + if(!obj->permYouOwner()) + { + all_owned_by_you = FALSE; + } + } + + if( 0 == deleteable_count ) + { + make_ui_sound("UISndInvalidOp"); + return; + } + + LLNotification::Params params("ConfirmObjectDeleteLock"); + params.functor(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection())); + + if(locked_but_deleteable_object || + no_copy_but_deleteable_object || + !all_owned_by_you) + { + // convert any transient pie-menu selections to full selection so this operation + // has some context + // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode + // but this is ok, if not ideal + convertTransient(); + + //This is messy, but needed to get all english our of the UI. + if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you) + { + //Locked only + params.name("ConfirmObjectDeleteLock"); + } + else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) + { + //No Copy only + params.name("ConfirmObjectDeleteNoCopy"); + } + else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) + { + //not owned only + params.name("ConfirmObjectDeleteNoOwn"); + } + else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) + { + //locked and no copy + params.name("ConfirmObjectDeleteLockNoCopy"); + } + else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) + { + //locked and not owned + params.name("ConfirmObjectDeleteLockNoOwn"); + } + else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you) + { + //no copy and not owned + params.name("ConfirmObjectDeleteNoCopyNoOwn"); + } + else + { + //locked, no copy and not owned + params.name("ConfirmObjectDeleteLockNoCopyNoOwn"); + } + + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } +} + +// static +bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (!handle->getObjectCount()) + { + llwarns << "Nothing to delete!" << llendl; + return false; + } + + switch(option) + { + case 0: + { + // TODO: Make sure you have delete permissions on all of them. + LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + // attempt to derez into the trash. + LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); + LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", + packDeRezHeader, + packObjectLocalID, + (void*)info, + SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes - // if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) - // - if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) - { - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - F32 duration = 0.5f; - duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; - effectp->setDuration(duration); - } - - gAgent.setLookAt(LOOKAT_TARGET_CLEAR); - - // Keep track of how many objects have been deleted. - F64 obj_delete_count = LLViewerStats::getInstance()->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT); - obj_delete_count += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount(); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count ); - } - break; - case 1: - default: - break; - } - return false; -} - - -void LLSelectMgr::selectForceDelete() -{ - sendListToRegions( - "ObjectDelete", - packDeleteHeader, - packObjectLocalID, - (void*)TRUE, - SEND_ONLY_ROOTS); -} - -void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale, - BOOL &is_for_sale_mixed, - BOOL &is_sale_price_mixed, - S32 &total_sale_price, - S32 &individual_sale_price) -{ - num_for_sale = 0; - is_for_sale_mixed = FALSE; - is_sale_price_mixed = FALSE; - total_sale_price = 0; - individual_sale_price = 0; - - - // Empty set. - if (getSelection()->root_begin() == getSelection()->root_end()) - return; - - LLSelectNode *node = *(getSelection()->root_begin()); - const BOOL first_node_for_sale = node->mSaleInfo.isForSale(); - const S32 first_node_sale_price = node->mSaleInfo.getSalePrice(); - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - const BOOL node_for_sale = node->mSaleInfo.isForSale(); - const S32 node_sale_price = node->mSaleInfo.getSalePrice(); - - // Set mixed if the fields don't match the first node's fields. - if (node_for_sale != first_node_for_sale) - is_for_sale_mixed = TRUE; - if (node_sale_price != first_node_sale_price) - is_sale_price_mixed = TRUE; - - if (node_for_sale) - { - total_sale_price += node_sale_price; - num_for_sale ++; - } - } - - individual_sale_price = first_node_sale_price; - if (is_for_sale_mixed) - { - is_sale_price_mixed = TRUE; - individual_sale_price = 0; - } -} - -// returns TRUE if all nodes are valid. method also stores an -// accumulated sale info. -BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info) -{ - BOOL first = TRUE; - LLSaleInfo sale_info; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - sale_info = node->mSaleInfo; - first = FALSE; - } - else - { - sale_info.accumulate(node->mSaleInfo); - } - } - - result_sale_info = sale_info; - - return TRUE; -} - -BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm) -{ - BOOL first = TRUE; - LLAggregatePermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - perm = node->mAggregatePerm; - first = FALSE; - } - else - { - perm.aggregate(node->mAggregatePerm); - } - } - - result_perm = perm; - - return TRUE; -} - -BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& result_perm) -{ - BOOL first = TRUE; - LLAggregatePermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm; - if (first) - { - perm = t_perm; - first = FALSE; - } - else - { - perm.aggregate(t_perm); - } - } - - result_perm = perm; - - return TRUE; -} - - -//-------------------------------------------------------------------- -// Duplicate objects -//-------------------------------------------------------------------- - -// JC - If this doesn't work right, duplicate the selection list -// before doing anything, do a deselect, then send the duplicate -// messages. -struct LLDuplicateData -{ - LLVector3 offset; - U32 flags; -}; - -void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) -{ - if (mSelectedObjects->isAttachment()) - { - //RN: do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - LLDuplicateData data; - - data.offset = offset; - data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); - - if (select_copy) - { - // the new copy will be coming in selected - deselectAll(); - } - else - { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - node->mDuplicated = TRUE; - node->mDuplicatePos = node->getObject()->getPositionGlobal(); - node->mDuplicateRot = node->getObject()->getRotation(); - } - } -} - -void LLSelectMgr::repeatDuplicate() -{ - if (mSelectedObjects->isAttachment()) - { - //RN: do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - - std::vector non_duplicated_objects; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mDuplicated) - { - non_duplicated_objects.push_back(node->getObject()); - } - } - - // make sure only previously duplicated objects are selected - for (std::vector::iterator iter = non_duplicated_objects.begin(); - iter != non_duplicated_objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - deselectObjectAndFamily(objectp); - } - - // duplicate objects in place - LLDuplicateData data; - - data.offset = LLVector3::zero; - data.flags = 0x0; - - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); - - // move current selection based on delta from duplication position and update duplication position - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (node->mDuplicated) - { - LLQuaternion cur_rot = node->getObject()->getRotation(); - LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot); - LLQuaternion new_rot = cur_rot * rot_delta; - LLVector3d cur_pos = node->getObject()->getPositionGlobal(); - LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta); - - node->mDuplicatePos = node->getObject()->getPositionGlobal(); - node->mDuplicateRot = node->getObject()->getRotation(); - node->getObject()->setPositionGlobal(new_pos); - node->getObject()->setRotation(new_rot); - } - } - - sendMultipleUpdate(UPD_ROTATION | UPD_POSITION); -} - -// static -void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data ) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); -} - - -//-------------------------------------------------------------------- -// Duplicate On Ray -//-------------------------------------------------------------------- - -// Duplicates the selected objects, but places the copy along a cast -// ray. -struct LLDuplicateOnRayData -{ - LLVector3 mRayStartRegion; - LLVector3 mRayEndRegion; - BOOL mBypassRaycast; - BOOL mRayEndIsIntersection; - LLUUID mRayTargetID; - BOOL mCopyCenters; - BOOL mCopyRotates; - U32 mFlags; -}; - -void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, - const LLVector3 &ray_end_region, - BOOL bypass_raycast, - BOOL ray_end_is_intersection, - const LLUUID &ray_target_id, - BOOL copy_centers, - BOOL copy_rotates, - BOOL select_copy) -{ - if (mSelectedObjects->isAttachment()) - { - // do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - - LLDuplicateOnRayData data; - - data.mRayStartRegion = ray_start_region; - data.mRayEndRegion = ray_end_region; - data.mBypassRaycast = bypass_raycast; - data.mRayEndIsIntersection = ray_end_is_intersection; - data.mRayTargetID = ray_target_id; - data.mCopyCenters = copy_centers; - data.mCopyRotates = copy_rotates; - data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - - sendListToRegions("ObjectDuplicateOnRay", - packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); - - if (select_copy) - { - // the new copy will be coming in selected - deselectAll(); - } -} - -// static -void LLSelectMgr::packDuplicateOnRayHead(void *user_data) -{ - LLMessageSystem *msg = gMessageSystem; - LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data; - - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); - msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion ); - msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion ); - msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast ); - msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection ); - msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters ); - msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates ); - msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID ); - msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags ); -} - - - -//------------------------------------------------------------------------ -// Object position, scale, rotation update, all-in-one -//------------------------------------------------------------------------ - -void LLSelectMgr::sendMultipleUpdate(U32 type) -{ - if (type == UPD_NONE) return; - // send individual updates when selecting textures or individual objects - ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST; - if (send_type == SEND_ONLY_ROOTS) - { - // tell simulator to apply to whole linked sets - type |= UPD_LINKED_SETS; - } - - sendListToRegions( - "MultipleObjectUpdate", - packAgentAndSessionID, - packMultipleUpdate, - &type, - send_type); -} - -// static -void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data) -{ - LLViewerObject* object = node->getObject(); - U32 *type32 = (U32 *)user_data; - U8 type = (U8)*type32; - U8 data[256]; - - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->addU8Fast(_PREHASH_Type, type ); - - S32 offset = 0; - - // JC: You MUST pack the data in this order. The receiving - // routine process_multiple_update_message on simulator will - // extract them in this order. - - if (type & UPD_POSITION) - { - htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); - offset += 12; - } - if (type & UPD_ROTATION) - { - LLQuaternion quat = object->getRotation(); - LLVector3 vec = quat.packToVector3(); - htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); - offset += 12; - } - if (type & UPD_SCALE) - { - //llinfos << "Sending object scale " << object->getScale() << llendl; - htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); - offset += 12; - } - gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); -} - -//------------------------------------------------------------------------ -// Ownership -//------------------------------------------------------------------------ -struct LLOwnerData -{ - LLUUID owner_id; - LLUUID group_id; - BOOL override; -}; - -void LLSelectMgr::sendOwner(const LLUUID& owner_id, - const LLUUID& group_id, - BOOL override) -{ - LLOwnerData data; - - data.owner_id = owner_id; - data.group_id = group_id; - data.override = override; - - sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); -} - -// static -void LLSelectMgr::packOwnerHead(void *user_data) -{ - LLOwnerData *data = (LLOwnerData *)user_data; - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - gMessageSystem->nextBlockFast(_PREHASH_HeaderData); - gMessageSystem->addBOOLFast(_PREHASH_Override, data->override); - gMessageSystem->addUUIDFast(_PREHASH_OwnerID, data->owner_id); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id); -} - -//------------------------------------------------------------------------ -// Group -//------------------------------------------------------------------------ - -void LLSelectMgr::sendGroup(const LLUUID& group_id) -{ - LLUUID local_group_id(group_id); - sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS); -} - - -//------------------------------------------------------------------------ -// Buy -//------------------------------------------------------------------------ - -struct LLBuyData -{ - std::vector mObjectsSent; - LLUUID mCategoryID; - LLSaleInfo mSaleInfo; -}; - -// *NOTE: does not work for multiple object buy, which UI does not -// currently support sale info is used for verification only, if it -// doesn't match region info then sale is canceled Need to get sale -// info -as displayed in the UI- for every item. -void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info) -{ - LLBuyData buy; - buy.mCategoryID = category_id; - buy.mSaleInfo = sale_info; - sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS); -} - -// static -void LLSelectMgr::packBuyObjectIDs(LLSelectNode* node, void* data) -{ - LLBuyData* buy = (LLBuyData*)data; - - LLViewerObject* object = node->getObject(); - if (std::find(buy->mObjectsSent.begin(), buy->mObjectsSent.end(), object) == buy->mObjectsSent.end()) - { - buy->mObjectsSent.push_back(object); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->addU8Fast(_PREHASH_SaleType, buy->mSaleInfo.getSaleType()); - gMessageSystem->addS32Fast(_PREHASH_SalePrice, buy->mSaleInfo.getSalePrice()); - } -} - -//------------------------------------------------------------------------ -// Permissions -//------------------------------------------------------------------------ - -struct LLPermData -{ - U8 mField; - BOOL mSet; - U32 mMask; - BOOL mOverride; -}; - -// TODO: Make this able to fail elegantly. -void LLSelectMgr::selectionSetObjectPermissions(U8 field, - BOOL set, - U32 mask, - BOOL override) -{ - LLPermData data; - - data.mField = field; - data.mSet = set; - data.mMask = mask; - data.mOverride = override; - - sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS); -} - -void LLSelectMgr::packPermissionsHead(void* user_data) -{ - LLPermData* data = (LLPermData*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_HeaderData); - gMessageSystem->addBOOLFast(_PREHASH_Override, data->mOverride); -} - - -// Now that you've added a bunch of objects, send a select message -// on the entire list for efficiency. -/* -void LLSelectMgr::sendSelect() -{ - llerrs << "Not implemented" << llendl; -} -*/ - -void LLSelectMgr::deselectAll() -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - // Zap the angular velocity, as the sim will set it to zero - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setAngularVelocity( 0,0,0 ); - objectp->setVelocity( 0,0,0 ); - } - - sendListToRegions( - "ObjectDeselect", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_INDIVIDUALS); - - removeAll(); - - mLastSentSelectionCenterGlobal.clearVec(); - - updatePointAt(); -} - -void LLSelectMgr::deselectAllForStandingUp() -{ - /* - This function is similar deselectAll() except for the first if statement - which was removed. This is needed as a workaround for DEV-2854 - */ - - // Zap the angular velocity, as the sim will set it to zero - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setAngularVelocity( 0,0,0 ); - objectp->setVelocity( 0,0,0 ); - } - - sendListToRegions( - "ObjectDeselect", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_INDIVIDUALS); - - removeAll(); - - mLastSentSelectionCenterGlobal.clearVec(); - - updatePointAt(); -} - -void LLSelectMgr::deselectUnused() -{ - // no more outstanding references to this selection - if (mSelectedObjects->getNumRefs() == 1) - { - deselectAll(); - } -} - -void LLSelectMgr::convertTransient() -{ - LLObjectSelection::iterator node_it; - for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it) - { - LLSelectNode *nodep = *node_it; - nodep->setTransient(FALSE); - } -} - -void LLSelectMgr::deselectAllIfTooFar() -{ - if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD) - { - return; - } - - // HACK: Don't deselect when we're navigating to rate an object's - // owner or creator. JC - if (gPieObject->getVisible() || gPieRate->getVisible() ) - { - return; - } - - LLVector3d selectionCenter = getSelectionCenterGlobal(); - if (gSavedSettings.getBOOL("LimitSelectDistance") - && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) - && !mSelectedObjects->isAttachment() - && !selectionCenter.isExactlyZero()) - { - F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); - F32 deselect_dist_sq = deselect_dist * deselect_dist; - - LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; - F32 select_dist_sq = (F32) select_delta.magVecSquared(); - - if (select_dist_sq > deselect_dist_sq) - { - if (gDebugSelectMgr) - { - llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl; - llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl; - llinfos << "selection pos global = " << selectionCenter << llendl; - } - - deselectAll(); - } - } -} - - -void LLSelectMgr::selectionSetObjectName(const std::string& name) -{ - // we only work correctly if 1 object is selected. - if(mSelectedObjects->getRootObjectCount() == 1) - { - sendListToRegions("ObjectName", - packAgentAndSessionID, - packObjectName, - (void*)(new std::string(name)), - SEND_ONLY_ROOTS); - } - else if(mSelectedObjects->getObjectCount() == 1) - { - sendListToRegions("ObjectName", - packAgentAndSessionID, - packObjectName, - (void*)(new std::string(name)), - SEND_INDIVIDUALS); - } -} - -void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) -{ - // we only work correctly if 1 object is selected. - if(mSelectedObjects->getRootObjectCount() == 1) - { - sendListToRegions("ObjectDescription", - packAgentAndSessionID, - packObjectDescription, - (void*)(new std::string(desc)), - SEND_ONLY_ROOTS); - } - else if(mSelectedObjects->getObjectCount() == 1) - { - sendListToRegions("ObjectDescription", - packAgentAndSessionID, - packObjectDescription, - (void*)(new std::string(desc)), - SEND_INDIVIDUALS); - } -} - -void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) -{ - // for now, we only want to be able to set one root category at - // a time. - if(mSelectedObjects->getRootObjectCount() != 1) return; - sendListToRegions("ObjectCategory", - packAgentAndSessionID, - packObjectCategory, - (void*)(&category), - SEND_ONLY_ROOTS); -} - -void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) -{ - sendListToRegions("ObjectSaleInfo", - packAgentAndSessionID, - packObjectSaleInfo, - (void*)(&sale_info), - SEND_ONLY_ROOTS); -} - -//---------------------------------------------------------------------- -// Attachments -//---------------------------------------------------------------------- - -void LLSelectMgr::sendAttach(U8 attachment_point) -{ - LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject(); - - if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD) - { - return; - } - - BOOL build_mode = LLToolMgr::getInstance()->inEdit(); - // Special case: Attach to default location for this object. - if (0 == attachment_point || - get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) - { - sendListToRegions( - "ObjectAttach", - packAgentIDAndSessionAndAttachment, - packObjectIDAndRotation, - &attachment_point, - SEND_ONLY_ROOTS ); - if (!build_mode) - { - deselectAll(); - } - } -} - -void LLSelectMgr::sendDetach() -{ - if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) - { - return; - } - - sendListToRegions( - "ObjectDetach", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_ONLY_ROOTS ); -} - - -void LLSelectMgr::sendDropAttachment() -{ - if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) - { - return; - } - - sendListToRegions( - "ObjectDrop", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_ONLY_ROOTS); -} - -//---------------------------------------------------------------------- -// Links -//---------------------------------------------------------------------- - -void LLSelectMgr::sendLink() -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - sendListToRegions( - "ObjectLink", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_ONLY_ROOTS); -} - -void LLSelectMgr::sendDelink() -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - // Delink needs to send individuals so you can unlink a single object from - // a linked set. - sendListToRegions( - "ObjectDelink", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_INDIVIDUALS); -} - - -//---------------------------------------------------------------------- -// Hinges -//---------------------------------------------------------------------- - -/* -void LLSelectMgr::sendHinge(U8 type) -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - sendListToRegions( - "ObjectHinge", - packHingeHead, - packObjectLocalID, - &type, - SEND_ONLY_ROOTS); -} - - -void LLSelectMgr::sendDehinge() -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - sendListToRegions( - "ObjectDehinge", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_ONLY_ROOTS); -}*/ - -void LLSelectMgr::sendSelect() -{ - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - sendListToRegions( - "ObjectSelect", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_INDIVIDUALS); -} - -// static -void LLSelectMgr::packHingeHead(void *user_data) -{ - U8 *type = (U8 *)user_data; - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - gMessageSystem->nextBlockFast(_PREHASH_JointType); - gMessageSystem->addU8Fast(_PREHASH_Type, *type ); -} - - -void LLSelectMgr::selectionDump() -{ - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - object->dump(); - return true; - } - } func; - getSelection()->applyToObjects(&func); -} - -void LLSelectMgr::saveSelectedObjectColors() -{ - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->saveColors(); - return true; - } - } func; - getSelection()->applyToNodes(&func); -} - -void LLSelectMgr::saveSelectedObjectTextures() -{ - // invalidate current selection so we update saved textures - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->mValid = FALSE; - return true; - } - } func; - getSelection()->applyToNodes(&func); - - // request object properties message to get updated permissions data - sendSelect(); -} - - -// This routine should be called whenever a drag is initiated. -// also need to know to which simulator to send update message -void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) -{ - if (mSelectedObjects->isEmpty()) - { - // nothing selected, so nothing to save - return; - } - - struct f : public LLSelectedNodeFunctor - { - EActionType mActionType; - f(EActionType a) : mActionType(a) {} - virtual bool apply(LLSelectNode* selectNode) - { - LLViewerObject* object = selectNode->getObject(); - if (!object) - { - return true; // skip - } - selectNode->mSavedPositionLocal = object->getPosition(); - if (object->isAttachment()) - { - if (object->isRootEdit()) - { - LLXform* parent_xform = object->mDrawable->getXform()->getParent(); - if (parent_xform) - { - selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - } - } - else - { - LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); - LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; - if (parent_xform) - { - LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); - LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); - selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - } - } - selectNode->mSavedRotation = object->getRenderRotation(); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - selectNode->mSavedRotation = object->getRotationRegion(); - } - - selectNode->mSavedScale = object->getScale(); - selectNode->saveTextureScaleRatios(); - return true; - } - } func(action_type); - getSelection()->applyToNodes(&func); - - mSavedSelectionBBox = getBBoxOfSelection(); -} - -struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor -{ - LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {} - U32 mFlags; - BOOL mState; - virtual bool apply(LLViewerObject* object) - { - if ( object->permModify() && // preemptive permissions check - object->isRoot() && // don't send for child objects - !object->isJointChild()) - { - object->setFlags( mFlags, mState); - } - return true; - } -}; - -void LLSelectMgr::selectionUpdatePhysics(BOOL physics) -{ - LLSelectMgrApplyFlags func( FLAGS_USE_PHYSICS, physics); - getSelection()->applyToObjects(&func); -} - -void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary) -{ - LLSelectMgrApplyFlags func( FLAGS_TEMPORARY_ON_REZ, is_temporary); - getSelection()->applyToObjects(&func); -} - -void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom) -{ - LLSelectMgrApplyFlags func( FLAGS_PHANTOM, is_phantom); - getSelection()->applyToObjects(&func); -} - -void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows) -{ - LLSelectMgrApplyFlags func( FLAGS_CAST_SHADOWS, cast_shadows); - getSelection()->applyToObjects(&func); -} - - -//---------------------------------------------------------------------- -// Helpful packing functions for sendObjectMessage() -//---------------------------------------------------------------------- - -// static -void LLSelectMgr::packAgentIDAndSessionAndAttachment( void *user_data) -{ - U8 *attachment_point = (U8*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addU8Fast(_PREHASH_AttachmentPoint, *attachment_point); -} - -// static -void LLSelectMgr::packAgentID( void *user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); -} - -// static -void LLSelectMgr::packAgentAndSessionID(void* user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -} - -// static -void LLSelectMgr::packAgentAndGroupID(void* user_data) -{ - LLOwnerData *data = (LLOwnerData *)user_data; - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, data->owner_id ); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id ); -} - -// static -void LLSelectMgr::packAgentAndSessionAndGroupID(void* user_data) -{ - LLUUID* group_idp = (LLUUID*) user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, *group_idp); -} - -// static -void LLSelectMgr::packDuplicateHeader(void* data) -{ - LLUUID group_id(gAgent.getGroupID()); - packAgentAndSessionAndGroupID(&group_id); - - LLDuplicateData* dup_data = (LLDuplicateData*) data; - - gMessageSystem->nextBlockFast(_PREHASH_SharedData); - gMessageSystem->addVector3Fast(_PREHASH_Offset, dup_data->offset); - gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, dup_data->flags); -} - -// static -void LLSelectMgr::packDeleteHeader(void* userdata) -{ - BOOL force = (BOOL)(intptr_t)userdata; - - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addBOOLFast(_PREHASH_Force, force); -} - -// static -void LLSelectMgr::packAgentGroupAndCatID(void* user_data) -{ - LLBuyData* buy = (LLBuyData*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - gMessageSystem->addUUIDFast(_PREHASH_CategoryID, buy->mCategoryID); -} - -//static -void LLSelectMgr::packDeRezHeader(void* user_data) -{ - LLDeRezInfo* info = (LLDeRezInfo*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - gMessageSystem->addU8Fast(_PREHASH_Destination, (U8)info->mDestination); - gMessageSystem->addUUIDFast(_PREHASH_DestinationID, info->mDestinationID); - LLUUID tid; - tid.generate(); - gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); - const U8 PACKET = 1; - gMessageSystem->addU8Fast(_PREHASH_PacketCount, PACKET); - gMessageSystem->addU8Fast(_PREHASH_PacketNumber, PACKET); -} - -// static -void LLSelectMgr::packObjectID(LLSelectNode* node, void *user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_ObjectID, node->getObject()->mID ); -} - -void LLSelectMgr::packObjectIDAndRotation(LLSelectNode* node, void *user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addQuatFast(_PREHASH_Rotation, node->getObject()->getRotation()); -} - -void LLSelectMgr::packObjectClickAction(LLSelectNode* node, void *user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addU8("ClickAction", node->getObject()->getClickAction()); -} - -void LLSelectMgr::packObjectIncludeInSearch(LLSelectNode* node, void *user_data) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addBOOL("IncludeInSearch", node->getObject()->getIncludeInSearch()); -} - -// static -void LLSelectMgr::packObjectLocalID(LLSelectNode* node, void *) -{ - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); -} - -// static -void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data) -{ - const std::string* name = (const std::string*)user_data; - if(!name->empty()) - { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - gMessageSystem->addStringFast(_PREHASH_Name, *name); - } - delete name; -} - -// static -void LLSelectMgr::packObjectDescription(LLSelectNode* node, void* user_data) -{ - const std::string* desc = (const std::string*)user_data; - if(!desc->empty()) - { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - gMessageSystem->addStringFast(_PREHASH_Description, *desc); - } -} - -// static -void LLSelectMgr::packObjectCategory(LLSelectNode* node, void* user_data) -{ - LLCategory* category = (LLCategory*)user_data; - if(!category) return; - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - category->packMessage(gMessageSystem); -} - -// static -void LLSelectMgr::packObjectSaleInfo(LLSelectNode* node, void* user_data) -{ - LLSaleInfo* sale_info = (LLSaleInfo*)user_data; - if(!sale_info) return; - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - sale_info->packMessage(gMessageSystem); -} - -// static -void LLSelectMgr::packPhysics(LLSelectNode* node, void *user_data) -{ -} - -// static -void LLSelectMgr::packShape(LLSelectNode* node, void *user_data) -{ -} - -// static -void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data) -{ - LLPermData *data = (LLPermData *)user_data; - - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); - - gMessageSystem->addU8Fast(_PREHASH_Field, data->mField); - gMessageSystem->addBOOLFast(_PREHASH_Set, data->mSet); - gMessageSystem->addU32Fast(_PREHASH_Mask, data->mMask); -} - -// Utility function to send some information to every region containing -// an object on the selection list. We want to do this to reduce the total -// number of packets sent by the viewer. -void LLSelectMgr::sendListToRegions(const std::string& message_name, - void (*pack_header)(void *user_data), - void (*pack_body)(LLSelectNode* node, void *user_data), - void *user_data, - ESendType send_type) -{ - LLSelectNode* node; - LLViewerRegion* last_region; - LLViewerRegion* current_region; - - S32 objects_sent = 0; - S32 packets_sent = 0; - S32 objects_in_this_packet = 0; - - //clear update override data (allow next update through) - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->mLastPositionLocal.setVec(0,0,0); - node->mLastRotation = LLQuaternion(); - node->mLastScale.setVec(0,0,0); - return true; - } - } func; - getSelection()->applyToNodes(&func); - - std::queue nodes_to_send; - - struct push_all : public LLSelectedNodeFunctor - { - std::queue& nodes_to_send; - push_all(std::queue& n) : nodes_to_send(n) {} - virtual bool apply(LLSelectNode* node) - { - if (node->getObject()) - { - nodes_to_send.push(node); - } - return true; - } - }; - struct push_some : public LLSelectedNodeFunctor - { - std::queue& nodes_to_send; - bool mRoots; - push_some(std::queue& n, bool roots) : nodes_to_send(n), mRoots(roots) {} - virtual bool apply(LLSelectNode* node) - { - if (node->getObject()) - { - BOOL is_root = node->getObject()->isRootEdit(); - if ((mRoots && is_root) || (!mRoots && !is_root)) - { - nodes_to_send.push(node); - } - } - return true; - } - }; - struct push_all pushall(nodes_to_send); - struct push_some pushroots(nodes_to_send, TRUE); - struct push_some pushnonroots(nodes_to_send, FALSE); - - switch(send_type) - { - case SEND_ONLY_ROOTS: - if(message_name == "ObjectBuy") - getSelection()->applyToRootNodes(&pushroots); - else - getSelection()->applyToRootNodes(&pushall); - - break; - case SEND_INDIVIDUALS: - getSelection()->applyToNodes(&pushall); - break; - case SEND_ROOTS_FIRST: - // first roots... - getSelection()->applyToNodes(&pushroots); - // then children... - getSelection()->applyToNodes(&pushnonroots); - break; - case SEND_CHILDREN_FIRST: - // first children... - getSelection()->applyToNodes(&pushnonroots); - // then roots... - getSelection()->applyToNodes(&pushroots); - break; - - default: - llerrs << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; - } - - // bail if nothing selected - if (nodes_to_send.empty()) - { - return; - } - - node = nodes_to_send.front(); - nodes_to_send.pop(); - - // cache last region information - current_region = node->getObject()->getRegion(); - - // Start duplicate message - // CRO: this isn't - gMessageSystem->newMessage(message_name.c_str()); - (*pack_header)(user_data); - - // For each object - while (node != NULL) - { - // remember the last region, look up the current one - last_region = current_region; - current_region = node->getObject()->getRegion(); - - // if to same simulator and message not too big - if ((current_region == last_region) - && (! gMessageSystem->isSendFull(NULL)) - && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) - { - // add another instance of the body of the data - (*pack_body)(node, user_data); - ++objects_sent; - ++objects_in_this_packet; - - // and on to the next object - if(nodes_to_send.empty()) - { - node = NULL; - } - else - { - node = nodes_to_send.front(); - nodes_to_send.pop(); - } - } - else - { - // otherwise send current message and start new one - gMessageSystem->sendReliable( last_region->getHost()); - packets_sent++; - objects_in_this_packet = 0; - - gMessageSystem->newMessage(message_name.c_str()); - (*pack_header)(user_data); - - // don't move to the next object, we still need to add the - // body data. - } - } - - // flush messages - if (gMessageSystem->getCurrentSendTotal() > 0) - { - gMessageSystem->sendReliable( current_region->getHost()); - packets_sent++; - } - else - { - gMessageSystem->clearMessage(); - } - - // llinfos << "sendListToRegions " << message_name << " obj " << objects_sent << " pkt " << packets_sent << llendl; -} - - -// -// Network communications -// - -void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object) -{ - // Remember that we asked the properties of this object. - sObjectPropertiesFamilyRequests.insert(object->mID); - //llinfos << "Registered an ObjectPropertiesFamily request for object " << object->mID << llendl; - - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_RequestFlags, 0x0 ); - msg->addUUIDFast(_PREHASH_ObjectID, object->mID ); - - LLViewerRegion* regionp = object->getRegion(); - msg->sendReliable( regionp->getHost() ); -} - - -// static -void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data) -{ - S32 i; - S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData); - for (i = 0; i < count; i++) - { - LLUUID id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i); - - LLUUID creator_id; - LLUUID owner_id; - LLUUID group_id; - LLUUID last_owner_id; - U64 creation_date; - LLUUID extra_id; - U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; - LLSaleInfo sale_info; - LLCategory category; - LLAggregatePermissions ag_perms; - LLAggregatePermissions ag_texture_perms; - LLAggregatePermissions ag_texture_perms_owner; - - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_CreatorID, creator_id, i); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, i); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id, i); - msg->getU64Fast(_PREHASH_ObjectData, _PREHASH_CreationDate, creation_date, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_GroupMask, group_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask, i); - sale_info.unpackMultiMessage(msg, _PREHASH_ObjectData, i); - - ag_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePerms, i); - ag_texture_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTextures, i); - ag_texture_perms_owner.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTexturesOwner, i); - category.unpackMultiMessage(msg, _PREHASH_ObjectData, i); - - S16 inv_serial = 0; - msg->getS16Fast(_PREHASH_ObjectData, _PREHASH_InventorySerial, inv_serial, i); - - LLUUID item_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ItemID, item_id, i); - LLUUID folder_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FolderID, folder_id, i); - LLUUID from_task_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FromTaskID, from_task_id, i); - - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i); - - std::string name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name, i); - std::string desc; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc, i); - - std::string touch_name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, touch_name, i); - std::string sit_name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i); - - //unpack TE IDs - std::vector texture_ids; - S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID); - if (size > 0) - { - S8 packed_buffer[SELECT_MAX_TES * UUID_BYTES]; - msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureID, packed_buffer, 0, i, SELECT_MAX_TES * UUID_BYTES); - - for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES) - { - LLUUID tid; - memcpy(tid.mData, packed_buffer + buf_offset, UUID_BYTES); /* Flawfinder: ignore */ - texture_ids.push_back(tid); - } - } - + { + if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) + { + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + F32 duration = 0.5f; + duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; + effectp->setDuration(duration); + } + } + + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + + // Keep track of how many objects have been deleted. + F64 obj_delete_count = LLViewerStats::getInstance()->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT); + obj_delete_count += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount(); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count ); + } + break; + case 1: + default: + break; + } + return false; +} + + +void LLSelectMgr::selectForceDelete() +{ + sendListToRegions( + "ObjectDelete", + packDeleteHeader, + packObjectLocalID, + (void*)TRUE, + SEND_ONLY_ROOTS); +} + +void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale, + BOOL &is_for_sale_mixed, + BOOL &is_sale_price_mixed, + S32 &total_sale_price, + S32 &individual_sale_price) +{ + num_for_sale = 0; + is_for_sale_mixed = FALSE; + is_sale_price_mixed = FALSE; + total_sale_price = 0; + individual_sale_price = 0; + + + // Empty set. + if (getSelection()->root_begin() == getSelection()->root_end()) + return; + + LLSelectNode *node = *(getSelection()->root_begin()); + const BOOL first_node_for_sale = node->mSaleInfo.isForSale(); + const S32 first_node_sale_price = node->mSaleInfo.getSalePrice(); + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + const BOOL node_for_sale = node->mSaleInfo.isForSale(); + const S32 node_sale_price = node->mSaleInfo.getSalePrice(); + + // Set mixed if the fields don't match the first node's fields. + if (node_for_sale != first_node_for_sale) + is_for_sale_mixed = TRUE; + if (node_sale_price != first_node_sale_price) + is_sale_price_mixed = TRUE; + + if (node_for_sale) + { + total_sale_price += node_sale_price; + num_for_sale ++; + } + } + + individual_sale_price = first_node_sale_price; + if (is_for_sale_mixed) + { + is_sale_price_mixed = TRUE; + individual_sale_price = 0; + } +} + +// returns TRUE if all nodes are valid. method also stores an +// accumulated sale info. +BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info) +{ + BOOL first = TRUE; + LLSaleInfo sale_info; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + sale_info = node->mSaleInfo; + first = FALSE; + } + else + { + sale_info.accumulate(node->mSaleInfo); + } + } + + result_sale_info = sale_info; + + return TRUE; +} + +BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm) +{ + BOOL first = TRUE; + LLAggregatePermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + perm = node->mAggregatePerm; + first = FALSE; + } + else + { + perm.aggregate(node->mAggregatePerm); + } + } + + result_perm = perm; + + return TRUE; +} + +BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& result_perm) +{ + BOOL first = TRUE; + LLAggregatePermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm; + if (first) + { + perm = t_perm; + first = FALSE; + } + else + { + perm.aggregate(t_perm); + } + } + + result_perm = perm; + + return TRUE; +} + + +//-------------------------------------------------------------------- +// Duplicate objects +//-------------------------------------------------------------------- + +// JC - If this doesn't work right, duplicate the selection list +// before doing anything, do a deselect, then send the duplicate +// messages. +struct LLDuplicateData +{ + LLVector3 offset; + U32 flags; +}; + +void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) +{ + if (mSelectedObjects->isAttachment()) + { + //RN: do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + LLDuplicateData data; + + data.offset = offset; + data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); + + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + + if (select_copy) + { + // the new copy will be coming in selected + deselectAll(); + } + else + { + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + node->mDuplicated = TRUE; + node->mDuplicatePos = node->getObject()->getPositionGlobal(); + node->mDuplicateRot = node->getObject()->getRotation(); + } + } +} + +void LLSelectMgr::repeatDuplicate() +{ + if (mSelectedObjects->isAttachment()) + { + //RN: do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + + std::vector non_duplicated_objects; + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mDuplicated) + { + non_duplicated_objects.push_back(node->getObject()); + } + } + + // make sure only previously duplicated objects are selected + for (std::vector::iterator iter = non_duplicated_objects.begin(); + iter != non_duplicated_objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + deselectObjectAndFamily(objectp); + } + + // duplicate objects in place + LLDuplicateData data; + + data.offset = LLVector3::zero; + data.flags = 0x0; + + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + + // move current selection based on delta from duplication position and update duplication position + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (node->mDuplicated) + { + LLQuaternion cur_rot = node->getObject()->getRotation(); + LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot); + LLQuaternion new_rot = cur_rot * rot_delta; + LLVector3d cur_pos = node->getObject()->getPositionGlobal(); + LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta); + + node->mDuplicatePos = node->getObject()->getPositionGlobal(); + node->mDuplicateRot = node->getObject()->getRotation(); + node->getObject()->setPositionGlobal(new_pos); + node->getObject()->setRotation(new_rot); + } + } + + sendMultipleUpdate(UPD_ROTATION | UPD_POSITION); +} + +// static +void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data ) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); +} + + +//-------------------------------------------------------------------- +// Duplicate On Ray +//-------------------------------------------------------------------- + +// Duplicates the selected objects, but places the copy along a cast +// ray. +struct LLDuplicateOnRayData +{ + LLVector3 mRayStartRegion; + LLVector3 mRayEndRegion; + BOOL mBypassRaycast; + BOOL mRayEndIsIntersection; + LLUUID mRayTargetID; + BOOL mCopyCenters; + BOOL mCopyRotates; + U32 mFlags; +}; + +void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, + const LLVector3 &ray_end_region, + BOOL bypass_raycast, + BOOL ray_end_is_intersection, + const LLUUID &ray_target_id, + BOOL copy_centers, + BOOL copy_rotates, + BOOL select_copy) +{ + if (mSelectedObjects->isAttachment()) + { + // do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + + LLDuplicateOnRayData data; + + data.mRayStartRegion = ray_start_region; + data.mRayEndRegion = ray_end_region; + data.mBypassRaycast = bypass_raycast; + data.mRayEndIsIntersection = ray_end_is_intersection; + data.mRayTargetID = ray_target_id; + data.mCopyCenters = copy_centers; + data.mCopyRotates = copy_rotates; + data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); + + sendListToRegions("ObjectDuplicateOnRay", + packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); + + if (select_copy) + { + // the new copy will be coming in selected + deselectAll(); + } +} + +// static +void LLSelectMgr::packDuplicateOnRayHead(void *user_data) +{ + LLMessageSystem *msg = gMessageSystem; + LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data; + + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); + msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion ); + msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion ); + msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast ); + msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection ); + msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters ); + msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates ); + msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID ); + msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags ); +} + + + +//------------------------------------------------------------------------ +// Object position, scale, rotation update, all-in-one +//------------------------------------------------------------------------ + +void LLSelectMgr::sendMultipleUpdate(U32 type) +{ + if (type == UPD_NONE) return; + // send individual updates when selecting textures or individual objects + ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST; + if (send_type == SEND_ONLY_ROOTS) + { + // tell simulator to apply to whole linked sets + type |= UPD_LINKED_SETS; + } + + sendListToRegions( + "MultipleObjectUpdate", + packAgentAndSessionID, + packMultipleUpdate, + &type, + send_type); +} + +// static +void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data) +{ + LLViewerObject* object = node->getObject(); + U32 *type32 = (U32 *)user_data; + U8 type = (U8)*type32; + U8 data[256]; + + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->addU8Fast(_PREHASH_Type, type ); + + S32 offset = 0; + + // JC: You MUST pack the data in this order. The receiving + // routine process_multiple_update_message on simulator will + // extract them in this order. + + if (type & UPD_POSITION) + { + htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); + offset += 12; + } + if (type & UPD_ROTATION) + { + LLQuaternion quat = object->getRotation(); + LLVector3 vec = quat.packToVector3(); + htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); + offset += 12; + } + if (type & UPD_SCALE) + { + //llinfos << "Sending object scale " << object->getScale() << llendl; + htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); + offset += 12; + } + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); +} + +//------------------------------------------------------------------------ +// Ownership +//------------------------------------------------------------------------ +struct LLOwnerData +{ + LLUUID owner_id; + LLUUID group_id; + BOOL override; +}; + +void LLSelectMgr::sendOwner(const LLUUID& owner_id, + const LLUUID& group_id, + BOOL override) +{ + LLOwnerData data; + + data.owner_id = owner_id; + data.group_id = group_id; + data.override = override; + + sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); +} + +// static +void LLSelectMgr::packOwnerHead(void *user_data) +{ + LLOwnerData *data = (LLOwnerData *)user_data; + + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gMessageSystem->nextBlockFast(_PREHASH_HeaderData); + gMessageSystem->addBOOLFast(_PREHASH_Override, data->override); + gMessageSystem->addUUIDFast(_PREHASH_OwnerID, data->owner_id); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id); +} + +//------------------------------------------------------------------------ +// Group +//------------------------------------------------------------------------ + +void LLSelectMgr::sendGroup(const LLUUID& group_id) +{ + LLUUID local_group_id(group_id); + sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS); +} + + +//------------------------------------------------------------------------ +// Buy +//------------------------------------------------------------------------ + +struct LLBuyData +{ + std::vector mObjectsSent; + LLUUID mCategoryID; + LLSaleInfo mSaleInfo; +}; + +// *NOTE: does not work for multiple object buy, which UI does not +// currently support sale info is used for verification only, if it +// doesn't match region info then sale is canceled Need to get sale +// info -as displayed in the UI- for every item. +void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info) +{ + LLBuyData buy; + buy.mCategoryID = category_id; + buy.mSaleInfo = sale_info; + sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS); +} + +// static +void LLSelectMgr::packBuyObjectIDs(LLSelectNode* node, void* data) +{ + LLBuyData* buy = (LLBuyData*)data; + + LLViewerObject* object = node->getObject(); + if (std::find(buy->mObjectsSent.begin(), buy->mObjectsSent.end(), object) == buy->mObjectsSent.end()) + { + buy->mObjectsSent.push_back(object); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->addU8Fast(_PREHASH_SaleType, buy->mSaleInfo.getSaleType()); + gMessageSystem->addS32Fast(_PREHASH_SalePrice, buy->mSaleInfo.getSalePrice()); + } +} + +//------------------------------------------------------------------------ +// Permissions +//------------------------------------------------------------------------ + +struct LLPermData +{ + U8 mField; + BOOL mSet; + U32 mMask; + BOOL mOverride; +}; + +// TODO: Make this able to fail elegantly. +void LLSelectMgr::selectionSetObjectPermissions(U8 field, + BOOL set, + U32 mask, + BOOL override) +{ + LLPermData data; + + data.mField = field; + data.mSet = set; + data.mMask = mask; + data.mOverride = override; + + sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS); +} + +void LLSelectMgr::packPermissionsHead(void* user_data) +{ + LLPermData* data = (LLPermData*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_HeaderData); + gMessageSystem->addBOOLFast(_PREHASH_Override, data->mOverride); +} + + +// Now that you've added a bunch of objects, send a select message +// on the entire list for efficiency. +/* +void LLSelectMgr::sendSelect() +{ + llerrs << "Not implemented" << llendl; +} +*/ + +void LLSelectMgr::deselectAll() +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + // Zap the angular velocity, as the sim will set it to zero + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setAngularVelocity( 0,0,0 ); + objectp->setVelocity( 0,0,0 ); + } + + sendListToRegions( + "ObjectDeselect", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_INDIVIDUALS); + + removeAll(); + + mLastSentSelectionCenterGlobal.clearVec(); + + updatePointAt(); +} + +void LLSelectMgr::deselectAllForStandingUp() +{ + /* + This function is similar deselectAll() except for the first if statement + which was removed. This is needed as a workaround for DEV-2854 + */ + + // Zap the angular velocity, as the sim will set it to zero + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setAngularVelocity( 0,0,0 ); + objectp->setVelocity( 0,0,0 ); + } + + sendListToRegions( + "ObjectDeselect", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_INDIVIDUALS); + + removeAll(); + + mLastSentSelectionCenterGlobal.clearVec(); + + updatePointAt(); +} + +void LLSelectMgr::deselectUnused() +{ + // no more outstanding references to this selection + if (mSelectedObjects->getNumRefs() == 1) + { + deselectAll(); + } +} + +void LLSelectMgr::convertTransient() +{ + LLObjectSelection::iterator node_it; + for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it) + { + LLSelectNode *nodep = *node_it; + nodep->setTransient(FALSE); + } +} + +void LLSelectMgr::deselectAllIfTooFar() +{ + if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD) + { + return; + } + + // HACK: Don't deselect when we're navigating to rate an object's + // owner or creator. JC + if (gPieObject->getVisible() || gPieRate->getVisible() ) + { + return; + } + + LLVector3d selectionCenter = getSelectionCenterGlobal(); + if (gSavedSettings.getBOOL("LimitSelectDistance") + && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) + && !mSelectedObjects->isAttachment() + && !selectionCenter.isExactlyZero()) + { + F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); + F32 deselect_dist_sq = deselect_dist * deselect_dist; + + LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; + F32 select_dist_sq = (F32) select_delta.magVecSquared(); + + if (select_dist_sq > deselect_dist_sq) + { + if (gDebugSelectMgr) + { + llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl; + llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl; + llinfos << "selection pos global = " << selectionCenter << llendl; + } + + deselectAll(); + } + } +} + + +void LLSelectMgr::selectionSetObjectName(const std::string& name) +{ + // we only work correctly if 1 object is selected. + if(mSelectedObjects->getRootObjectCount() == 1) + { + sendListToRegions("ObjectName", + packAgentAndSessionID, + packObjectName, + (void*)(new std::string(name)), + SEND_ONLY_ROOTS); + } + else if(mSelectedObjects->getObjectCount() == 1) + { + sendListToRegions("ObjectName", + packAgentAndSessionID, + packObjectName, + (void*)(new std::string(name)), + SEND_INDIVIDUALS); + } +} + +void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) +{ + // we only work correctly if 1 object is selected. + if(mSelectedObjects->getRootObjectCount() == 1) + { + sendListToRegions("ObjectDescription", + packAgentAndSessionID, + packObjectDescription, + (void*)(new std::string(desc)), + SEND_ONLY_ROOTS); + } + else if(mSelectedObjects->getObjectCount() == 1) + { + sendListToRegions("ObjectDescription", + packAgentAndSessionID, + packObjectDescription, + (void*)(new std::string(desc)), + SEND_INDIVIDUALS); + } +} + +void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) +{ + // for now, we only want to be able to set one root category at + // a time. + if(mSelectedObjects->getRootObjectCount() != 1) return; + sendListToRegions("ObjectCategory", + packAgentAndSessionID, + packObjectCategory, + (void*)(&category), + SEND_ONLY_ROOTS); +} + +void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) +{ + sendListToRegions("ObjectSaleInfo", + packAgentAndSessionID, + packObjectSaleInfo, + (void*)(&sale_info), + SEND_ONLY_ROOTS); +} + +//---------------------------------------------------------------------- +// Attachments +//---------------------------------------------------------------------- + +void LLSelectMgr::sendAttach(U8 attachment_point) +{ + LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject(); + + if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD) + { + return; + } + + BOOL build_mode = LLToolMgr::getInstance()->inEdit(); + // Special case: Attach to default location for this object. + if (0 == attachment_point || + get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) + { + sendListToRegions( + "ObjectAttach", + packAgentIDAndSessionAndAttachment, + packObjectIDAndRotation, + &attachment_point, + SEND_ONLY_ROOTS ); + if (!build_mode) + { + deselectAll(); + } + } +} + +void LLSelectMgr::sendDetach() +{ + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) + { + return; + } + + sendListToRegions( + "ObjectDetach", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_ONLY_ROOTS ); +} + + +void LLSelectMgr::sendDropAttachment() +{ + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) + { + return; + } + + sendListToRegions( + "ObjectDrop", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_ONLY_ROOTS); +} + +//---------------------------------------------------------------------- +// Links +//---------------------------------------------------------------------- + +void LLSelectMgr::sendLink() +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + sendListToRegions( + "ObjectLink", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_ONLY_ROOTS); +} + +void LLSelectMgr::sendDelink() +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + // Delink needs to send individuals so you can unlink a single object from + // a linked set. + sendListToRegions( + "ObjectDelink", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_INDIVIDUALS); +} + + +//---------------------------------------------------------------------- +// Hinges +//---------------------------------------------------------------------- + +/* +void LLSelectMgr::sendHinge(U8 type) +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + sendListToRegions( + "ObjectHinge", + packHingeHead, + packObjectLocalID, + &type, + SEND_ONLY_ROOTS); +} + + +void LLSelectMgr::sendDehinge() +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + sendListToRegions( + "ObjectDehinge", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_ONLY_ROOTS); +}*/ + +void LLSelectMgr::sendSelect() +{ + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + sendListToRegions( + "ObjectSelect", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_INDIVIDUALS); +} + +// static +void LLSelectMgr::packHingeHead(void *user_data) +{ + U8 *type = (U8 *)user_data; + + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gMessageSystem->nextBlockFast(_PREHASH_JointType); + gMessageSystem->addU8Fast(_PREHASH_Type, *type ); +} + + +void LLSelectMgr::selectionDump() +{ + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + object->dump(); + return true; + } + } func; + getSelection()->applyToObjects(&func); +} + +void LLSelectMgr::saveSelectedObjectColors() +{ + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->saveColors(); + return true; + } + } func; + getSelection()->applyToNodes(&func); +} + +void LLSelectMgr::saveSelectedObjectTextures() +{ + // invalidate current selection so we update saved textures + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->mValid = FALSE; + return true; + } + } func; + getSelection()->applyToNodes(&func); + + // request object properties message to get updated permissions data + sendSelect(); +} + + +// This routine should be called whenever a drag is initiated. +// also need to know to which simulator to send update message +void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) +{ + if (mSelectedObjects->isEmpty()) + { + // nothing selected, so nothing to save + return; + } + + struct f : public LLSelectedNodeFunctor + { + EActionType mActionType; + f(EActionType a) : mActionType(a) {} + virtual bool apply(LLSelectNode* selectNode) + { + LLViewerObject* object = selectNode->getObject(); + if (!object) + { + return true; // skip + } + selectNode->mSavedPositionLocal = object->getPosition(); + if (object->isAttachment()) + { + if (object->isRootEdit()) + { + LLXform* parent_xform = object->mDrawable->getXform()->getParent(); + if (parent_xform) + { + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + } + } + else + { + LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); + LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; + if (parent_xform) + { + LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); + LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + } + } + selectNode->mSavedRotation = object->getRenderRotation(); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + selectNode->mSavedRotation = object->getRotationRegion(); + } + + selectNode->mSavedScale = object->getScale(); + selectNode->saveTextureScaleRatios(); + return true; + } + } func(action_type); + getSelection()->applyToNodes(&func); + + mSavedSelectionBBox = getBBoxOfSelection(); +} + +struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor +{ + LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {} + U32 mFlags; + BOOL mState; + virtual bool apply(LLViewerObject* object) + { + if ( object->permModify() && // preemptive permissions check + object->isRoot() && // don't send for child objects + !object->isJointChild()) + { + object->setFlags( mFlags, mState); + } + return true; + } +}; + +void LLSelectMgr::selectionUpdatePhysics(BOOL physics) +{ + LLSelectMgrApplyFlags func( FLAGS_USE_PHYSICS, physics); + getSelection()->applyToObjects(&func); +} + +void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary) +{ + LLSelectMgrApplyFlags func( FLAGS_TEMPORARY_ON_REZ, is_temporary); + getSelection()->applyToObjects(&func); +} + +void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom) +{ + LLSelectMgrApplyFlags func( FLAGS_PHANTOM, is_phantom); + getSelection()->applyToObjects(&func); +} + +void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows) +{ + LLSelectMgrApplyFlags func( FLAGS_CAST_SHADOWS, cast_shadows); + getSelection()->applyToObjects(&func); +} + + +//---------------------------------------------------------------------- +// Helpful packing functions for sendObjectMessage() +//---------------------------------------------------------------------- + +// static +void LLSelectMgr::packAgentIDAndSessionAndAttachment( void *user_data) +{ + U8 *attachment_point = (U8*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addU8Fast(_PREHASH_AttachmentPoint, *attachment_point); +} + +// static +void LLSelectMgr::packAgentID( void *user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); +} + +// static +void LLSelectMgr::packAgentAndSessionID(void* user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +} + +// static +void LLSelectMgr::packAgentAndGroupID(void* user_data) +{ + LLOwnerData *data = (LLOwnerData *)user_data; + + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, data->owner_id ); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id ); +} + +// static +void LLSelectMgr::packAgentAndSessionAndGroupID(void* user_data) +{ + LLUUID* group_idp = (LLUUID*) user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, *group_idp); +} + +// static +void LLSelectMgr::packDuplicateHeader(void* data) +{ + LLUUID group_id(gAgent.getGroupID()); + packAgentAndSessionAndGroupID(&group_id); + + LLDuplicateData* dup_data = (LLDuplicateData*) data; + + gMessageSystem->nextBlockFast(_PREHASH_SharedData); + gMessageSystem->addVector3Fast(_PREHASH_Offset, dup_data->offset); + gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, dup_data->flags); +} + +// static +void LLSelectMgr::packDeleteHeader(void* userdata) +{ + BOOL force = (BOOL)(intptr_t)userdata; + + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addBOOLFast(_PREHASH_Force, force); +} + +// static +void LLSelectMgr::packAgentGroupAndCatID(void* user_data) +{ + LLBuyData* buy = (LLBuyData*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->addUUIDFast(_PREHASH_CategoryID, buy->mCategoryID); +} + +//static +void LLSelectMgr::packDeRezHeader(void* user_data) +{ + LLDeRezInfo* info = (LLDeRezInfo*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->addU8Fast(_PREHASH_Destination, (U8)info->mDestination); + gMessageSystem->addUUIDFast(_PREHASH_DestinationID, info->mDestinationID); + LLUUID tid; + tid.generate(); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); + const U8 PACKET = 1; + gMessageSystem->addU8Fast(_PREHASH_PacketCount, PACKET); + gMessageSystem->addU8Fast(_PREHASH_PacketNumber, PACKET); +} + +// static +void LLSelectMgr::packObjectID(LLSelectNode* node, void *user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_ObjectID, node->getObject()->mID ); +} + +void LLSelectMgr::packObjectIDAndRotation(LLSelectNode* node, void *user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addQuatFast(_PREHASH_Rotation, node->getObject()->getRotation()); +} + +void LLSelectMgr::packObjectClickAction(LLSelectNode* node, void *user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addU8("ClickAction", node->getObject()->getClickAction()); +} + +void LLSelectMgr::packObjectIncludeInSearch(LLSelectNode* node, void *user_data) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addBOOL("IncludeInSearch", node->getObject()->getIncludeInSearch()); +} + +// static +void LLSelectMgr::packObjectLocalID(LLSelectNode* node, void *) +{ + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); +} + +// static +void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data) +{ + const std::string* name = (const std::string*)user_data; + if(!name->empty()) + { + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Name, *name); + } + delete name; +} + +// static +void LLSelectMgr::packObjectDescription(LLSelectNode* node, void* user_data) +{ + const std::string* desc = (const std::string*)user_data; + if(!desc->empty()) + { + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Description, *desc); + } +} + +// static +void LLSelectMgr::packObjectCategory(LLSelectNode* node, void* user_data) +{ + LLCategory* category = (LLCategory*)user_data; + if(!category) return; + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + category->packMessage(gMessageSystem); +} + +// static +void LLSelectMgr::packObjectSaleInfo(LLSelectNode* node, void* user_data) +{ + LLSaleInfo* sale_info = (LLSaleInfo*)user_data; + if(!sale_info) return; + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + sale_info->packMessage(gMessageSystem); +} + +// static +void LLSelectMgr::packPhysics(LLSelectNode* node, void *user_data) +{ +} + +// static +void LLSelectMgr::packShape(LLSelectNode* node, void *user_data) +{ +} + +// static +void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data) +{ + LLPermData *data = (LLPermData *)user_data; + + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); + + gMessageSystem->addU8Fast(_PREHASH_Field, data->mField); + gMessageSystem->addBOOLFast(_PREHASH_Set, data->mSet); + gMessageSystem->addU32Fast(_PREHASH_Mask, data->mMask); +} + +// Utility function to send some information to every region containing +// an object on the selection list. We want to do this to reduce the total +// number of packets sent by the viewer. +void LLSelectMgr::sendListToRegions(const std::string& message_name, + void (*pack_header)(void *user_data), + void (*pack_body)(LLSelectNode* node, void *user_data), + void *user_data, + ESendType send_type) +{ + LLSelectNode* node; + LLViewerRegion* last_region; + LLViewerRegion* current_region; + + S32 objects_sent = 0; + S32 packets_sent = 0; + S32 objects_in_this_packet = 0; + + //clear update override data (allow next update through) + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->mLastPositionLocal.setVec(0,0,0); + node->mLastRotation = LLQuaternion(); + node->mLastScale.setVec(0,0,0); + return true; + } + } func; + getSelection()->applyToNodes(&func); + + std::queue nodes_to_send; + + struct push_all : public LLSelectedNodeFunctor + { + std::queue& nodes_to_send; + push_all(std::queue& n) : nodes_to_send(n) {} + virtual bool apply(LLSelectNode* node) + { + if (node->getObject()) + { + nodes_to_send.push(node); + } + return true; + } + }; + struct push_some : public LLSelectedNodeFunctor + { + std::queue& nodes_to_send; + bool mRoots; + push_some(std::queue& n, bool roots) : nodes_to_send(n), mRoots(roots) {} + virtual bool apply(LLSelectNode* node) + { + if (node->getObject()) + { + BOOL is_root = node->getObject()->isRootEdit(); + if ((mRoots && is_root) || (!mRoots && !is_root)) + { + nodes_to_send.push(node); + } + } + return true; + } + }; + struct push_all pushall(nodes_to_send); + struct push_some pushroots(nodes_to_send, TRUE); + struct push_some pushnonroots(nodes_to_send, FALSE); + + switch(send_type) + { + case SEND_ONLY_ROOTS: + if(message_name == "ObjectBuy") + getSelection()->applyToRootNodes(&pushroots); + else + getSelection()->applyToRootNodes(&pushall); + + break; + case SEND_INDIVIDUALS: + getSelection()->applyToNodes(&pushall); + break; + case SEND_ROOTS_FIRST: + // first roots... + getSelection()->applyToNodes(&pushroots); + // then children... + getSelection()->applyToNodes(&pushnonroots); + break; + case SEND_CHILDREN_FIRST: + // first children... + getSelection()->applyToNodes(&pushnonroots); + // then roots... + getSelection()->applyToNodes(&pushroots); + break; + + default: + llerrs << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; + } + + // bail if nothing selected + if (nodes_to_send.empty()) + { + return; + } + + node = nodes_to_send.front(); + nodes_to_send.pop(); + + // cache last region information + current_region = node->getObject()->getRegion(); + + // Start duplicate message + // CRO: this isn't + gMessageSystem->newMessage(message_name.c_str()); + (*pack_header)(user_data); + + // For each object + while (node != NULL) + { + // remember the last region, look up the current one + last_region = current_region; + current_region = node->getObject()->getRegion(); + + // if to same simulator and message not too big + if ((current_region == last_region) + && (! gMessageSystem->isSendFull(NULL)) + && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) + { + // add another instance of the body of the data + (*pack_body)(node, user_data); + ++objects_sent; + ++objects_in_this_packet; + + // and on to the next object + if(nodes_to_send.empty()) + { + node = NULL; + } + else + { + node = nodes_to_send.front(); + nodes_to_send.pop(); + } + } + else + { + // otherwise send current message and start new one + gMessageSystem->sendReliable( last_region->getHost()); + packets_sent++; + objects_in_this_packet = 0; + + gMessageSystem->newMessage(message_name.c_str()); + (*pack_header)(user_data); + + // don't move to the next object, we still need to add the + // body data. + } + } + + // flush messages + if (gMessageSystem->getCurrentSendTotal() > 0) + { + gMessageSystem->sendReliable( current_region->getHost()); + packets_sent++; + } + else + { + gMessageSystem->clearMessage(); + } + + // llinfos << "sendListToRegions " << message_name << " obj " << objects_sent << " pkt " << packets_sent << llendl; +} + + +// +// Network communications +// + +void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object) +{ + // Remember that we asked the properties of this object. + sObjectPropertiesFamilyRequests.insert(object->mID); + //llinfos << "Registered an ObjectPropertiesFamily request for object " << object->mID << llendl; + + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_RequestFlags, 0x0 ); + msg->addUUIDFast(_PREHASH_ObjectID, object->mID ); + + LLViewerRegion* regionp = object->getRegion(); + msg->sendReliable( regionp->getHost() ); +} + + +// static +void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data) +{ + S32 i; + S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData); + for (i = 0; i < count; i++) + { + LLUUID id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i); + + LLUUID creator_id; + LLUUID owner_id; + LLUUID group_id; + LLUUID last_owner_id; + U64 creation_date; + LLUUID extra_id; + U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; + LLSaleInfo sale_info; + LLCategory category; + LLAggregatePermissions ag_perms; + LLAggregatePermissions ag_texture_perms; + LLAggregatePermissions ag_texture_perms_owner; + + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_CreatorID, creator_id, i); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, i); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id, i); + msg->getU64Fast(_PREHASH_ObjectData, _PREHASH_CreationDate, creation_date, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_GroupMask, group_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask, i); + sale_info.unpackMultiMessage(msg, _PREHASH_ObjectData, i); + + ag_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePerms, i); + ag_texture_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTextures, i); + ag_texture_perms_owner.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTexturesOwner, i); + category.unpackMultiMessage(msg, _PREHASH_ObjectData, i); + + S16 inv_serial = 0; + msg->getS16Fast(_PREHASH_ObjectData, _PREHASH_InventorySerial, inv_serial, i); + + LLUUID item_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ItemID, item_id, i); + LLUUID folder_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FolderID, folder_id, i); + LLUUID from_task_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FromTaskID, from_task_id, i); + + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i); + + std::string name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name, i); + std::string desc; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc, i); + + std::string touch_name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, touch_name, i); + std::string sit_name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i); + + //unpack TE IDs + std::vector texture_ids; + S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID); + if (size > 0) + { + S8 packed_buffer[SELECT_MAX_TES * UUID_BYTES]; + msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureID, packed_buffer, 0, i, SELECT_MAX_TES * UUID_BYTES); + + for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES) + { + LLUUID tid; + memcpy(tid.mData, packed_buffer + buf_offset, UUID_BYTES); /* Flawfinder: ignore */ + texture_ids.push_back(tid); + } + } + // Send to export floaters LLFloaterExport::receiveObjectProperties(id, name, desc); - // - - // Iterate through nodes at end, since it can be on both the regular AND hover list - struct f : public LLSelectedNodeFunctor - { - LLUUID mID; - f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mID == mID); - } - } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); - - if (node) - { - if (node->mInventorySerial != inv_serial) - { - node->getObject()->dirtyInventory(); - } - - // save texture data as soon as we get texture perms first time - if (!node->mValid) - { - BOOL can_copy = FALSE; - BOOL can_transfer = FALSE; - - LLAggregatePermissions::EValue value = LLAggregatePermissions::AP_NONE; - if(node->getObject()->permYouOwner()) - { - value = ag_texture_perms_owner.getValue(PERM_COPY); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_copy = TRUE; - } - value = ag_texture_perms_owner.getValue(PERM_TRANSFER); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_transfer = TRUE; - } - } - else - { - value = ag_texture_perms.getValue(PERM_COPY); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_copy = TRUE; - } - value = ag_texture_perms.getValue(PERM_TRANSFER); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_transfer = TRUE; - } - } - - if (can_copy && can_transfer) - { - // this should be the only place that saved textures is called - node->saveTextures(texture_ids); - } - } - - node->mValid = TRUE; - node->mPermissions->init(creator_id, owner_id, - last_owner_id, group_id); - node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); - node->mCreationDate = creation_date; - node->mItemID = item_id; - node->mFolderID = folder_id; - node->mFromTaskID = from_task_id; - node->mName.assign(name); - node->mDescription.assign(desc); - node->mSaleInfo = sale_info; - node->mAggregatePerm = ag_perms; - node->mAggregateTexturePerm = ag_texture_perms; - node->mAggregateTexturePermOwner = ag_texture_perms_owner; - node->mCategory = category; - node->mInventorySerial = inv_serial; - node->mSitName.assign(sit_name); - node->mTouchName.assign(touch_name); - } - } - - dialog_refresh_all(); - - // silly hack to allow 'save into inventory' - if(gPopupMenuView->getVisible()) - { - gPopupMenuView->setItemEnabled(SAVE_INTO_INVENTORY, - enable_save_into_inventory(NULL)); - } - - // hack for left-click buy object - LLToolPie::selectionPropertiesReceived(); -} - -// static -void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data) -{ - LLUUID id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id); - if (sObjectPropertiesFamilyRequests.count(id) == 0) - { - // This reply is not for us. - return; - } - // We got the reply, so remove the object from the list of pending requests - sObjectPropertiesFamilyRequests.erase(id); - //llinfos << "Got ObjectPropertiesFamily reply for object " << id << llendl; - - U32 request_flags; - LLUUID creator_id; - LLUUID owner_id; - LLUUID group_id; - LLUUID extra_id; - U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; - LLSaleInfo sale_info; - LLCategory category; - - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags, request_flags ); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id ); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask ); - msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask, group_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask); - sale_info.unpackMessage(msg, _PREHASH_ObjectData); - category.unpackMessage(msg, _PREHASH_ObjectData); - - LLUUID last_owner_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id ); - - // unpack name & desc - std::string name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); - - std::string desc; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc); - + // + + // Iterate through nodes at end, since it can be on both the regular AND hover list + struct f : public LLSelectedNodeFunctor + { + LLUUID mID; + f(const LLUUID& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mID == mID); + } + } func(id); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); + + if (node) + { + if (node->mInventorySerial != inv_serial) + { + node->getObject()->dirtyInventory(); + } + + // save texture data as soon as we get texture perms first time + if (!node->mValid) + { + BOOL can_copy = FALSE; + BOOL can_transfer = FALSE; + + LLAggregatePermissions::EValue value = LLAggregatePermissions::AP_NONE; + if(node->getObject()->permYouOwner()) + { + value = ag_texture_perms_owner.getValue(PERM_COPY); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_copy = TRUE; + } + value = ag_texture_perms_owner.getValue(PERM_TRANSFER); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_transfer = TRUE; + } + } + else + { + value = ag_texture_perms.getValue(PERM_COPY); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_copy = TRUE; + } + value = ag_texture_perms.getValue(PERM_TRANSFER); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_transfer = TRUE; + } + } + + if (can_copy && can_transfer) + { + // this should be the only place that saved textures is called + node->saveTextures(texture_ids); + } + } + + node->mValid = TRUE; + node->mPermissions->init(creator_id, owner_id, + last_owner_id, group_id); + node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); + node->mCreationDate = creation_date; + node->mItemID = item_id; + node->mFolderID = folder_id; + node->mFromTaskID = from_task_id; + node->mName.assign(name); + node->mDescription.assign(desc); + node->mSaleInfo = sale_info; + node->mAggregatePerm = ag_perms; + node->mAggregateTexturePerm = ag_texture_perms; + node->mAggregateTexturePermOwner = ag_texture_perms_owner; + node->mCategory = category; + node->mInventorySerial = inv_serial; + node->mSitName.assign(sit_name); + node->mTouchName.assign(touch_name); + } + } + + dialog_refresh_all(); + + // silly hack to allow 'save into inventory' + if(gPopupMenuView->getVisible()) + { + gPopupMenuView->setItemEnabled(SAVE_INTO_INVENTORY, + enable_save_into_inventory(NULL)); + } + + // hack for left-click buy object + LLToolPie::selectionPropertiesReceived(); +} + +// static +void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data) +{ + LLUUID id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id); + if (sObjectPropertiesFamilyRequests.count(id) == 0) + { + // This reply is not for us. + return; + } + // We got the reply, so remove the object from the list of pending requests + sObjectPropertiesFamilyRequests.erase(id); + //llinfos << "Got ObjectPropertiesFamily reply for object " << id << llendl; + + U32 request_flags; + LLUUID creator_id; + LLUUID owner_id; + LLUUID group_id; + LLUUID extra_id; + U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; + LLSaleInfo sale_info; + LLCategory category; + + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags, request_flags ); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id ); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask ); + msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask, group_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask); + sale_info.unpackMessage(msg, _PREHASH_ObjectData); + category.unpackMessage(msg, _PREHASH_ObjectData); + + LLUUID last_owner_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id ); + + // unpack name & desc + std::string name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); + + std::string desc; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc); + // Send to export floaters LLFloaterExport::receiveObjectProperties(id, name, desc); // - // the reporter widget askes the server for info about picked objects - if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST)) - { - EReportType report_type = (COMPLAINT_REPORT_REQUEST & request_flags) ? COMPLAINT_REPORT : BUG_REPORT; - LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type); - if (reporterp) - { - std::string fullname; - gCacheName->getFullName(owner_id, fullname); - reporterp->setPickedObjectProperties(name, fullname, owner_id); - } - } - else if (request_flags & OBJECT_PAY_REQUEST) - { - // check if the owner of the paid object is muted - LLMuteList::getInstance()->autoRemove(owner_id, LLMuteList::AR_MONEY); - } - - // Now look through all of the hovered nodes - struct f : public LLSelectedNodeFunctor - { - LLUUID mID; - f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mID == mID); - } - } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func); - - if (node) - { - node->mValid = TRUE; - node->mPermissions->init(LLUUID::null, owner_id, - last_owner_id, group_id); - node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); - node->mSaleInfo = sale_info; - node->mCategory = category; - node->mName.assign(name); - node->mDescription.assign(desc); - } - - dialog_refresh_all(); -} - - -// static -void LLSelectMgr::processForceObjectSelect(LLMessageSystem* msg, void**) -{ - BOOL reset_list; - msg->getBOOL("Header", "ResetList", reset_list); - - if (reset_list) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - LLUUID full_id; - S32 local_id; - LLViewerObject* object; - std::vector objects; - S32 i; - S32 block_count = msg->getNumberOfBlocks("Data"); - - for (i = 0; i < block_count; i++) - { - msg->getS32("Data", "LocalID", local_id, i); - - gObjectList.getUUIDFromLocal(full_id, - local_id, - msg->getSenderIP(), - msg->getSenderPort()); - object = gObjectList.findObject(full_id); - if (object) - { - objects.push_back(object); - } - } - - // Don't select, just highlight - LLSelectMgr::getInstance()->highlightObjectAndFamily(objects); -} - - -extern LLGLdouble gGLModelView[16]; - -void LLSelectMgr::updateSilhouettes() -{ - S32 num_sils_genned = 0; - - LLVector3d cameraPos = gAgent.getCameraPositionGlobal(); - F32 currentCameraZoom = gAgent.getCurrentCameraBuildOffset(); - - if (!mSilhouetteImagep) - { - mSilhouetteImagep = gImageList.getImageFromFile("silhouette.j2c", TRUE, TRUE); - } - - mHighlightedObjects->cleanupNodes(); - - if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - object->setChanged(LLXform::SILHOUETTE); - return true; - } - } func; - getSelection()->applyToObjects(&func); - - mLastCameraPos = gAgent.getCameraPositionGlobal(); - } - - std::vector changed_objects; - - updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects); - if (mRectSelectedObjects.size() > 0) - { - //gGLSPipelineSelection.set(); - - //mSilhouetteImagep->bindTexture(); - //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); - - std::set roots; - - // sync mHighlightedObjects with mRectSelectedObjects since the latter is rebuilt every frame and former - // persists from frame to frame to avoid regenerating object silhouettes - // mHighlightedObjects includes all siblings of rect selected objects - - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - - // generate list of roots from current object selection - for (std::set >::iterator iter = mRectSelectedObjects.begin(); - iter != mRectSelectedObjects.end(); iter++) - { - LLViewerObject *objectp = *iter; - if (select_linked_set) - { - LLViewerObject *rootp = (LLViewerObject*)objectp->getRoot(); - roots.insert(rootp); - } - else - { - roots.insert(objectp); - } - } - - // remove highlight nodes not in roots list - std::vector remove_these_nodes; - std::vector remove_these_roots; - - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - if (objectp->isRoot() || !select_linked_set) - { - if (roots.count(objectp) == 0) - { - remove_these_nodes.push_back(node); - } - else - { - remove_these_roots.push_back(objectp); - } - } - else - { - LLViewerObject* rootp = (LLViewerObject*)objectp->getRoot(); - - if (roots.count(rootp) == 0) - { - remove_these_nodes.push_back(node); - } - } - } - - // remove all highlight nodes no longer in rectangle selection - for (std::vector::iterator iter = remove_these_nodes.begin(); - iter != remove_these_nodes.end(); ++iter) - { - LLSelectNode* nodep = *iter; - mHighlightedObjects->removeNode(nodep); - } - - // remove all root objects already being highlighted - for (std::vector::iterator iter = remove_these_roots.begin(); - iter != remove_these_roots.end(); ++iter) - { - LLViewerObject* objectp = *iter; - roots.erase(objectp); - } - - // add all new objects in rectangle selection - for (std::set::iterator iter = roots.begin(); - iter != roots.end(); iter++) - { - LLViewerObject* objectp = *iter; - if (!canSelectObject(objectp)) - { - continue; - } - - LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE); - rect_select_root_node->selectAllTEs(TRUE); - - if (!select_linked_set) - { - rect_select_root_node->mIndividualSelection = TRUE; - } - else - { - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child_objectp = *iter; - - if (!canSelectObject(child_objectp)) - { - continue; - } - - LLSelectNode* rect_select_node = new LLSelectNode(child_objectp, TRUE); - rect_select_node->selectAllTEs(TRUE); - mHighlightedObjects->addNodeAtEnd(rect_select_node); - } - } - - // Add the root last, to preserve order for link operations. - mHighlightedObjects->addNodeAtEnd(rect_select_root_node); - } - - num_sils_genned = 0; - - // render silhouettes for highlighted objects - //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - - // do roots first, then children so that root flags are cleared ASAP - BOOL roots_only = (pass == 0); - BOOL is_root = objectp->isRootEdit(); - if (roots_only != is_root) - { - continue; - } - - if (!node->mSilhouetteExists - || objectp->isChanged(LLXform::SILHOUETTE) - || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) - { - if (num_sils_genned++ < MAX_SILS_PER_FRAME) - { - generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); - changed_objects.push_back(objectp); - } - else if (objectp->isAttachment() && objectp->getRootEdit()->mDrawable.notNull()) - { - //RN: hack for orthogonal projection of HUD attachments - LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); - if (attachment_pt && attachment_pt->getIsHUDAttachment()) - { - LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); - generateSilhouette(node, camera_pos); - } - } - } - //LLColor4 highlight_color; - // - //if (subtracting_from_selection) - //{ - // node->renderOneSilhouette(LLColor4::red); - //} - //else if (!objectp->isSelected()) - //{ - // highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; - // node->renderOneSilhouette(highlight_color); - //} - } - } - //mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D); - } - else - { - mHighlightedObjects->deleteAllNodes(); - } - - for (std::vector::iterator iter = changed_objects.begin(); - iter != changed_objects.end(); ++iter) - { - // clear flags after traversing node list (as child objects need to refer to parent flags, etc) - LLViewerObject* objectp = *iter; - objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE); - } - - //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); -} - -void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector& changed_objects) -{ - if (object_handle->getNumNodes()) - { - //gGLSPipelineSelection.set(); - - //mSilhouetteImagep->bindTexture(); - //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); - - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = object_handle->begin(); - iter != object_handle->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - // do roots first, then children so that root flags are cleared ASAP - BOOL roots_only = (pass == 0); - BOOL is_root = (objectp->isRootEdit()); - if (roots_only != is_root || objectp->mDrawable.isNull()) - { - continue; - } - - if (!node->mSilhouetteExists - || objectp->isChanged(LLXform::SILHOUETTE) - || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) - { - if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible()) - { - generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); - changed_objects.push_back(objectp); - } - else if (objectp->isAttachment()) - { - //RN: hack for orthogonal projection of HUD attachments - LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); - if (attachment_pt && attachment_pt->getIsHUDAttachment()) - { - LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); - generateSilhouette(node, camera_pos); - } - } - } - } - } - } -} -void LLSelectMgr::renderSilhouettes(BOOL for_hud) -{ - if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights) - { - return; - } - - gGL.getTexUnit(0)->bind(mSilhouetteImagep.get()); - LLGLSPipelineSelection gls_select; - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - LLGLEnable blend(GL_BLEND); - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if (for_hud && avatar) - { - LLBBox hud_bbox = avatar->getHUDBBox(); - - F32 cur_zoom = gAgent.mHUDCurZoom; - - // set up transform to encompass bounding box of HUD - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame - glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); - glScalef(cur_zoom, cur_zoom, cur_zoom); - } - if (mSelectedObjects->getNumNodes()) - { + // the reporter widget askes the server for info about picked objects + if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST)) + { + EReportType report_type = (COMPLAINT_REPORT_REQUEST & request_flags) ? COMPLAINT_REPORT : BUG_REPORT; + LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type); + if (reporterp) + { + std::string fullname; + gCacheName->getFullName(owner_id, fullname); + reporterp->setPickedObjectProperties(name, fullname, owner_id); + } + } + else if (request_flags & OBJECT_PAY_REQUEST) + { + // check if the owner of the paid object is muted + LLMuteList::getInstance()->autoRemove(owner_id, LLMuteList::AR_MONEY); + } + + // Now look through all of the hovered nodes + struct f : public LLSelectedNodeFunctor + { + LLUUID mID; + f(const LLUUID& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mID == mID); + } + } func(id); + LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func); + + if (node) + { + node->mValid = TRUE; + node->mPermissions->init(LLUUID::null, owner_id, + last_owner_id, group_id); + node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); + node->mSaleInfo = sale_info; + node->mCategory = category; + node->mName.assign(name); + node->mDescription.assign(desc); + } + + dialog_refresh_all(); +} + + +// static +void LLSelectMgr::processForceObjectSelect(LLMessageSystem* msg, void**) +{ + BOOL reset_list; + msg->getBOOL("Header", "ResetList", reset_list); + + if (reset_list) + { + LLSelectMgr::getInstance()->deselectAll(); + } + + LLUUID full_id; + S32 local_id; + LLViewerObject* object; + std::vector objects; + S32 i; + S32 block_count = msg->getNumberOfBlocks("Data"); + + for (i = 0; i < block_count; i++) + { + msg->getS32("Data", "LocalID", local_id, i); + + gObjectList.getUUIDFromLocal(full_id, + local_id, + msg->getSenderIP(), + msg->getSenderPort()); + object = gObjectList.findObject(full_id); + if (object) + { + objects.push_back(object); + } + } + + // Don't select, just highlight + LLSelectMgr::getInstance()->highlightObjectAndFamily(objects); +} + + +extern LLGLdouble gGLModelView[16]; + +void LLSelectMgr::updateSilhouettes() +{ + S32 num_sils_genned = 0; + + LLVector3d cameraPos = gAgent.getCameraPositionGlobal(); + F32 currentCameraZoom = gAgent.getCurrentCameraBuildOffset(); + + if (!mSilhouetteImagep) + { + mSilhouetteImagep = gImageList.getImageFromFile("silhouette.j2c", TRUE, TRUE); + } + + mHighlightedObjects->cleanupNodes(); + + if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + object->setChanged(LLXform::SILHOUETTE); + return true; + } + } func; + getSelection()->applyToObjects(&func); + + mLastCameraPos = gAgent.getCameraPositionGlobal(); + } + + std::vector changed_objects; + + updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects); + if (mRectSelectedObjects.size() > 0) + { + //gGLSPipelineSelection.set(); + + //mSilhouetteImagep->bindTexture(); + //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); + + std::set roots; + + // sync mHighlightedObjects with mRectSelectedObjects since the latter is rebuilt every frame and former + // persists from frame to frame to avoid regenerating object silhouettes + // mHighlightedObjects includes all siblings of rect selected objects + + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + + // generate list of roots from current object selection + for (std::set >::iterator iter = mRectSelectedObjects.begin(); + iter != mRectSelectedObjects.end(); iter++) + { + LLViewerObject *objectp = *iter; + if (select_linked_set) + { + LLViewerObject *rootp = (LLViewerObject*)objectp->getRoot(); + roots.insert(rootp); + } + else + { + roots.insert(objectp); + } + } + + // remove highlight nodes not in roots list + std::vector remove_these_nodes; + std::vector remove_these_roots; + + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + if (objectp->isRoot() || !select_linked_set) + { + if (roots.count(objectp) == 0) + { + remove_these_nodes.push_back(node); + } + else + { + remove_these_roots.push_back(objectp); + } + } + else + { + LLViewerObject* rootp = (LLViewerObject*)objectp->getRoot(); + + if (roots.count(rootp) == 0) + { + remove_these_nodes.push_back(node); + } + } + } + + // remove all highlight nodes no longer in rectangle selection + for (std::vector::iterator iter = remove_these_nodes.begin(); + iter != remove_these_nodes.end(); ++iter) + { + LLSelectNode* nodep = *iter; + mHighlightedObjects->removeNode(nodep); + } + + // remove all root objects already being highlighted + for (std::vector::iterator iter = remove_these_roots.begin(); + iter != remove_these_roots.end(); ++iter) + { + LLViewerObject* objectp = *iter; + roots.erase(objectp); + } + + // add all new objects in rectangle selection + for (std::set::iterator iter = roots.begin(); + iter != roots.end(); iter++) + { + LLViewerObject* objectp = *iter; + if (!canSelectObject(objectp)) + { + continue; + } + + LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE); + rect_select_root_node->selectAllTEs(TRUE); + + if (!select_linked_set) + { + rect_select_root_node->mIndividualSelection = TRUE; + } + else + { + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child_objectp = *iter; + + if (!canSelectObject(child_objectp)) + { + continue; + } + + LLSelectNode* rect_select_node = new LLSelectNode(child_objectp, TRUE); + rect_select_node->selectAllTEs(TRUE); + mHighlightedObjects->addNodeAtEnd(rect_select_node); + } + } + + // Add the root last, to preserve order for link operations. + mHighlightedObjects->addNodeAtEnd(rect_select_root_node); + } + + num_sils_genned = 0; + + // render silhouettes for highlighted objects + //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + + // do roots first, then children so that root flags are cleared ASAP + BOOL roots_only = (pass == 0); + BOOL is_root = objectp->isRootEdit(); + if (roots_only != is_root) + { + continue; + } + + if (!node->mSilhouetteExists + || objectp->isChanged(LLXform::SILHOUETTE) + || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) + { + if (num_sils_genned++ < MAX_SILS_PER_FRAME) + { + generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); + changed_objects.push_back(objectp); + } + else if (objectp->isAttachment() && objectp->getRootEdit()->mDrawable.notNull()) + { + //RN: hack for orthogonal projection of HUD attachments + LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); + if (attachment_pt && attachment_pt->getIsHUDAttachment()) + { + LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); + generateSilhouette(node, camera_pos); + } + } + } + //LLColor4 highlight_color; + // + //if (subtracting_from_selection) + //{ + // node->renderOneSilhouette(LLColor4::red); + //} + //else if (!objectp->isSelected()) + //{ + // highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; + // node->renderOneSilhouette(highlight_color); + //} + } + } + //mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D); + } + else + { + mHighlightedObjects->deleteAllNodes(); + } + + for (std::vector::iterator iter = changed_objects.begin(); + iter != changed_objects.end(); ++iter) + { + // clear flags after traversing node list (as child objects need to refer to parent flags, etc) + LLViewerObject* objectp = *iter; + objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE); + } + + //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector& changed_objects) +{ + if (object_handle->getNumNodes()) + { + //gGLSPipelineSelection.set(); + + //mSilhouetteImagep->bindTexture(); + //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); + + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = object_handle->begin(); + iter != object_handle->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + // do roots first, then children so that root flags are cleared ASAP + BOOL roots_only = (pass == 0); + BOOL is_root = (objectp->isRootEdit()); + if (roots_only != is_root || objectp->mDrawable.isNull()) + { + continue; + } + + if (!node->mSilhouetteExists + || objectp->isChanged(LLXform::SILHOUETTE) + || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) + { + if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible()) + { + generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); + changed_objects.push_back(objectp); + } + else if (objectp->isAttachment()) + { + //RN: hack for orthogonal projection of HUD attachments + LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); + if (attachment_pt && attachment_pt->getIsHUDAttachment()) + { + LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); + generateSilhouette(node, camera_pos); + } + } + } + } + } + } +} +void LLSelectMgr::renderSilhouettes(BOOL for_hud) +{ + if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights) + { + return; + } + + gGL.getTexUnit(0)->bind(mSilhouetteImagep.get()); + LLGLSPipelineSelection gls_select; + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); + LLGLEnable blend(GL_BLEND); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + + LLVOAvatar* avatar = gAgent.getAvatarObject(); + if (for_hud && avatar) + { + LLBBox hud_bbox = avatar->getHUDBBox(); + + F32 cur_zoom = gAgent.mHUDCurZoom; + + // set up transform to encompass bounding box of HUD + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame + glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); + glScalef(cur_zoom, cur_zoom, cur_zoom); + } + if (mSelectedObjects->getNumNodes()) + { LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID(); // //for (S32 pass = 0; pass < 2; pass++) //{ // - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - if (objectp->isHUDAttachment() != for_hud) - { - continue; - } - if(objectp->getID() == inspect_item_id) - { - node->renderOneSilhouette(sHighlightInspectColor); - } - else if (node->isTransient()) - { - BOOL oldHidden = LLSelectMgr::sRenderHiddenSelections; - LLSelectMgr::sRenderHiddenSelections = FALSE; - node->renderOneSilhouette(sContextSilhouetteColor); - LLSelectMgr::sRenderHiddenSelections = oldHidden; - } - else if (objectp->isRootEdit()) - { - node->renderOneSilhouette(sSilhouetteParentColor); - } - else - { - node->renderOneSilhouette(sSilhouetteChildColor); - } + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + if (objectp->isHUDAttachment() != for_hud) + { + continue; + } + if(objectp->getID() == inspect_item_id) + { + node->renderOneSilhouette(sHighlightInspectColor); + } + else if (node->isTransient()) + { + BOOL oldHidden = LLSelectMgr::sRenderHiddenSelections; + LLSelectMgr::sRenderHiddenSelections = FALSE; + node->renderOneSilhouette(sContextSilhouetteColor); + LLSelectMgr::sRenderHiddenSelections = oldHidden; + } + else if (objectp->isRootEdit()) + { + node->renderOneSilhouette(sSilhouetteParentColor); + } + else + { + node->renderOneSilhouette(sSilhouetteChildColor); + } } // //} // - } - - if (mHighlightedObjects->getNumNodes()) - { - // render silhouettes for highlighted objects - BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - if (objectp->isHUDAttachment() != for_hud) - { - continue; - } - - if (subtracting_from_selection) - { - node->renderOneSilhouette(LLColor4::red); - } - else if (!objectp->isSelected()) - { - LLColor4 highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; - node->renderOneSilhouette(highlight_color); - } - } - } - } - - if (for_hud && avatar) - { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - stop_glerror(); - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); -} - -void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) -{ - LLViewerObject* objectp = nodep->getObject(); - - if (objectp && objectp->getPCode() == LL_PCODE_VOLUME) - { - ((LLVOVolume*)objectp)->generateSilhouette(nodep, view_point); - } -} - -// -// Utility classes -// -LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow) -: mObject(object), - mIndividualSelection(FALSE), - mTransient(FALSE), - mValid(FALSE), - mPermissions(new LLPermissions()), - mInventorySerial(0), - mSilhouetteExists(FALSE), - mDuplicated(FALSE), - mTESelectMask(0), - mLastTESelected(0), - mName(LLStringUtil::null), - mDescription(LLStringUtil::null), - mTouchName(LLStringUtil::null), - mSitName(LLStringUtil::null), - mCreationDate(0) -{ - selectAllTEs(FALSE); - saveColors(); -} - -LLSelectNode::LLSelectNode(const LLSelectNode& nodep) -{ - mTESelectMask = nodep.mTESelectMask; - mLastTESelected = nodep.mLastTESelected; - - mIndividualSelection = nodep.mIndividualSelection; - - mValid = nodep.mValid; - mTransient = nodep.mTransient; - mPermissions = new LLPermissions(*nodep.mPermissions); - mSaleInfo = nodep.mSaleInfo;; - mAggregatePerm = nodep.mAggregatePerm; - mAggregateTexturePerm = nodep.mAggregateTexturePerm; - mAggregateTexturePermOwner = nodep.mAggregateTexturePermOwner; - mName = nodep.mName; - mDescription = nodep.mDescription; - mCategory = nodep.mCategory; - mSavedPositionLocal = nodep.mSavedPositionLocal; - mSavedPositionGlobal = nodep.mSavedPositionGlobal; - mSavedScale = nodep.mSavedScale; - mSavedRotation = nodep.mSavedRotation; - mDuplicated = nodep.mDuplicated; - mDuplicatePos = nodep.mDuplicatePos; - mDuplicateRot = nodep.mDuplicateRot; - mItemID = nodep.mItemID; - mFolderID = nodep.mFolderID; - mFromTaskID = nodep.mFromTaskID; - mTouchName = nodep.mTouchName; - mSitName = nodep.mSitName; - mCreationDate = nodep.mCreationDate; - - mSilhouetteVertices = nodep.mSilhouetteVertices; - mSilhouetteNormals = nodep.mSilhouetteNormals; - mSilhouetteSegments = nodep.mSilhouetteSegments; - mSilhouetteExists = nodep.mSilhouetteExists; - mObject = nodep.mObject; - - std::vector::const_iterator color_iter; - mSavedColors.clear(); - for (color_iter = nodep.mSavedColors.begin(); color_iter != nodep.mSavedColors.end(); ++color_iter) - { - mSavedColors.push_back(*color_iter); - } - - saveTextures(nodep.mSavedTextures); -} - -LLSelectNode::~LLSelectNode() -{ - delete mPermissions; - mPermissions = NULL; -} - -void LLSelectNode::selectAllTEs(BOOL b) -{ - mTESelectMask = b ? 0xFFFFFFFF : 0x0; - mLastTESelected = 0; -} - -void LLSelectNode::selectTE(S32 te_index, BOOL selected) -{ - if (te_index < 0 || te_index >= SELECT_MAX_TES) - { - return; - } - if (selected) - { - mTESelectMask |= (0x1 << te_index); - } - else - { - mTESelectMask &= ~(0x1 << te_index); - } - mLastTESelected = te_index; -} - -BOOL LLSelectNode::isTESelected(S32 te_index) -{ - if (te_index < 0 || te_index >= mObject->getNumTEs()) - { - return FALSE; - } - return (mTESelectMask & (0x1 << te_index)) != 0; -} - -S32 LLSelectNode::getLastSelectedTE() -{ - if (!isTESelected(mLastTESelected)) - { - return -1; - } - return mLastTESelected; -} - -LLViewerObject* LLSelectNode::getObject() -{ - if (!mObject) - { - return NULL; - } - else if (mObject->isDead()) - { - mObject = NULL; - } - return mObject; -} - -void LLSelectNode::setObject(LLViewerObject* object) -{ - mObject = object; -} - -void LLSelectNode::saveColors() -{ - if (mObject.notNull()) - { - mSavedColors.clear(); - for (S32 i = 0; i < mObject->getNumTEs(); i++) - { - const LLTextureEntry* tep = mObject->getTE(i); - mSavedColors.push_back(tep->getColor()); - } - } -} - -void LLSelectNode::saveTextures(const std::vector& textures) -{ - if (mObject.notNull()) - { - mSavedTextures.clear(); - - for (std::vector::const_iterator texture_it = textures.begin(); - texture_it != textures.end(); ++texture_it) - { - mSavedTextures.push_back(*texture_it); - } - } -} - -void LLSelectNode::saveTextureScaleRatios() -{ - mTextureScaleRatios.clear(); - if (mObject.notNull()) - { - for (U8 i = 0; i < mObject->getNumTEs(); i++) - { - F32 s,t; - const LLTextureEntry* tep = mObject->getTE(i); - tep->getScale(&s,&t); - U32 s_axis = 0; - U32 t_axis = 0; - - LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); - - LLVector3 v; - LLVector3 scale = mObject->getScale(); - - if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) - { - v.mV[s_axis] = s*scale.mV[s_axis]; - v.mV[t_axis] = t*scale.mV[t_axis]; - } - else - { - v.mV[s_axis] = s/scale.mV[s_axis]; - v.mV[t_axis] = t/scale.mV[t_axis]; - } - - mTextureScaleRatios.push_back(v); - } - } -} - - -// This implementation should be similar to LLTask::allowOperationOnTask -BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const -{ - // Extract ownership. - BOOL object_is_group_owned = FALSE; - LLUUID object_owner_id; - mPermissions->getOwnership(object_owner_id, object_is_group_owned); - - // Operations on invalid or public objects is not allowed. - if (!mObject || (mObject->isDead()) || !mPermissions->isOwned()) - { - return FALSE; - } - - // The transfer permissions can never be given through proxy. - if (PERM_TRANSFER == op) - { - // The owner of an agent-owned object can transfer to themselves. - if ( !object_is_group_owned - && (gAgent.getID() == object_owner_id) ) - { - return TRUE; - } - else - { - // Otherwise check aggregate permissions. - return mObject->permTransfer(); - } - } - - if (PERM_MOVE == op - || PERM_MODIFY == op) - { - // only owners can move or modify their attachments - // no proxy allowed. - if (mObject->isAttachment() && object_owner_id != gAgent.getID()) - { - return FALSE; - } - } - - // Calculate proxy_agent_id and group_id to use for permissions checks. - // proxy_agent_id may be set to the object owner through group powers. - // group_id can only be set to the object's group, if the agent is in that group. - LLUUID group_id = LLUUID::null; - LLUUID proxy_agent_id = gAgent.getID(); - - // Gods can always operate. - if (gAgent.isGodlike()) - { - return TRUE; - } - - // Check if the agent is in the same group as the object. - LLUUID object_group_id = mPermissions->getGroup(); - if (object_group_id.notNull() && - gAgent.isInGroup(object_group_id)) - { - // Assume the object's group during this operation. - group_id = object_group_id; - } - - // Only allow proxy powers for PERM_COPY if the actual agent can - // receive the item (ie has PERM_TRANSFER permissions). - // NOTE: op == PERM_TRANSFER has already been handled, but if - // that ever changes we need to BLOCK proxy powers for PERM_TRANSFER. DK 03/28/06 - if (PERM_COPY != op || mPermissions->allowTransferTo(gAgent.getID())) - { - // Check if the agent can assume ownership through group proxy or agent-granted proxy. - if ( ( object_is_group_owned - && gAgent.hasPowerInGroup(object_owner_id, group_proxy_power)) - // Only allow proxy for move, modify, and copy. - || ( (PERM_MOVE == op || PERM_MODIFY == op || PERM_COPY == op) - && (!object_is_group_owned - && gAgent.isGrantedProxy(*mPermissions)))) - { - // This agent is able to assume the ownership role for this operation. - proxy_agent_id = object_owner_id; - } - } - - // We now have max ownership information. - if (PERM_OWNER == op) - { - // This this was just a check for ownership, we can now return the answer. - return (proxy_agent_id == object_owner_id ? TRUE : FALSE); - } - - // check permissions to see if the agent can operate - return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); -} - -//----------------------------------------------------------------------------- -// renderOneSilhouette() -//----------------------------------------------------------------------------- -void LLSelectNode::renderOneSilhouette(const LLColor4 &color) -{ - LLViewerObject* objectp = getObject(); - if (!objectp) - { - return; - } - - LLDrawable* drawable = objectp->mDrawable; - if(!drawable) - { - return; - } - - if (!mSilhouetteExists) - { - return; - } - - BOOL is_hud_object = objectp->isHUDAttachment(); - - if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) - { - return; - } - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - if (!is_hud_object) - { - glLoadIdentity(); - glMultMatrixd(gGLModelView); - } - - - if (drawable->isActive()) - { - glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix); - } - - LLVolume *volume = objectp->getVolume(); - if (volume) - { - F32 silhouette_thickness; - if (is_hud_object && gAgent.getAvatarObject()) - { - silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.mHUDCurZoom; - } - else - { - LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition(); - silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()); - } - F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); - - F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); - F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f); - F32 u_divisor = 1.f / ((F32)(mSilhouetteVertices.size() - 1)); - - if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) - { - gGL.flush(); - gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); - LLGLEnable fog(GL_FOG); - glFogi(GL_FOG_MODE, GL_LINEAR); - float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec(); - LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0); - glFogf(GL_FOG_START, d); - glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); - glFogfv(GL_FOG_COLOR, fogCol.mV); - - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.begin(LLRender::LINES); - { - S32 i = 0; - for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) - { - for(; i < mSilhouetteSegments[seg_num]; i++) - { - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - } - } - } - gGL.end(); - u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); - } - - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.begin(LLRender::TRIANGLES); - { - S32 i = 0; - for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) - { - S32 first_i = i; - LLVector3 v; - LLVector2 t; - - for(; i < mSilhouetteSegments[seg_num]; i++) - { - - if (i == first_i) { - LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; - vert += mSilhouetteVertices[i]; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); - gGL.vertex3fv( vert.mV ); - - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - - v = mSilhouetteVertices[i]; - t = LLVector2(u_coord, v_coord); - } - else { - LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; - vert += mSilhouetteVertices[i]; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); - gGL.vertex3fv( vert.mV ); - gGL.vertex3fv( vert.mV ); - - gGL.texCoord2fv(t.mV); - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); - gGL.vertex3fv(v.mV); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - - } - } - } - } - gGL.end(); - gGL.flush(); - } - glPopMatrix(); -} - -// -// Utility Functions -// - -// Update everyone who cares about the selection list -void dialog_refresh_all() -{ - if (gNoRender) - { - return; - } - - //could refresh selected object info in toolbar here - - gFloaterTools->dirty(); - - if( gPieObject->getVisible() ) - { - gPieObject->arrange(); - } - - if( gPieAttachment->getVisible() ) - { - gPieAttachment->arrange(); - } - - LLFloaterProperties::dirtyAll(); - LLFloaterInspect::dirty(); -} - -S32 get_family_count(LLViewerObject *parent) -{ - if (!parent) - { - llwarns << "Trying to get_family_count on null parent!" << llendl; - } - S32 count = 1; // for this object - LLViewerObject::const_child_list_t& child_list = parent->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - - if (!child) - { - llwarns << "Family object has NULL child! Show Doug." << llendl; - } - else if (child->isDead()) - { - llwarns << "Family object has dead child object. Show Doug." << llendl; - } - else - { - if (LLSelectMgr::getInstance()->canSelectObject(child)) - { - count += get_family_count( child ); - } - } - } - return count; -} - -//----------------------------------------------------------------------------- -// updateSelectionCenter -//----------------------------------------------------------------------------- -void LLSelectMgr::updateSelectionCenter() -{ - const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection - // center (tractor beam) - - //override any object updates received - //for selected objects - overrideObjectUpdates(); - - LLViewerObject* object = mSelectedObjects->getFirstObject(); - if (!object) - { - // nothing selected, probably grabbing - // Ignore by setting to avatar origin. - mSelectionCenterGlobal.clearVec(); - mShowSelection = FALSE; - mSelectionBBox = LLBBox(); - mPauseRequest = NULL; - resetAgentHUDZoom(); - - } - else - { - mSelectedObjects->mSelectType = getSelectTypeForObject(object); - - if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) - { - mPauseRequest = gAgent.getAvatarObject()->requestPause(); - } - else - { - mPauseRequest = NULL; - } - - if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject()) - { - // reset hud ZOOM - gAgent.mHUDTargetZoom = 1.f; - gAgent.mHUDCurZoom = 1.f; - } - - mShowSelection = FALSE; - LLBBox bbox; - - // have stuff selected - LLVector3d select_center; - // keep a list of jointed objects for showing the joint HUDEffects - - // Initialize the bounding box to the root prim, so the BBox orientation - // matches the root prim's (affecting the orientation of the manipulators). - bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() ); - - std::vector < LLViewerObject *> jointed_objects; - - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if (!object) - continue; - LLViewerObject *myAvatar = gAgent.getAvatarObject(); - LLViewerObject *root = object->getRootEdit(); - if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment - !root->isChild(myAvatar) && // not the object you're sitting on - !object->isAvatar()) // not another avatar - { - mShowSelection = TRUE; - } - - bbox.addBBoxAgent( object->getBoundingBoxAgent() ); - - if (object->isJointChild()) - { - jointed_objects.push_back(object); - } - } - - LLVector3 bbox_center_agent = bbox.getCenterAgent(); - mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); - mSelectionBBox = bbox; - - } - - if ( !(gAgentID == LLUUID::null)) - { - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (mShowSelection) - { - LLVector3d select_center_global; - - if( tool->isEditing() ) - { - select_center_global = tool->getEditingPointGlobal(); - } - else - { - select_center_global = mSelectionCenterGlobal; - } - - // Send selection center if moved beyond threshold (used to animate tractor beam) - LLVector3d diff; - diff = select_center_global - mLastSentSelectionCenterGlobal; - - if ( diff.magVecSquared() > MOVE_SELECTION_THRESHOLD*MOVE_SELECTION_THRESHOLD ) - { - // Transmit updated selection center - mLastSentSelectionCenterGlobal = select_center_global; - } - } - } - - // give up edit menu if no objects selected - if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0) - { - gEditMenuHandler = NULL; - } -} - -void LLSelectMgr::updatePointAt() -{ - if (mShowSelection) - { - if (mSelectedObjects->getObjectCount()) - { - LLVector3 select_offset; - const LLPickInfo& pick = gViewerWindow->getLastPick(); - LLViewerObject *click_object = pick.getObject(); - if (click_object && click_object->isSelected()) - { - // clicked on another object in our selection group, use that as target - select_offset.setVec(pick.mObjectOffset); - select_offset.rotVec(~click_object->getRenderRotation()); - - gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset); - gAgent.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset); - } - else - { - // didn't click on an object this time, revert to pointing at center of first object - gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); - gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); - } - } - else - { - gAgent.setPointAt(POINTAT_TARGET_CLEAR); - gAgent.setLookAt(LOOKAT_TARGET_CLEAR); - } - } - else - { - gAgent.setPointAt(POINTAT_TARGET_CLEAR); - gAgent.setLookAt(LOOKAT_TARGET_CLEAR); - } -} - -//----------------------------------------------------------------------------- -// getBBoxOfSelection() -//----------------------------------------------------------------------------- -LLBBox LLSelectMgr::getBBoxOfSelection() const -{ - return mSelectionBBox; -} - - -//----------------------------------------------------------------------------- -// canUndo() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::canUndo() const -{ - return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG -} - -//----------------------------------------------------------------------------- -// undo() -//----------------------------------------------------------------------------- -void LLSelectMgr::undo() -{ - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); -} - -//----------------------------------------------------------------------------- -// canRedo() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::canRedo() const -{ - return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG -} - -//----------------------------------------------------------------------------- -// redo() -//----------------------------------------------------------------------------- -void LLSelectMgr::redo() -{ - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); -} - -//----------------------------------------------------------------------------- -// canDoDelete() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::canDoDelete() const -{ - // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) - return const_cast(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG -} - -//----------------------------------------------------------------------------- -// doDelete() -//----------------------------------------------------------------------------- -void LLSelectMgr::doDelete() -{ - selectDelete(); -} - -//----------------------------------------------------------------------------- -// canDeselect() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::canDeselect() const -{ - return !mSelectedObjects->isEmpty(); -} - -//----------------------------------------------------------------------------- -// deselect() -//----------------------------------------------------------------------------- -void LLSelectMgr::deselect() -{ - deselectAll(); -} -//----------------------------------------------------------------------------- -// canDuplicate() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::canDuplicate() const -{ - return const_cast(this)->mSelectedObjects->getFirstCopyableObject() != NULL; // HACK: casting away constness - MG -} -//----------------------------------------------------------------------------- -// duplicate() -//----------------------------------------------------------------------------- -void LLSelectMgr::duplicate() -{ - LLVector3 offset(0.5f, 0.5f, 0.f); - selectDuplicate(offset, TRUE); -} - -ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object) -{ - if (!object) - { - return SELECT_TYPE_WORLD; - } - if (object->isHUDAttachment()) - { - return SELECT_TYPE_HUD; - } - else if (object->isAttachment()) - { - return SELECT_TYPE_ATTACHMENT; - } - else - { - return SELECT_TYPE_WORLD; - } -} - -void LLSelectMgr::validateSelection() -{ - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (!LLSelectMgr::getInstance()->canSelectObject(object)) - { - LLSelectMgr::getInstance()->deselectObjectOnly(object); - } - return true; - } - } func; - getSelection()->applyToObjects(&func); -} - -BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) -{ - // Never select dead objects - if (!object || object->isDead()) - { - return FALSE; - } - - if (mForceSelection) - { - return TRUE; - } - - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove())) - { - // only select my own objects - return FALSE; - } - - // Can't select orphans - if (object->isOrphaned()) return FALSE; - - // Can't select avatars - if (object->isAvatar()) return FALSE; - - // Can't select land - if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE; - + } + + if (mHighlightedObjects->getNumNodes()) + { + // render silhouettes for highlighted objects + BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + if (objectp->isHUDAttachment() != for_hud) + { + continue; + } + + if (subtracting_from_selection) + { + node->renderOneSilhouette(LLColor4::red); + } + else if (!objectp->isSelected()) + { + LLColor4 highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; + node->renderOneSilhouette(highlight_color); + } + } + } + } + + if (for_hud && avatar) + { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + stop_glerror(); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) +{ + LLViewerObject* objectp = nodep->getObject(); + + if (objectp && objectp->getPCode() == LL_PCODE_VOLUME) + { + ((LLVOVolume*)objectp)->generateSilhouette(nodep, view_point); + } +} + +// +// Utility classes +// +LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow) +: mObject(object), + mIndividualSelection(FALSE), + mTransient(FALSE), + mValid(FALSE), + mPermissions(new LLPermissions()), + mInventorySerial(0), + mSilhouetteExists(FALSE), + mDuplicated(FALSE), + mTESelectMask(0), + mLastTESelected(0), + mName(LLStringUtil::null), + mDescription(LLStringUtil::null), + mTouchName(LLStringUtil::null), + mSitName(LLStringUtil::null), + mCreationDate(0) +{ + selectAllTEs(FALSE); + saveColors(); +} + +LLSelectNode::LLSelectNode(const LLSelectNode& nodep) +{ + mTESelectMask = nodep.mTESelectMask; + mLastTESelected = nodep.mLastTESelected; + + mIndividualSelection = nodep.mIndividualSelection; + + mValid = nodep.mValid; + mTransient = nodep.mTransient; + mPermissions = new LLPermissions(*nodep.mPermissions); + mSaleInfo = nodep.mSaleInfo;; + mAggregatePerm = nodep.mAggregatePerm; + mAggregateTexturePerm = nodep.mAggregateTexturePerm; + mAggregateTexturePermOwner = nodep.mAggregateTexturePermOwner; + mName = nodep.mName; + mDescription = nodep.mDescription; + mCategory = nodep.mCategory; + mSavedPositionLocal = nodep.mSavedPositionLocal; + mSavedPositionGlobal = nodep.mSavedPositionGlobal; + mSavedScale = nodep.mSavedScale; + mSavedRotation = nodep.mSavedRotation; + mDuplicated = nodep.mDuplicated; + mDuplicatePos = nodep.mDuplicatePos; + mDuplicateRot = nodep.mDuplicateRot; + mItemID = nodep.mItemID; + mFolderID = nodep.mFolderID; + mFromTaskID = nodep.mFromTaskID; + mTouchName = nodep.mTouchName; + mSitName = nodep.mSitName; + mCreationDate = nodep.mCreationDate; + + mSilhouetteVertices = nodep.mSilhouetteVertices; + mSilhouetteNormals = nodep.mSilhouetteNormals; + mSilhouetteSegments = nodep.mSilhouetteSegments; + mSilhouetteExists = nodep.mSilhouetteExists; + mObject = nodep.mObject; + + std::vector::const_iterator color_iter; + mSavedColors.clear(); + for (color_iter = nodep.mSavedColors.begin(); color_iter != nodep.mSavedColors.end(); ++color_iter) + { + mSavedColors.push_back(*color_iter); + } + + saveTextures(nodep.mSavedTextures); +} + +LLSelectNode::~LLSelectNode() +{ + delete mPermissions; + mPermissions = NULL; +} + +void LLSelectNode::selectAllTEs(BOOL b) +{ + mTESelectMask = b ? 0xFFFFFFFF : 0x0; + mLastTESelected = 0; +} + +void LLSelectNode::selectTE(S32 te_index, BOOL selected) +{ + if (te_index < 0 || te_index >= SELECT_MAX_TES) + { + return; + } + if (selected) + { + mTESelectMask |= (0x1 << te_index); + } + else + { + mTESelectMask &= ~(0x1 << te_index); + } + mLastTESelected = te_index; +} + +BOOL LLSelectNode::isTESelected(S32 te_index) +{ + if (te_index < 0 || te_index >= mObject->getNumTEs()) + { + return FALSE; + } + return (mTESelectMask & (0x1 << te_index)) != 0; +} + +S32 LLSelectNode::getLastSelectedTE() +{ + if (!isTESelected(mLastTESelected)) + { + return -1; + } + return mLastTESelected; +} + +LLViewerObject* LLSelectNode::getObject() +{ + if (!mObject) + { + return NULL; + } + else if (mObject->isDead()) + { + mObject = NULL; + } + return mObject; +} + +void LLSelectNode::setObject(LLViewerObject* object) +{ + mObject = object; +} + +void LLSelectNode::saveColors() +{ + if (mObject.notNull()) + { + mSavedColors.clear(); + for (S32 i = 0; i < mObject->getNumTEs(); i++) + { + const LLTextureEntry* tep = mObject->getTE(i); + mSavedColors.push_back(tep->getColor()); + } + } +} + +void LLSelectNode::saveTextures(const std::vector& textures) +{ + if (mObject.notNull()) + { + mSavedTextures.clear(); + + for (std::vector::const_iterator texture_it = textures.begin(); + texture_it != textures.end(); ++texture_it) + { + mSavedTextures.push_back(*texture_it); + } + } +} + +void LLSelectNode::saveTextureScaleRatios() +{ + mTextureScaleRatios.clear(); + if (mObject.notNull()) + { + for (U8 i = 0; i < mObject->getNumTEs(); i++) + { + F32 s,t; + const LLTextureEntry* tep = mObject->getTE(i); + tep->getScale(&s,&t); + U32 s_axis = 0; + U32 t_axis = 0; + + LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); + + LLVector3 v; + LLVector3 scale = mObject->getScale(); + + if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) + { + v.mV[s_axis] = s*scale.mV[s_axis]; + v.mV[t_axis] = t*scale.mV[t_axis]; + } + else + { + v.mV[s_axis] = s/scale.mV[s_axis]; + v.mV[t_axis] = t/scale.mV[t_axis]; + } + + mTextureScaleRatios.push_back(v); + } + } +} + + +// This implementation should be similar to LLTask::allowOperationOnTask +BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const +{ + // Extract ownership. + BOOL object_is_group_owned = FALSE; + LLUUID object_owner_id; + mPermissions->getOwnership(object_owner_id, object_is_group_owned); + + // Operations on invalid or public objects is not allowed. + if (!mObject || (mObject->isDead()) || !mPermissions->isOwned()) + { + return FALSE; + } + + // The transfer permissions can never be given through proxy. + if (PERM_TRANSFER == op) + { + // The owner of an agent-owned object can transfer to themselves. + if ( !object_is_group_owned + && (gAgent.getID() == object_owner_id) ) + { + return TRUE; + } + else + { + // Otherwise check aggregate permissions. + return mObject->permTransfer(); + } + } + + if (PERM_MOVE == op + || PERM_MODIFY == op) + { + // only owners can move or modify their attachments + // no proxy allowed. + if (mObject->isAttachment() && object_owner_id != gAgent.getID()) + { + return FALSE; + } + } + + // Calculate proxy_agent_id and group_id to use for permissions checks. + // proxy_agent_id may be set to the object owner through group powers. + // group_id can only be set to the object's group, if the agent is in that group. + LLUUID group_id = LLUUID::null; + LLUUID proxy_agent_id = gAgent.getID(); + + // Gods can always operate. + if (gAgent.isGodlike()) + { + return TRUE; + } + + // Check if the agent is in the same group as the object. + LLUUID object_group_id = mPermissions->getGroup(); + if (object_group_id.notNull() && + gAgent.isInGroup(object_group_id)) + { + // Assume the object's group during this operation. + group_id = object_group_id; + } + + // Only allow proxy powers for PERM_COPY if the actual agent can + // receive the item (ie has PERM_TRANSFER permissions). + // NOTE: op == PERM_TRANSFER has already been handled, but if + // that ever changes we need to BLOCK proxy powers for PERM_TRANSFER. DK 03/28/06 + if (PERM_COPY != op || mPermissions->allowTransferTo(gAgent.getID())) + { + // Check if the agent can assume ownership through group proxy or agent-granted proxy. + if ( ( object_is_group_owned + && gAgent.hasPowerInGroup(object_owner_id, group_proxy_power)) + // Only allow proxy for move, modify, and copy. + || ( (PERM_MOVE == op || PERM_MODIFY == op || PERM_COPY == op) + && (!object_is_group_owned + && gAgent.isGrantedProxy(*mPermissions)))) + { + // This agent is able to assume the ownership role for this operation. + proxy_agent_id = object_owner_id; + } + } + + // We now have max ownership information. + if (PERM_OWNER == op) + { + // This this was just a check for ownership, we can now return the answer. + return (proxy_agent_id == object_owner_id ? TRUE : FALSE); + } + + // check permissions to see if the agent can operate + return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); +} + +//----------------------------------------------------------------------------- +// renderOneSilhouette() +//----------------------------------------------------------------------------- +void LLSelectNode::renderOneSilhouette(const LLColor4 &color) +{ + LLViewerObject* objectp = getObject(); + if (!objectp) + { + return; + } + + LLDrawable* drawable = objectp->mDrawable; + if(!drawable) + { + return; + } + + if (!mSilhouetteExists) + { + return; + } + + BOOL is_hud_object = objectp->isHUDAttachment(); + + if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) + { + return; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + if (!is_hud_object) + { + glLoadIdentity(); + glMultMatrixd(gGLModelView); + } + + + if (drawable->isActive()) + { + glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix); + } + + LLVolume *volume = objectp->getVolume(); + if (volume) + { + F32 silhouette_thickness; + if (is_hud_object && gAgent.getAvatarObject()) + { + silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.mHUDCurZoom; + } + else + { + LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition(); + silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()); + } + F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); + + F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); + F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f); + F32 u_divisor = 1.f / ((F32)(mSilhouetteVertices.size() - 1)); + + if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) + { + gGL.flush(); + gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); + LLGLEnable fog(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec(); + LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0); + glFogf(GL_FOG_START, d); + glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); + glFogfv(GL_FOG_COLOR, fogCol.mV); + + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.begin(LLRender::LINES); + { + S32 i = 0; + for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) + { + for(; i < mSilhouetteSegments[seg_num]; i++) + { + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv( mSilhouetteVertices[i].mV ); + } + } + } + gGL.end(); + u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); + } + + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.begin(LLRender::TRIANGLES); + { + S32 i = 0; + for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) + { + S32 first_i = i; + LLVector3 v; + LLVector2 t; + + for(; i < mSilhouetteSegments[seg_num]; i++) + { + + if (i == first_i) { + LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; + vert += mSilhouetteVertices[i]; + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); + gGL.vertex3fv( vert.mV ); + + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv( mSilhouetteVertices[i].mV ); + + v = mSilhouetteVertices[i]; + t = LLVector2(u_coord, v_coord); + } + else { + LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; + vert += mSilhouetteVertices[i]; + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); + gGL.vertex3fv( vert.mV ); + gGL.vertex3fv( vert.mV ); + + gGL.texCoord2fv(t.mV); + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + gGL.vertex3fv(v.mV); + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv( mSilhouetteVertices[i].mV ); + + } + } + } + } + gGL.end(); + gGL.flush(); + } + glPopMatrix(); +} + +// +// Utility Functions +// + +// Update everyone who cares about the selection list +void dialog_refresh_all() +{ + if (gNoRender) + { + return; + } + + //could refresh selected object info in toolbar here + + gFloaterTools->dirty(); + + if( gPieObject->getVisible() ) + { + gPieObject->arrange(); + } + + if( gPieAttachment->getVisible() ) + { + gPieAttachment->arrange(); + } + + LLFloaterProperties::dirtyAll(); + LLFloaterInspect::dirty(); +} + +S32 get_family_count(LLViewerObject *parent) +{ + if (!parent) + { + llwarns << "Trying to get_family_count on null parent!" << llendl; + } + S32 count = 1; // for this object + LLViewerObject::const_child_list_t& child_list = parent->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + + if (!child) + { + llwarns << "Family object has NULL child! Show Doug." << llendl; + } + else if (child->isDead()) + { + llwarns << "Family object has dead child object. Show Doug." << llendl; + } + else + { + if (LLSelectMgr::getInstance()->canSelectObject(child)) + { + count += get_family_count( child ); + } + } + } + return count; +} + +//----------------------------------------------------------------------------- +// updateSelectionCenter +//----------------------------------------------------------------------------- +void LLSelectMgr::updateSelectionCenter() +{ + const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection + // center (tractor beam) + + //override any object updates received + //for selected objects + overrideObjectUpdates(); + + LLViewerObject* object = mSelectedObjects->getFirstObject(); + if (!object) + { + // nothing selected, probably grabbing + // Ignore by setting to avatar origin. + mSelectionCenterGlobal.clearVec(); + mShowSelection = FALSE; + mSelectionBBox = LLBBox(); + mPauseRequest = NULL; + resetAgentHUDZoom(); + + } + else + { + mSelectedObjects->mSelectType = getSelectTypeForObject(object); + + if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + { + mPauseRequest = gAgent.getAvatarObject()->requestPause(); + } + else + { + mPauseRequest = NULL; + } + + if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject()) + { + // reset hud ZOOM + gAgent.mHUDTargetZoom = 1.f; + gAgent.mHUDCurZoom = 1.f; + } + + mShowSelection = FALSE; + LLBBox bbox; + + // have stuff selected + LLVector3d select_center; + // keep a list of jointed objects for showing the joint HUDEffects + + // Initialize the bounding box to the root prim, so the BBox orientation + // matches the root prim's (affecting the orientation of the manipulators). + bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() ); + + std::vector < LLViewerObject *> jointed_objects; + + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (!object) + continue; + LLViewerObject *myAvatar = gAgent.getAvatarObject(); + LLViewerObject *root = object->getRootEdit(); + if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment + !root->isChild(myAvatar) && // not the object you're sitting on + !object->isAvatar()) // not another avatar + { + mShowSelection = TRUE; + } + + bbox.addBBoxAgent( object->getBoundingBoxAgent() ); + + if (object->isJointChild()) + { + jointed_objects.push_back(object); + } + } + + LLVector3 bbox_center_agent = bbox.getCenterAgent(); + mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); + mSelectionBBox = bbox; + + } + + if ( !(gAgentID == LLUUID::null)) + { + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + if (mShowSelection) + { + LLVector3d select_center_global; + + if( tool->isEditing() ) + { + select_center_global = tool->getEditingPointGlobal(); + } + else + { + select_center_global = mSelectionCenterGlobal; + } + + // Send selection center if moved beyond threshold (used to animate tractor beam) + LLVector3d diff; + diff = select_center_global - mLastSentSelectionCenterGlobal; + + if ( diff.magVecSquared() > MOVE_SELECTION_THRESHOLD*MOVE_SELECTION_THRESHOLD ) + { + // Transmit updated selection center + mLastSentSelectionCenterGlobal = select_center_global; + } + } + } + + // give up edit menu if no objects selected + if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0) + { + gEditMenuHandler = NULL; + } +} + +void LLSelectMgr::updatePointAt() +{ + if (mShowSelection) + { + if (mSelectedObjects->getObjectCount()) + { + LLVector3 select_offset; + const LLPickInfo& pick = gViewerWindow->getLastPick(); + LLViewerObject *click_object = pick.getObject(); + if (click_object && click_object->isSelected()) + { + // clicked on another object in our selection group, use that as target + select_offset.setVec(pick.mObjectOffset); + select_offset.rotVec(~click_object->getRenderRotation()); + + gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset); + gAgent.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset); + } + else + { + // didn't click on an object this time, revert to pointing at center of first object + gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); + gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); + } + } + else + { + gAgent.setPointAt(POINTAT_TARGET_CLEAR); + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + } + } + else + { + gAgent.setPointAt(POINTAT_TARGET_CLEAR); + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + } +} + +//----------------------------------------------------------------------------- +// getBBoxOfSelection() +//----------------------------------------------------------------------------- +LLBBox LLSelectMgr::getBBoxOfSelection() const +{ + return mSelectionBBox; +} + + +//----------------------------------------------------------------------------- +// canUndo() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::canUndo() const +{ + return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG +} + +//----------------------------------------------------------------------------- +// undo() +//----------------------------------------------------------------------------- +void LLSelectMgr::undo() +{ + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + LLUUID group_id(gAgent.getGroupID()); + sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); +} + +//----------------------------------------------------------------------------- +// canRedo() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::canRedo() const +{ + return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG +} + +//----------------------------------------------------------------------------- +// redo() +//----------------------------------------------------------------------------- +void LLSelectMgr::redo() +{ + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + LLUUID group_id(gAgent.getGroupID()); + sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); +} + +//----------------------------------------------------------------------------- +// canDoDelete() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::canDoDelete() const +{ + // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) + return const_cast(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG +} + +//----------------------------------------------------------------------------- +// doDelete() +//----------------------------------------------------------------------------- +void LLSelectMgr::doDelete() +{ + selectDelete(); +} + +//----------------------------------------------------------------------------- +// canDeselect() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::canDeselect() const +{ + return !mSelectedObjects->isEmpty(); +} + +//----------------------------------------------------------------------------- +// deselect() +//----------------------------------------------------------------------------- +void LLSelectMgr::deselect() +{ + deselectAll(); +} +//----------------------------------------------------------------------------- +// canDuplicate() +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::canDuplicate() const +{ + return const_cast(this)->mSelectedObjects->getFirstCopyableObject() != NULL; // HACK: casting away constness - MG +} +//----------------------------------------------------------------------------- +// duplicate() +//----------------------------------------------------------------------------- +void LLSelectMgr::duplicate() +{ + LLVector3 offset(0.5f, 0.5f, 0.f); + selectDuplicate(offset, TRUE); +} + +ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object) +{ + if (!object) + { + return SELECT_TYPE_WORLD; + } + if (object->isHUDAttachment()) + { + return SELECT_TYPE_HUD; + } + else if (object->isAttachment()) + { + return SELECT_TYPE_ATTACHMENT; + } + else + { + return SELECT_TYPE_WORLD; + } +} + +void LLSelectMgr::validateSelection() +{ + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (!LLSelectMgr::getInstance()->canSelectObject(object)) + { + LLSelectMgr::getInstance()->deselectObjectOnly(object); + } + return true; + } + } func; + getSelection()->applyToObjects(&func); +} + +BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) +{ + // Never select dead objects + if (!object || object->isDead()) + { + return FALSE; + } + + if (mForceSelection) + { + return TRUE; + } + + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || + (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove())) + { + // only select my own objects + return FALSE; + } + + // Can't select orphans + if (object->isOrphaned()) return FALSE; + + // Can't select avatars + if (object->isAvatar()) return FALSE; + + // Can't select land + if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE; + // //ESelectType selection_type = getSelectTypeForObject(object); //if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE; // - - return TRUE; -} - -BOOL LLSelectMgr::setForceSelection(BOOL force) -{ - std::swap(mForceSelection,force); - return force; -} - -void LLSelectMgr::resetAgentHUDZoom() -{ - gAgent.mHUDTargetZoom = 1.f; - gAgent.mHUDCurZoom = 1.f; -} - -void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const -{ - target_zoom = gAgent.mHUDTargetZoom; - current_zoom = gAgent.mHUDCurZoom; -} - -void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) -{ - gAgent.mHUDTargetZoom = target_zoom; - gAgent.mHUDCurZoom = current_zoom; -} - -LLObjectSelection::LLObjectSelection() : - LLRefCount(), - mSelectType(SELECT_TYPE_WORLD) -{ -} - -LLObjectSelection::~LLObjectSelection() -{ - deleteAllNodes(); -} - -void LLObjectSelection::cleanupNodes() -{ - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ) - { - list_t::iterator curiter = iter++; - LLSelectNode* node = *curiter; - if (node->getObject() == NULL || node->getObject()->isDead()) - { - mList.erase(curiter); - delete node; - } - } -} - -void LLObjectSelection::updateEffects() -{ -} - -S32 LLObjectSelection::getNumNodes() -{ - return mList.size(); -} - -void LLObjectSelection::addNode(LLSelectNode *nodep) -{ - llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); - mList.push_front(nodep); - mSelectNodeMap[nodep->getObject()] = nodep; -} - -void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep) -{ - llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); - mList.push_back(nodep); - mSelectNodeMap[nodep->getObject()] = nodep; -} - -void LLObjectSelection::moveNodeToFront(LLSelectNode *nodep) -{ - mList.remove(nodep); - mList.push_front(nodep); -} - -void LLObjectSelection::removeNode(LLSelectNode *nodep) -{ - mSelectNodeMap.erase(nodep->getObject()); - if (nodep->getObject() == mPrimaryObject) - { - mPrimaryObject = NULL; - } - nodep->setObject(NULL); // Will get erased in cleanupNodes() - mList.remove(nodep); -} - -void LLObjectSelection::deleteAllNodes() -{ - std::for_each(mList.begin(), mList.end(), DeletePointer()); - mList.clear(); - mSelectNodeMap.clear(); - mPrimaryObject = NULL; -} - -LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp) -{ - std::map, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp); - if (found_it != mSelectNodeMap.end()) - { - return found_it->second; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// isEmpty() -//----------------------------------------------------------------------------- -BOOL LLObjectSelection::isEmpty() const -{ - return (mList.size() == 0); -} - -//----------------------------------------------------------------------------- -// getOwnershipCost() -//----------------------------------------------------------------------------- -BOOL LLObjectSelection::getOwnershipCost(S32 &cost) -{ - S32 count = getObjectCount(); - cost = count * OWNERSHIP_COST_PER_OBJECT; - return (count > 0); -} - - -//----------------------------------------------------------------------------- -// getObjectCount() - returns number of non null objects -//----------------------------------------------------------------------------- -S32 LLObjectSelection::getObjectCount() -{ - cleanupNodes(); - S32 count = mList.size(); - return count; -} - - -//----------------------------------------------------------------------------- -// getTECount() -//----------------------------------------------------------------------------- -S32 LLObjectSelection::getTECount() -{ - S32 count = 0; - for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if (!object) - continue; - S32 num_tes = object->getNumTEs(); - for (S32 te = 0; te < num_tes; te++) - { - if (node->isTESelected(te)) - { - ++count; - } - } - } - return count; -} - -//----------------------------------------------------------------------------- -// getRootObjectCount() -//----------------------------------------------------------------------------- -S32 LLObjectSelection::getRootObjectCount() -{ - S32 count = 0; - for (LLObjectSelection::root_iterator iter = root_begin(); iter != root_end(); iter++) - { - ++count; - } - return count; -} - -bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func) -{ - bool result = true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - bool r = func->apply(object); - result = result && r; - } - return result; -} - -bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly) -{ - bool result = firstonly ? false : true; - for (root_iterator iter = root_begin(); iter != root_end(); ) - { - root_iterator nextiter = iter++; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - bool r = func->apply(object); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; -} - -bool LLObjectSelection::applyToTEs(LLSelectedTEFunctor* func, bool firstonly) -{ - bool result = firstonly ? false : true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces - for (S32 te = 0; te < num_tes; ++te) - { - if (node->isTESelected(te)) - { - bool r = func->apply(object, te); - if (firstonly && r) - return true; - else - result = result && r; - } - } - } - return result; -} - -bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func, bool firstonly) -{ - bool result = firstonly ? false : true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - bool r = func->apply(node); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; -} - -bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool firstonly) -{ - bool result = firstonly ? false : true; - for (root_iterator iter = root_begin(); iter != root_end(); ) - { - root_iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - bool r = func->apply(node); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; -} - -//----------------------------------------------------------------------------- -// contains() -//----------------------------------------------------------------------------- -BOOL LLObjectSelection::contains(LLViewerObject* object) -{ - return findNode(object) != NULL; -} - - -//----------------------------------------------------------------------------- -// contains() -//----------------------------------------------------------------------------- -BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te) -{ - if (te == SELECT_ALL_TES) - { - // ...all faces - for (LLObjectSelection::iterator iter = begin(); - iter != end(); iter++) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object) - { - BOOL all_selected = TRUE; - for (S32 i = 0; i < SELECT_MAX_TES; i++) - { - all_selected = all_selected && nodep->isTESelected(i); - } - return all_selected; - } - } - return FALSE; - } - else - { - // ...one face - for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object && nodep->isTESelected(te)) - { - return TRUE; - } - } - return FALSE; - } -} - -// returns TRUE is any node is currenly worn as an attachment -BOOL LLObjectSelection::isAttachment() -{ - return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); -} - -//----------------------------------------------------------------------------- -// getSelectedParentObject() -//----------------------------------------------------------------------------- -LLViewerObject* getSelectedParentObject(LLViewerObject *object) -{ - LLViewerObject *parent; - while (object && (parent = (LLViewerObject*)object->getParent())) - { - if (parent->isSelected()) - { - object = parent; - } - else - { - break; - } - } - return object; -} - -//----------------------------------------------------------------------------- -// getFirstNode -//----------------------------------------------------------------------------- -LLSelectNode* LLObjectSelection::getFirstNode(LLSelectedNodeFunctor* func) -{ - for (iterator iter = begin(); iter != end(); ++iter) - { - LLSelectNode* node = *iter; - if (func == NULL || func->apply(node)) - { - return node; - } - } - return NULL; -} - -LLSelectNode* LLObjectSelection::getFirstRootNode(LLSelectedNodeFunctor* func, BOOL non_root_ok) -{ - for (root_iterator iter = root_begin(); iter != root_end(); ++iter) - { - LLSelectNode* node = *iter; - if (func == NULL || func->apply(node)) - { - return node; - } - } - if (non_root_ok) - { - // Get non root - return getFirstNode(func); - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// getFirstSelectedObject -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent) -{ - LLSelectNode* res = getFirstNode(func); - if (res && get_parent) - { - return getSelectedParentObject(res->getObject()); - } - else if (res) - { - return res->getObject(); - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getFirstObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstObject() -{ - LLSelectNode* res = getFirstNode(NULL); - return res ? res->getObject() : NULL; -} - -//----------------------------------------------------------------------------- -// getFirstRootObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstRootObject(BOOL non_root_ok) -{ - LLSelectNode* res = getFirstRootNode(NULL, non_root_ok); - return res ? res->getObject() : NULL; -} - -//----------------------------------------------------------------------------- -// getFirstMoveableNode() -//----------------------------------------------------------------------------- -LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) -{ - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permMove(); - } - } func; - LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func); - return res; -} - -//----------------------------------------------------------------------------- -// getFirstCopyableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent) -{ - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permCopy() && !obj->isAttachment(); - } - } func; - return getFirstSelectedObject(&func, get_parent); -} - -//----------------------------------------------------------------------------- -// getFirstDeleteableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstDeleteableObject() -{ - //RN: don't currently support deletion of child objects, as that requires separating them first - // then derezzing to trash - - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - // you can delete an object if you are the owner - // or you have permission to modify it. - if( obj && ( (obj->permModify()) || - (obj->permYouOwner()) || - (!obj->permAnyOwner()) )) // public - { - if( !obj->isAttachment() ) - { - return true; - } - } - return false; - } - } func; - LLSelectNode* node = getFirstNode(&func); - return node ? node->getObject() : NULL; -} - -//----------------------------------------------------------------------------- -// getFirstEditableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent) -{ - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permModify(); - } - } func; - return getFirstSelectedObject(&func, get_parent); -} - -//----------------------------------------------------------------------------- -// getFirstMoveableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent) -{ - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permMove(); - } - } func; - return getFirstSelectedObject(&func, get_parent); -} - -//----------------------------------------------------------------------------- -// Position + Rotation update methods called from LLViewerJoystick -//----------------------------------------------------------------------------- -bool LLSelectMgr::selectionMove(const LLVector3& displ, - F32 roll, F32 pitch, F32 yaw, U32 update_type) -{ - if (update_type == UPD_NONE) - { - return false; - } - - LLVector3 displ_global; - bool update_success = true; - bool update_position = update_type & UPD_POSITION; - bool update_rotation = update_type & UPD_ROTATION; - const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts"); - - if (update_position) - { - // calculate the distance of the object closest to the camera origin - F32 min_dist = 1e+30f; - LLVector3 obj_pos; - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it) - { - obj_pos = (*it)->getObject()->getPositionEdit(); - - F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin()); - if (obj_dist < min_dist) - { - min_dist = obj_dist; - } - } - - // factor the distance inside the displacement vector. This will get us - // equally visible movements for both close and far away selections. - min_dist = sqrt(min_dist) / 2; - displ_global.setVec(displ.mV[0]*min_dist, - displ.mV[1]*min_dist, - displ.mV[2]*min_dist); - - // equates to: Displ_global = Displ * M_cam_axes_in_global_frame - displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); - } - - LLQuaternion new_rot; - if (update_rotation) - { - // let's calculate the rotation around each camera axes - LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis()); - LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis()); - LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis()); - new_rot.setQuat(qx * qy * qz); - } - - LLViewerObject *obj; - S32 obj_count = getSelection()->getObjectCount(); - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it ) - { - obj = (*it)->getObject(); - bool enable_pos = false, enable_rot = false; - bool perm_move = obj->permMove(); - bool perm_mod = obj->permModify(); - - LLVector3d sel_center(getSelectionCenterGlobal()); - - if (update_rotation) - { - enable_rot = perm_move - && ((perm_mod && !obj->isAttachment()) || noedit_linked_parts); - - if (enable_rot) - { - int children_count = obj->getChildren().size(); - if (obj_count > 1 && children_count > 0) - { - // for linked sets, rotate around the group center - const LLVector3 t(obj->getPositionGlobal() - sel_center); - - // Ra = T x R x T^-1 - LLMatrix4 mt; mt.setTranslation(t); - const LLMatrix4 mnew_rot(new_rot); - LLMatrix4 mt_1; mt_1.setTranslation(-t); - mt *= mnew_rot; - mt *= mt_1; - - // Rfin = Rcur * Ra - obj->setRotation(obj->getRotationEdit() * mt.quaternion()); - displ_global += mt.getTranslation(); - } - else - { - obj->setRotation(obj->getRotationEdit() * new_rot); - } - } - else - { - update_success = false; - } - } - - if (update_position) - { - // establish if object can be moved or not - enable_pos = perm_move && !obj->isAttachment() - && (perm_mod || noedit_linked_parts); - - if (enable_pos) - { - obj->setPosition(obj->getPositionEdit() + displ_global); - } - else - { - update_success = false; - } - } - - if (enable_pos && enable_rot && obj->mDrawable.notNull()) - { - gPipeline.markMoved(obj->mDrawable, TRUE); - } - } - - if (update_position && update_success && obj_count > 1) - { - updateSelectionCenter(); - } - - return update_success; -} - -void LLSelectMgr::sendSelectionMove() -{ - LLSelectNode *node = mSelectedObjects->getFirstRootNode(); - if (node == NULL) - { - return; - } - - //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - - U32 update_type = UPD_POSITION | UPD_ROTATION; - LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion(); - S32 objects_in_this_packet = 0; - - // apply to linked objects if unable to select their individual parts - if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) - { - // tell simulator to apply to whole linked sets - update_type |= UPD_LINKED_SETS; - } - - // prepare first bulk message - gMessageSystem->newMessage("MultipleObjectUpdate"); - packAgentAndSessionID(&update_type); - - LLViewerObject *obj = NULL; - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it) - { - obj = (*it)->getObject(); - - // note: following code adapted from sendListToRegions() (@3924) - last_region = curr_region; - curr_region = obj->getRegion(); - - // if not simulator or message too big - if (curr_region != last_region - || gMessageSystem->isSendFull(NULL) - || objects_in_this_packet >= MAX_OBJECTS_PER_PACKET) - { - // send sim the current message and start new one - gMessageSystem->sendReliable(last_region->getHost()); - objects_in_this_packet = 0; - gMessageSystem->newMessage("MultipleObjectUpdate"); - packAgentAndSessionID(&update_type); - } - - // add another instance of the body of data - packMultipleUpdate(*it, &update_type); - ++objects_in_this_packet; - } - - // flush remaining messages - if (gMessageSystem->getCurrentSendTotal() > 0) - { - gMessageSystem->sendReliable(curr_region->getHost()); - } - else - { - gMessageSystem->clearMessage(); - } - - //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); -} + + return TRUE; +} + +BOOL LLSelectMgr::setForceSelection(BOOL force) +{ + std::swap(mForceSelection,force); + return force; +} + +void LLSelectMgr::resetAgentHUDZoom() +{ + gAgent.mHUDTargetZoom = 1.f; + gAgent.mHUDCurZoom = 1.f; +} + +void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const +{ + target_zoom = gAgent.mHUDTargetZoom; + current_zoom = gAgent.mHUDCurZoom; +} + +void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) +{ + gAgent.mHUDTargetZoom = target_zoom; + gAgent.mHUDCurZoom = current_zoom; +} + +LLObjectSelection::LLObjectSelection() : + LLRefCount(), + mSelectType(SELECT_TYPE_WORLD) +{ +} + +LLObjectSelection::~LLObjectSelection() +{ + deleteAllNodes(); +} + +void LLObjectSelection::cleanupNodes() +{ + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ) + { + list_t::iterator curiter = iter++; + LLSelectNode* node = *curiter; + if (node->getObject() == NULL || node->getObject()->isDead()) + { + mList.erase(curiter); + delete node; + } + } +} + +void LLObjectSelection::updateEffects() +{ +} + +S32 LLObjectSelection::getNumNodes() +{ + return mList.size(); +} + +void LLObjectSelection::addNode(LLSelectNode *nodep) +{ + llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); + mList.push_front(nodep); + mSelectNodeMap[nodep->getObject()] = nodep; +} + +void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep) +{ + llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); + mList.push_back(nodep); + mSelectNodeMap[nodep->getObject()] = nodep; +} + +void LLObjectSelection::moveNodeToFront(LLSelectNode *nodep) +{ + mList.remove(nodep); + mList.push_front(nodep); +} + +void LLObjectSelection::removeNode(LLSelectNode *nodep) +{ + mSelectNodeMap.erase(nodep->getObject()); + if (nodep->getObject() == mPrimaryObject) + { + mPrimaryObject = NULL; + } + nodep->setObject(NULL); // Will get erased in cleanupNodes() + mList.remove(nodep); +} + +void LLObjectSelection::deleteAllNodes() +{ + std::for_each(mList.begin(), mList.end(), DeletePointer()); + mList.clear(); + mSelectNodeMap.clear(); + mPrimaryObject = NULL; +} + +LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp) +{ + std::map, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp); + if (found_it != mSelectNodeMap.end()) + { + return found_it->second; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// isEmpty() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::isEmpty() const +{ + return (mList.size() == 0); +} + +//----------------------------------------------------------------------------- +// getOwnershipCost() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::getOwnershipCost(S32 &cost) +{ + S32 count = getObjectCount(); + cost = count * OWNERSHIP_COST_PER_OBJECT; + return (count > 0); +} + + +//----------------------------------------------------------------------------- +// getObjectCount() - returns number of non null objects +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getObjectCount() +{ + cleanupNodes(); + S32 count = mList.size(); + return count; +} + + +//----------------------------------------------------------------------------- +// getTECount() +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getTECount() +{ + S32 count = 0; + for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (!object) + continue; + S32 num_tes = object->getNumTEs(); + for (S32 te = 0; te < num_tes; te++) + { + if (node->isTESelected(te)) + { + ++count; + } + } + } + return count; +} + +//----------------------------------------------------------------------------- +// getRootObjectCount() +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getRootObjectCount() +{ + S32 count = 0; + for (LLObjectSelection::root_iterator iter = root_begin(); iter != root_end(); iter++) + { + ++count; + } + return count; +} + +bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func) +{ + bool result = true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + bool r = func->apply(object); + result = result && r; + } + return result; +} + +bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly) +{ + bool result = firstonly ? false : true; + for (root_iterator iter = root_begin(); iter != root_end(); ) + { + root_iterator nextiter = iter++; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + bool r = func->apply(object); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; +} + +bool LLObjectSelection::applyToTEs(LLSelectedTEFunctor* func, bool firstonly) +{ + bool result = firstonly ? false : true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + bool r = func->apply(object, te); + if (firstonly && r) + return true; + else + result = result && r; + } + } + } + return result; +} + +bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func, bool firstonly) +{ + bool result = firstonly ? false : true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + bool r = func->apply(node); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; +} + +bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool firstonly) +{ + bool result = firstonly ? false : true; + for (root_iterator iter = root_begin(); iter != root_end(); ) + { + root_iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + bool r = func->apply(node); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; +} + +//----------------------------------------------------------------------------- +// contains() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::contains(LLViewerObject* object) +{ + return findNode(object) != NULL; +} + + +//----------------------------------------------------------------------------- +// contains() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te) +{ + if (te == SELECT_ALL_TES) + { + // ...all faces + for (LLObjectSelection::iterator iter = begin(); + iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object) + { + BOOL all_selected = TRUE; + for (S32 i = 0; i < SELECT_MAX_TES; i++) + { + all_selected = all_selected && nodep->isTESelected(i); + } + return all_selected; + } + } + return FALSE; + } + else + { + // ...one face + for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object && nodep->isTESelected(te)) + { + return TRUE; + } + } + return FALSE; + } +} + +// returns TRUE is any node is currenly worn as an attachment +BOOL LLObjectSelection::isAttachment() +{ + return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); +} + +//----------------------------------------------------------------------------- +// getSelectedParentObject() +//----------------------------------------------------------------------------- +LLViewerObject* getSelectedParentObject(LLViewerObject *object) +{ + LLViewerObject *parent; + while (object && (parent = (LLViewerObject*)object->getParent())) + { + if (parent->isSelected()) + { + object = parent; + } + else + { + break; + } + } + return object; +} + +//----------------------------------------------------------------------------- +// getFirstNode +//----------------------------------------------------------------------------- +LLSelectNode* LLObjectSelection::getFirstNode(LLSelectedNodeFunctor* func) +{ + for (iterator iter = begin(); iter != end(); ++iter) + { + LLSelectNode* node = *iter; + if (func == NULL || func->apply(node)) + { + return node; + } + } + return NULL; +} + +LLSelectNode* LLObjectSelection::getFirstRootNode(LLSelectedNodeFunctor* func, BOOL non_root_ok) +{ + for (root_iterator iter = root_begin(); iter != root_end(); ++iter) + { + LLSelectNode* node = *iter; + if (func == NULL || func->apply(node)) + { + return node; + } + } + if (non_root_ok) + { + // Get non root + return getFirstNode(func); + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// getFirstSelectedObject +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent) +{ + LLSelectNode* res = getFirstNode(func); + if (res && get_parent) + { + return getSelectedParentObject(res->getObject()); + } + else if (res) + { + return res->getObject(); + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getFirstObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstObject() +{ + LLSelectNode* res = getFirstNode(NULL); + return res ? res->getObject() : NULL; +} + +//----------------------------------------------------------------------------- +// getFirstRootObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstRootObject(BOOL non_root_ok) +{ + LLSelectNode* res = getFirstRootNode(NULL, non_root_ok); + return res ? res->getObject() : NULL; +} + +//----------------------------------------------------------------------------- +// getFirstMoveableNode() +//----------------------------------------------------------------------------- +LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) +{ + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permMove(); + } + } func; + LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func); + return res; +} + +//----------------------------------------------------------------------------- +// getFirstCopyableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent) +{ + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permCopy() && !obj->isAttachment(); + } + } func; + return getFirstSelectedObject(&func, get_parent); +} + +//----------------------------------------------------------------------------- +// getFirstDeleteableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstDeleteableObject() +{ + //RN: don't currently support deletion of child objects, as that requires separating them first + // then derezzing to trash + + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + // you can delete an object if you are the owner + // or you have permission to modify it. + if( obj && ( (obj->permModify()) || + (obj->permYouOwner()) || + (!obj->permAnyOwner()) )) // public + { + if( !obj->isAttachment() ) + { + return true; + } + } + return false; + } + } func; + LLSelectNode* node = getFirstNode(&func); + return node ? node->getObject() : NULL; +} + +//----------------------------------------------------------------------------- +// getFirstEditableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent) +{ + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permModify(); + } + } func; + return getFirstSelectedObject(&func, get_parent); +} + +//----------------------------------------------------------------------------- +// getFirstMoveableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent) +{ + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permMove(); + } + } func; + return getFirstSelectedObject(&func, get_parent); +} + +//----------------------------------------------------------------------------- +// Position + Rotation update methods called from LLViewerJoystick +//----------------------------------------------------------------------------- +bool LLSelectMgr::selectionMove(const LLVector3& displ, + F32 roll, F32 pitch, F32 yaw, U32 update_type) +{ + if (update_type == UPD_NONE) + { + return false; + } + + LLVector3 displ_global; + bool update_success = true; + bool update_position = update_type & UPD_POSITION; + bool update_rotation = update_type & UPD_ROTATION; + const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts"); + + if (update_position) + { + // calculate the distance of the object closest to the camera origin + F32 min_dist = 1e+30f; + LLVector3 obj_pos; + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it) + { + obj_pos = (*it)->getObject()->getPositionEdit(); + + F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin()); + if (obj_dist < min_dist) + { + min_dist = obj_dist; + } + } + + // factor the distance inside the displacement vector. This will get us + // equally visible movements for both close and far away selections. + min_dist = sqrt(min_dist) / 2; + displ_global.setVec(displ.mV[0]*min_dist, + displ.mV[1]*min_dist, + displ.mV[2]*min_dist); + + // equates to: Displ_global = Displ * M_cam_axes_in_global_frame + displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); + } + + LLQuaternion new_rot; + if (update_rotation) + { + // let's calculate the rotation around each camera axes + LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis()); + LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis()); + LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis()); + new_rot.setQuat(qx * qy * qz); + } + + LLViewerObject *obj; + S32 obj_count = getSelection()->getObjectCount(); + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it ) + { + obj = (*it)->getObject(); + bool enable_pos = false, enable_rot = false; + bool perm_move = obj->permMove(); + bool perm_mod = obj->permModify(); + + LLVector3d sel_center(getSelectionCenterGlobal()); + + if (update_rotation) + { + enable_rot = perm_move + && ((perm_mod && !obj->isAttachment()) || noedit_linked_parts); + + if (enable_rot) + { + int children_count = obj->getChildren().size(); + if (obj_count > 1 && children_count > 0) + { + // for linked sets, rotate around the group center + const LLVector3 t(obj->getPositionGlobal() - sel_center); + + // Ra = T x R x T^-1 + LLMatrix4 mt; mt.setTranslation(t); + const LLMatrix4 mnew_rot(new_rot); + LLMatrix4 mt_1; mt_1.setTranslation(-t); + mt *= mnew_rot; + mt *= mt_1; + + // Rfin = Rcur * Ra + obj->setRotation(obj->getRotationEdit() * mt.quaternion()); + displ_global += mt.getTranslation(); + } + else + { + obj->setRotation(obj->getRotationEdit() * new_rot); + } + } + else + { + update_success = false; + } + } + + if (update_position) + { + // establish if object can be moved or not + enable_pos = perm_move && !obj->isAttachment() + && (perm_mod || noedit_linked_parts); + + if (enable_pos) + { + obj->setPosition(obj->getPositionEdit() + displ_global); + } + else + { + update_success = false; + } + } + + if (enable_pos && enable_rot && obj->mDrawable.notNull()) + { + gPipeline.markMoved(obj->mDrawable, TRUE); + } + } + + if (update_position && update_success && obj_count > 1) + { + updateSelectionCenter(); + } + + return update_success; +} + +void LLSelectMgr::sendSelectionMove() +{ + LLSelectNode *node = mSelectedObjects->getFirstRootNode(); + if (node == NULL) + { + return; + } + + //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + + U32 update_type = UPD_POSITION | UPD_ROTATION; + LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion(); + S32 objects_in_this_packet = 0; + + // apply to linked objects if unable to select their individual parts + if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) + { + // tell simulator to apply to whole linked sets + update_type |= UPD_LINKED_SETS; + } + + // prepare first bulk message + gMessageSystem->newMessage("MultipleObjectUpdate"); + packAgentAndSessionID(&update_type); + + LLViewerObject *obj = NULL; + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it) + { + obj = (*it)->getObject(); + + // note: following code adapted from sendListToRegions() (@3924) + last_region = curr_region; + curr_region = obj->getRegion(); + + // if not simulator or message too big + if (curr_region != last_region + || gMessageSystem->isSendFull(NULL) + || objects_in_this_packet >= MAX_OBJECTS_PER_PACKET) + { + // send sim the current message and start new one + gMessageSystem->sendReliable(last_region->getHost()); + objects_in_this_packet = 0; + gMessageSystem->newMessage("MultipleObjectUpdate"); + packAgentAndSessionID(&update_type); + } + + // add another instance of the body of data + packMultipleUpdate(*it, &update_type); + ++objects_in_this_packet; + } + + // flush remaining messages + if (gMessageSystem->getCurrentSendTotal() > 0) + { + gMessageSystem->sendReliable(curr_region->getHost()); + } + else + { + gMessageSystem->clearMessage(); + } + + //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); +} diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index bb0b24391..4aa7d4a78 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,14 +199,29 @@ //#include "llactivation.h" #include "llao.h" #include "llfloaterblacklist.h" -//#include "llcheats.h" +#include "scriptcounter.h" // + + + + + + + #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" #endif + + + + + + + + // // exported globals // @@ -241,6 +256,7 @@ static bool gUseCircuitCallbackCalled = false; EStartupState LLStartUp::gStartupState = STATE_FIRST; + // // local function declaration // @@ -1706,14 +1722,6 @@ bool idle_startup() hashed_mac.finalize(); hashed_mac.hex_digest(hashed_mac_string); - // - std::string my_mac = std::string(hashed_mac_string); - if(gSavedSettings.getBOOL("SpecifyMAC")) - my_mac = gSavedSettings.getString("SpecifiedMAC").c_str(); - std::string my_id0 = LLAppViewer::instance()->getSerialNumber(); - if(gSavedSettings.getBOOL("SpecifyID0")) - my_id0 = gSavedSettings.getString("SpecifiedID0"); - // LLViewerLogin* vl = LLViewerLogin::getInstance(); std::string grid_uri = vl->getCurrentGridURI(); @@ -1734,12 +1742,9 @@ bool idle_startup() gAcceptCriticalMessage, gLastExecEvent, requested_options, - // - // hashed_mac_string, - // LLAppViewer::instance()->getSerialNumber()); - my_mac, - my_id0); - // + hashed_mac_string, + LLAppViewer::instance()->getSerialNumber()); + // reset globals gAcceptTOS = FALSE; @@ -2942,19 +2947,6 @@ bool idle_startup() } } - // testing adding a local inventory folder... - LLViewerInventoryCategory* test_cat = new LLViewerInventoryCategory(gAgent.getID()); - test_cat->rename(std::string("Pretend Inventory")); - LLUUID test_cat_id; - test_cat_id.generate(); - test_cat->setUUID(test_cat_id); - gLocalInventoryRoot = test_cat_id; - test_cat->setParent(LLUUID::null); - test_cat->setPreferredType(LLAssetType::AT_NONE); - - gInventory.addCategory(test_cat); - // - options.clear(); if(LLUserAuth::getInstance()->getOptions("buddy-list", options)) { @@ -4004,11 +3996,13 @@ void use_circuit_callback(void**, S32 result) } } + void pass_processObjectPropertiesFamily(LLMessageSystem *msg, void**) { // Send the result to the corresponding requesters. LLSelectMgr::processObjectPropertiesFamily(msg, NULL); JCFloaterAreaSearch::processObjectPropertiesFamily(msg, NULL); + ScriptCounter::processObjectPropertiesFamily(msg,0); } void register_viewer_callbacks(LLMessageSystem* msg) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 5db0881d6..f87a8cba7 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -484,7 +484,12 @@ BOOL LLFloaterTexturePicker::postBuild() { LLFloater::postBuild(); - childSetValue("texture_uuid", mImageAssetID); + LLInventoryItem* itemp = gInventory.getItem(mImageAssetID); + + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + childSetValue("texture_uuid", mImageAssetID); + else + childSetValue("texture_uuid", LLUUID::null.asString()); if (!mLabel.empty()) { @@ -913,19 +918,14 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *da { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; - // - //LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE); - //if (self && inventory_item_id.notNull()) - if(self) - // + LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE); + if (self && inventory_item_id.notNull()) { LLToolPipette::getInstance()->setResult(TRUE, ""); self->setImageID(te.getID()); self->mNoCopyTextureSelected = FALSE; - // - self->childSetValue("texture_uuid", te.getID().asString()); - /* + LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) @@ -933,8 +933,10 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *da // no copy texture self->mNoCopyTextureSelected = TRUE; } - */ - // + else + { + self->childSetValue("texture_uuid", te.getID().asString()); + } self->commitIfImmediateSet(); } @@ -1309,7 +1311,6 @@ BOOL LLTextureCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } - // void LLTextureCtrl::onFloaterClose() diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 6b53e3bc5..b9f2cdd9d 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -70,6 +70,8 @@ #include "llimview.h" // #include "llappviewer.h" // gLocalInventoryRoot +#include "llparcel.h" // always rez +#include "llviewerparcelmgr.h" // always rez // // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES @@ -1257,16 +1259,16 @@ void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj, } hit_obj->saveScript(new_script, active, true); gFloaterTools->dirty(); - // - if(gSavedSettings.getBOOL("BroadcastViewerEffects")) + + if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { // // VEFFECT: SetScript - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setTargetObject(hit_obj); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setTargetObject(hit_obj); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); // } // @@ -1362,7 +1364,17 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + + // Alway rez objects as land group if available. + if (gSavedSettings.getBOOL("AscentAlwaysRezInGroup")) + { + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(gAgent.isInGroup(parcel->getGroupID())) + msg->addUUIDFast(_PREHASH_GroupID, parcel->getGroupID()); + else if(gAgent.isInGroup(parcel->getOwnerID())) + msg->addUUIDFast(_PREHASH_GroupID, parcel->getOwnerID()); + else msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + } else msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); msg->nextBlock("RezData"); // if it's being rezzed from task inventory, we need to enable @@ -1426,16 +1438,16 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, gInventory.notifyObservers(); } // - if(gSavedSettings.getBOOL("BroadcastViewerEffects")) + if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { - // - // VEFFECT: DropObject - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setPositionGlobal(mLastHitPos); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - // + // + // VEFFECT: DropObject + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setPositionGlobal(mLastHitPos); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + // } // LLViewerStats::getInstance()->incStat(LLViewerStats::ST_REZ_COUNT); @@ -1494,15 +1506,15 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS); } // - if(gSavedSettings.getBOOL("BroadcastViewerEffects")) + if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { - // - // VEFFECT: AddToInventory - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setTargetObject(hit_obj); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); + // + // VEFFECT: AddToInventory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setTargetObject(hit_obj); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); // } // @@ -1610,15 +1622,15 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent, BUCKET_SIZE); gAgent.sendReliableMessage(); // - if(gSavedSettings.getBOOL("BroadcastViewerEffects")) + if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { - // - // VEFFECT: giveInventory - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setTargetObject(gObjectList.findObject(to_agent)); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); + // + // VEFFECT: giveInventory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setTargetObject(gObjectList.findObject(to_agent)); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); // } // @@ -1833,16 +1845,16 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent, gAgent.sendReliableMessage(); delete[] bucket; // - if(gSavedSettings.getBOOL("BroadcastViewerEffects")) + if (gSavedSettings.getBOOL("BroadcastViewerEffects")) { - // - // VEFFECT: giveInventoryCategory - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgent.getAvatarObject()); - effectp->setTargetObject(gObjectList.findObject(to_agent)); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - // + // + // VEFFECT: giveInventoryCategory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgent.getAvatarObject()); + effectp->setTargetObject(gObjectList.findObject(to_agent)); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + // } // gFloaterTools->dirty(); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 4c79a0a21..11e4534d0 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1,167 +1,167 @@ -/** - * @file lltoolpie.cpp - * @brief LLToolPie class implementation - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lltoolpie.h" - -#include "indra_constants.h" -#include "llclickaction.h" -#include "llparcel.h" - -#include "llagent.h" -#include "llviewercontrol.h" -#include "llfocusmgr.h" -#include "llfirstuse.h" -#include "llfloateravatarinfo.h" -#include "llfloaterland.h" -#include "llfloaterscriptdebug.h" -#include "llhoverview.h" -#include "llhudeffecttrail.h" -#include "llhudmanager.h" -#include "llmenugl.h" -#include "llmutelist.h" -#include "llselectmgr.h" -#include "lltoolfocus.h" -#include "lltoolgrab.h" -#include "lltoolmgr.h" -#include "lltoolselect.h" -#include "llviewercamera.h" -#include "llviewerparcelmedia.h" -#include "llviewermenu.h" -#include "llviewerobjectlist.h" -#include "llviewerobject.h" -#include "llviewerparcelmgr.h" -#include "llviewerwindow.h" -#include "llviewermedia.h" -#include "llviewermediafocus.h" -#include "llvoavatar.h" -#include "llworld.h" -#include "llui.h" -#include "llweb.h" - -// -#include "lllocalinventory.h" -// - -extern void handle_buy(void*); - -extern BOOL gDebugClicks; - -static bool handle_media_click(const LLPickInfo& info); -static bool handle_media_hover(const LLPickInfo& info); -static void handle_click_action_play(); -static void handle_click_action_open_media(LLPointer objectp); -static ECursorType cursor_from_parcel_media(U8 click_action); - - -LLToolPie::LLToolPie() -: LLTool(std::string("Pie")), - mPieMouseButtonDown( FALSE ), - mGrabMouseButtonDown( FALSE ), - mMouseOutsideSlop( FALSE ), - mClickAction(0) -{ } - - -BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) -{ - //left mouse down always picks transparent - gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); - mGrabMouseButtonDown = TRUE; - return TRUE; -} - -// static -void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickAndShowMenu(FALSE); -} - -BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - // don't pick transparent so users can't "pay" transparent objects - gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE); - mPieMouseButtonDown = TRUE; - // don't steal focus from UI - return FALSE; -} - -BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); -} -// static -void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickAndShowMenu(TRUE); -} - -// True if you selected an object. -BOOL LLToolPie::pickAndShowMenu(BOOL always_show) -{ - S32 x = mPick.mMousePt.mX; - S32 y = mPick.mMousePt.mY; - MASK mask = mPick.mKeyMask; - if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) - { - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel(); - if (parcel) - { - LLViewerParcelMgr::getInstance()->selectCollisionParcel(); - if (parcel->getParcelFlag(PF_USE_PASS_LIST) - && !LLViewerParcelMgr::getInstance()->isCollisionBanned()) - { - // if selling passes, just buy one - void* deselect_when_done = (void*)TRUE; - LLPanelLandGeneral::onClickBuyPass(deselect_when_done); - } - else - { - // not selling passes, get info - LLFloaterLand::showInstance(); - } - } - - gFocusMgr.setKeyboardFocus(NULL); - return LLTool::handleMouseDown(x, y, mask); - } - - // didn't click in any UI object, so must have clicked in the world - LLViewerObject *object = mPick.getObject(); - LLViewerObject *parent = NULL; - +/** + * @file lltoolpie.cpp + * @brief LLToolPie class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltoolpie.h" + +#include "indra_constants.h" +#include "llclickaction.h" +#include "llparcel.h" + +#include "llagent.h" +#include "llviewercontrol.h" +#include "llfocusmgr.h" +#include "llfirstuse.h" +#include "llfloateravatarinfo.h" +#include "llfloaterland.h" +#include "llfloaterscriptdebug.h" +#include "llhoverview.h" +#include "llhudeffecttrail.h" +#include "llhudmanager.h" +#include "llmenugl.h" +#include "llmutelist.h" +#include "llselectmgr.h" +#include "lltoolfocus.h" +#include "lltoolgrab.h" +#include "lltoolmgr.h" +#include "lltoolselect.h" +#include "llviewercamera.h" +#include "llviewerparcelmedia.h" +#include "llviewermenu.h" +#include "llviewerobjectlist.h" +#include "llviewerobject.h" +#include "llviewerparcelmgr.h" +#include "llviewerwindow.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" +#include "llvoavatar.h" +#include "llworld.h" +#include "llui.h" +#include "llweb.h" + +// +#include "lllocalinventory.h" +// + +extern void handle_buy(void*); + +extern BOOL gDebugClicks; + +static bool handle_media_click(const LLPickInfo& info); +static bool handle_media_hover(const LLPickInfo& info); +static void handle_click_action_play(); +static void handle_click_action_open_media(LLPointer objectp); +static ECursorType cursor_from_parcel_media(U8 click_action); + + +LLToolPie::LLToolPie() +: LLTool(std::string("Pie")), + mPieMouseButtonDown( FALSE ), + mGrabMouseButtonDown( FALSE ), + mMouseOutsideSlop( FALSE ), + mClickAction(0) +{ } + + +BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) +{ + //left mouse down always picks transparent + gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); + mGrabMouseButtonDown = TRUE; + return TRUE; +} + +// static +void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) +{ + LLToolPie::getInstance()->mPick = pick_info; + LLToolPie::getInstance()->pickAndShowMenu(FALSE); +} + +BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + // don't pick transparent so users can't "pay" transparent objects + gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE); + mPieMouseButtonDown = TRUE; + // don't steal focus from UI + return FALSE; +} + +BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); +} +// static +void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) +{ + LLToolPie::getInstance()->mPick = pick_info; + LLToolPie::getInstance()->pickAndShowMenu(TRUE); +} + +// True if you selected an object. +BOOL LLToolPie::pickAndShowMenu(BOOL always_show) +{ + S32 x = mPick.mMousePt.mX; + S32 y = mPick.mMousePt.mY; + MASK mask = mPick.mKeyMask; + if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel(); + if (parcel) + { + LLViewerParcelMgr::getInstance()->selectCollisionParcel(); + if (parcel->getParcelFlag(PF_USE_PASS_LIST) + && !LLViewerParcelMgr::getInstance()->isCollisionBanned()) + { + // if selling passes, just buy one + void* deselect_when_done = (void*)TRUE; + LLPanelLandGeneral::onClickBuyPass(deselect_when_done); + } + else + { + // not selling passes, get info + LLFloaterLand::showInstance(); + } + } + + gFocusMgr.setKeyboardFocus(NULL); + return LLTool::handleMouseDown(x, y, mask); + } + + // didn't click in any UI object, so must have clicked in the world + LLViewerObject *object = mPick.getObject(); + LLViewerObject *parent = NULL; + // if(mPick.mKeyMask == MASK_SHIFT) { @@ -180,838 +180,836 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) } return TRUE; } - // - - if (mPick.mPickType != LLPickInfo::PICK_LAND) - { - LLViewerParcelMgr::getInstance()->deselectLand(); - } - - if (object) - { - parent = object->getRootEdit(); - } - - - BOOL touchable = (object && object->flagHandleTouch()) - || (parent && parent->flagHandleTouch()); - - - // If it's a left-click, and we have a special action, do it. - if (useClickAction(always_show, mask, object, parent)) - { - mClickAction = 0; - if (object && object->getClickAction()) - { - mClickAction = object->getClickAction(); - } - else if (parent && parent->getClickAction()) - { - mClickAction = parent->getClickAction(); - } - - switch(mClickAction) - { - case CLICK_ACTION_TOUCH: - // touch behavior down below... - break; - case CLICK_ACTION_SIT: - if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // agent not already sitting - { + // + + if (mPick.mPickType != LLPickInfo::PICK_LAND) + { + LLViewerParcelMgr::getInstance()->deselectLand(); + } + + if (object) + { + parent = object->getRootEdit(); + } + + + BOOL touchable = (object && object->flagHandleTouch()) + || (parent && parent->flagHandleTouch()); + + + // If it's a left-click, and we have a special action, do it. + if (useClickAction(always_show, mask, object, parent)) + { + mClickAction = 0; + if (object && object->getClickAction()) + { + mClickAction = object->getClickAction(); + } + else if (parent && parent->getClickAction()) + { + mClickAction = parent->getClickAction(); + } + + switch(mClickAction) + { + case CLICK_ACTION_TOUCH: + // touch behavior down below... + break; + case CLICK_ACTION_SIT: + if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // agent not already sitting + { // if(!gSavedSettings.getBOOL("DisableClickSit")) // - handle_sit_or_stand(); - // put focus in world when sitting on an object - gFocusMgr.setKeyboardFocus(NULL); - return TRUE; - } // else nothing (fall through to touch) - - case CLICK_ACTION_PAY: - if ((object && object->flagTakesMoney()) - || (parent && parent->flagTakesMoney())) - { - // pay event goes to object actually clicked on - mClickActionObject = object; - mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); - if (LLSelectMgr::getInstance()->selectGetAllValid()) - { - // call this right away, since we have all the info we need to continue the action - selectionPropertiesReceived(); - } - return TRUE; - } - break; - case CLICK_ACTION_BUY: - mClickActionObject = parent; - mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); - if (LLSelectMgr::getInstance()->selectGetAllValid()) - { - // call this right away, since we have all the info we need to continue the action - selectionPropertiesReceived(); - } - return TRUE; - case CLICK_ACTION_OPEN: - if (parent && parent->allowOpen()) - { - mClickActionObject = parent; - mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); - if (LLSelectMgr::getInstance()->selectGetAllValid()) - { - // call this right away, since we have all the info we need to continue the action - selectionPropertiesReceived(); - } - } - return TRUE; - case CLICK_ACTION_PLAY: - handle_click_action_play(); - return TRUE; - case CLICK_ACTION_OPEN_MEDIA: - // mClickActionObject = object; - handle_click_action_open_media(object); - return TRUE; - default: - // nothing - break; - } - } - - if (!always_show && handle_media_click(mPick)) - { - return FALSE; - } - - // put focus back "in world" - gFocusMgr.setKeyboardFocus(NULL); - - // Switch to grab tool if physical or triggerable - if (object && - !object->isAvatar() && - ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) && - !always_show) - { - gGrabTransientTool = this; - LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); - return LLToolGrab::getInstance()->handleObjectHit( mPick ); - } - - LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon; - if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) - { - LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); - } - - // If left-click never selects or spawns a menu - // Eat the event. - if (!gSavedSettings.getBOOL("LeftClickShowMenu") - && !always_show) - { - // mouse already released - if (!mGrabMouseButtonDown) - { - return TRUE; - } - - while( object && object->isAttachment() && !object->flagHandleTouch()) - { - // don't pick avatar through hud attachment - if (object->isHUDAttachment()) - { - break; - } - object = (LLViewerObject*)object->getParent(); - } - if (object && object == gAgent.getAvatarObject()) - { - // we left clicked on avatar, switch to focus mode - LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); - gViewerWindow->hideCursor(); - LLToolCamera::getInstance()->setMouseCapture(TRUE); - LLToolCamera::getInstance()->pickCallback(mPick); - gAgent.setFocusOnAvatar(TRUE, TRUE); - - return TRUE; - } - // Could be first left-click on nothing - LLFirstUse::useLeftClickNoHit(); - - // Eat the event - return LLTool::handleMouseDown(x, y, mask); - } - - if (!always_show && gAgent.leftButtonGrabbed()) - { - // if the left button is grabbed, don't put up the pie menu - return LLTool::handleMouseDown(x, y, mask); - } - - // Can't ignore children here. - LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); - - // Spawn pie menu - if (mPick.mPickType == LLPickInfo::PICK_LAND) - { - LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); - gMenuHolder->setParcelSelection(selection); - gPieLand->show(x, y, mPieMouseButtonDown); - - // + handle_sit_or_stand(); + // put focus in world when sitting on an object + gFocusMgr.setKeyboardFocus(NULL); + return TRUE; + } // else nothing (fall through to touch) + + case CLICK_ACTION_PAY: + if ((object && object->flagTakesMoney()) + || (parent && parent->flagTakesMoney())) + { + // pay event goes to object actually clicked on + mClickActionObject = object; + mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); + if (LLSelectMgr::getInstance()->selectGetAllValid()) + { + // call this right away, since we have all the info we need to continue the action + selectionPropertiesReceived(); + } + return TRUE; + } + break; + case CLICK_ACTION_BUY: + mClickActionObject = parent; + mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); + if (LLSelectMgr::getInstance()->selectGetAllValid()) + { + // call this right away, since we have all the info we need to continue the action + selectionPropertiesReceived(); + } + return TRUE; + case CLICK_ACTION_OPEN: + if (parent && parent->allowOpen()) + { + mClickActionObject = parent; + mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); + if (LLSelectMgr::getInstance()->selectGetAllValid()) + { + // call this right away, since we have all the info we need to continue the action + selectionPropertiesReceived(); + } + } + return TRUE; + case CLICK_ACTION_PLAY: + handle_click_action_play(); + return TRUE; + case CLICK_ACTION_OPEN_MEDIA: + // mClickActionObject = object; + handle_click_action_open_media(object); + return TRUE; + default: + // nothing + break; + } + } + + if (!always_show && handle_media_click(mPick)) + { + return FALSE; + } + + // put focus back "in world" + gFocusMgr.setKeyboardFocus(NULL); + + // Switch to grab tool if physical or triggerable + if (object && + !object->isAvatar() && + ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) && + !always_show) + { + gGrabTransientTool = this; + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); + return LLToolGrab::getInstance()->handleObjectHit( mPick ); + } + + LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon; + if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) + { + LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); + } + + // If left-click never selects or spawns a menu + // Eat the event. + if (!gSavedSettings.getBOOL("LeftClickShowMenu") + && !always_show) + { + // mouse already released + if (!mGrabMouseButtonDown) + { + return TRUE; + } + + while( object && object->isAttachment() && !object->flagHandleTouch()) + { + // don't pick avatar through hud attachment + if (object->isHUDAttachment()) + { + break; + } + object = (LLViewerObject*)object->getParent(); + } + if (object && object == gAgent.getAvatarObject()) + { + // we left clicked on avatar, switch to focus mode + LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); + gViewerWindow->hideCursor(); + LLToolCamera::getInstance()->setMouseCapture(TRUE); + LLToolCamera::getInstance()->pickCallback(mPick); + gAgent.setFocusOnAvatar(TRUE, TRUE); + + return TRUE; + } + // Could be first left-click on nothing + LLFirstUse::useLeftClickNoHit(); + + // Eat the event + return LLTool::handleMouseDown(x, y, mask); + } + + if (!always_show && gAgent.leftButtonGrabbed()) + { + // if the left button is grabbed, don't put up the pie menu + return LLTool::handleMouseDown(x, y, mask); + } + + // Can't ignore children here. + LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); + + // Spawn pie menu + if (mPick.mPickType == LLPickInfo::PICK_LAND) + { + LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); + gMenuHolder->setParcelSelection(selection); + gPieLand->show(x, y, mPieMouseButtonDown); + if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { // - // VEFFECT: ShowPie - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(mPick.mPosGlobal); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - effectp->setDuration(0.25f); + // VEFFECT: ShowPie + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); + effectp->setPositionGlobal(mPick.mPosGlobal); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + effectp->setDuration(0.25f); // } // - } - else if (mPick.mObjectID == gAgent.getID() ) - { - if(!gPieSelf) - { - //either at very early startup stage or at late quitting stage, - //this event is ignored. - return TRUE ; - } - - gPieSelf->show(x, y, mPieMouseButtonDown); - } - else if (object) - { - gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection()); - - if (object->isAvatar() - || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner())) - { - // Find the attachment's avatar - while( object && object->isAttachment()) - { - object = (LLViewerObject*)object->getParent(); - } - - // Object is an avatar, so check for mute by id. - LLVOAvatar* avatar = (LLVOAvatar*)object; - std::string name = avatar->getFullname(); - if (LLMuteList::getInstance()->isMuted(avatar->getID(), name)) - { - gMenuHolder->childSetText("Avatar Mute", std::string("Unmute")); // *TODO:Translate - //gMutePieMenu->setLabel("Unmute"); - } - else - { - gMenuHolder->childSetText("Avatar Mute", std::string("Mute")); // *TODO:Translate - //gMutePieMenu->setLabel("Mute"); - } - - gPieAvatar->show(x, y, mPieMouseButtonDown); - } - else if (object->isAttachment()) - { - gPieAttachment->show(x, y, mPieMouseButtonDown); - } - else - { - // BUG: What about chatting child objects? - std::string name; - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (node) - { - name = node->mName; - } - if (LLMuteList::getInstance()->isMuted(object->getID(), name)) - { - gMenuHolder->childSetText("Object Mute", std::string("Unmute")); // *TODO:Translate - //gMuteObjectPieMenu->setLabel("Unmute"); - } - else - { - gMenuHolder->childSetText("Object Mute", std::string("Mute")); // *TODO:Translate - //gMuteObjectPieMenu->setLabel("Mute"); - } - - gPieObject->show(x, y, mPieMouseButtonDown); - - // + } + else if (mPick.mObjectID == gAgent.getID() ) + { + if(!gPieSelf) + { + //either at very early startup stage or at late quitting stage, + //this event is ignored. + return TRUE ; + } + + gPieSelf->show(x, y, mPieMouseButtonDown); + } + else if (object) + { + gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection()); + + if (object->isAvatar() + || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner())) + { + // Find the attachment's avatar + while( object && object->isAttachment()) + { + object = (LLViewerObject*)object->getParent(); + } + + // Object is an avatar, so check for mute by id. + LLVOAvatar* avatar = (LLVOAvatar*)object; + std::string name = avatar->getFullname(); + if (LLMuteList::getInstance()->isMuted(avatar->getID(), name)) + { + gMenuHolder->childSetText("Avatar Mute", std::string("Unmute")); // *TODO:Translate + //gMutePieMenu->setLabel("Unmute"); + } + else + { + gMenuHolder->childSetText("Avatar Mute", std::string("Mute")); // *TODO:Translate + //gMutePieMenu->setLabel("Mute"); + } + + gPieAvatar->show(x, y, mPieMouseButtonDown); + } + else if (object->isAttachment()) + { + gPieAttachment->show(x, y, mPieMouseButtonDown); + } + else + { + // BUG: What about chatting child objects? + std::string name; + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node) + { + name = node->mName; + } + if (LLMuteList::getInstance()->isMuted(object->getID(), name)) + { + gMenuHolder->childSetText("Object Mute", std::string("Unmute")); // *TODO:Translate + //gMuteObjectPieMenu->setLabel("Unmute"); + } + else + { + gMenuHolder->childSetText("Object Mute", std::string("Mute")); // *TODO:Translate + //gMuteObjectPieMenu->setLabel("Mute"); + } + + gPieObject->show(x, y, mPieMouseButtonDown); + if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { - // - // VEFFECT: ShowPie object - // Don't show when you click on someone else, it freaks them - // out. - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(mPick.mPosGlobal); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - effectp->setDuration(0.25f); - // + // + // VEFFECT: ShowPie object + // Don't show when you click on someone else, it freaks them + // out. + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); + effectp->setPositionGlobal(mPick.mPosGlobal); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + effectp->setDuration(0.25f); + // } // - } - } - - if (always_show) - { - // ignore return value - LLTool::handleRightMouseDown(x, y, mask); - } - else - { - // ignore return value - LLTool::handleMouseDown(x, y, mask); - } - - // We handled the event. - return TRUE; -} - -BOOL LLToolPie::useClickAction(BOOL always_show, - MASK mask, - LLViewerObject* object, - LLViewerObject* parent) -{ - return !always_show - && mask == MASK_NONE - && object - && !object->isAttachment() - && LLPrimitive::isPrimitive(object->getPCode()) - && (object->getClickAction() - || parent->getClickAction()); - -} - -U8 final_click_action(LLViewerObject* obj) -{ - if (!obj) return CLICK_ACTION_NONE; - if (obj->isAttachment()) return CLICK_ACTION_NONE; - - U8 click_action = CLICK_ACTION_TOUCH; - LLViewerObject* parent = obj->getRootEdit(); - if (obj->getClickAction() - || (parent && parent->getClickAction())) - { - if (obj->getClickAction()) - { - click_action = obj->getClickAction(); - } - else if (parent && parent->getClickAction()) - { - click_action = parent->getClickAction(); - } - } - return click_action; -} - -ECursorType cursor_from_object(LLViewerObject* object) -{ - LLViewerObject* parent = NULL; - if (object) - { - parent = object->getRootEdit(); - } - U8 click_action = final_click_action(object); - ECursorType cursor = UI_CURSOR_ARROW; - switch(click_action) - { - case CLICK_ACTION_SIT: - if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // not already sitting? - { - cursor = UI_CURSOR_TOOLSIT; - } - break; - case CLICK_ACTION_BUY: - cursor = UI_CURSOR_TOOLBUY; - break; - case CLICK_ACTION_OPEN: - // Open always opens the parent. - if (parent && parent->allowOpen()) - { - cursor = UI_CURSOR_TOOLOPEN; - } - break; - case CLICK_ACTION_PAY: - if ((object && object->flagTakesMoney()) - || (parent && parent->flagTakesMoney())) - { - cursor = UI_CURSOR_TOOLPAY; - } - break; - case CLICK_ACTION_PLAY: - case CLICK_ACTION_OPEN_MEDIA: - cursor = cursor_from_parcel_media(click_action); - break; - default: - break; - } - return cursor; -} - -void LLToolPie::resetSelection() -{ - mLeftClickSelection = NULL; - mClickActionObject = NULL; - mClickAction = 0; -} - -// When we get object properties after left-clicking on an object -// with left-click = buy, if it's the same object, do the buy. - -// static -void LLToolPie::selectionPropertiesReceived() -{ - // Make sure all data has been received. - // This function will be called repeatedly as the data comes in. - if (!LLSelectMgr::getInstance()->selectGetAllValid()) - { - return; - } - - LLObjectSelection* selection = LLToolPie::getInstance()->getLeftClickSelection(); - if (selection) - { - LLViewerObject* selected_object = selection->getPrimaryObject(); - // since we don't currently have a way to lock a selection, it could have changed - // after we initially clicked on the object - if (selected_object == LLToolPie::getInstance()->getClickActionObject()) - { - U8 click_action = LLToolPie::getInstance()->getClickAction(); - switch (click_action) - { - case CLICK_ACTION_BUY: - handle_buy(NULL); - break; - case CLICK_ACTION_PAY: - handle_give_money_dialog(); - break; - case CLICK_ACTION_OPEN: - handle_object_open(); - break; - default: - break; - } - } - } - LLToolPie::getInstance()->resetSelection(); -} - -BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) -{ - /* - // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag - // gets started. - const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() ); - const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; - // ...normal modes can only yaw - if (x < ROTATE_H_MARGIN) - { - gAgent.yaw(rotate_angle); - mMouseOutsideSlop = TRUE; - } - else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) - { - gAgent.yaw(-rotate_angle); - mMouseOutsideSlop = TRUE; - } - */ - - - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - - LLViewerObject *object = NULL; - LLViewerObject *parent = NULL; - object = gViewerWindow->getHoverPick().getObject(); - - if (object) - { - parent = object->getRootEdit(); - - if (object && useClickAction(FALSE, mask, object, parent)) - { - ECursorType cursor = cursor_from_object(object); - gViewerWindow->getWindow()->setCursor(cursor); - } - else if (handle_media_hover(gViewerWindow->getHoverPick())) - { - // cursor set by media object - } - else if ((object && !object->isAvatar() && object->usePhysics()) - || (parent && !parent->isAvatar() && parent->usePhysics())) - { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); - } - else if ( (object && object->flagHandleTouch()) - || (parent && parent->flagHandleTouch())) - { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND); - } - } - else - { - // We need to clear media hover flag - if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) - { - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); - } - - } - - return TRUE; -} - -BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) -{ - LLViewerObject* obj = mPick.getObject(); - U8 click_action = final_click_action(obj); - if (click_action != CLICK_ACTION_NONE) - { - switch(click_action) - { - case CLICK_ACTION_BUY: - case CLICK_ACTION_PAY: - case CLICK_ACTION_OPEN: - // Because these actions open UI dialogs, we won't change - // the cursor again until the next hover and GL pick over - // the world. Keep the cursor an arrow, assuming that - // after the user moves off the UI, they won't be on the - // same object anymore. - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - // Make sure the hover-picked object is ignored. - gHoverView->resetLastHoverObject(); - break; - default: - break; - } - } - mGrabMouseButtonDown = FALSE; - LLToolMgr::getInstance()->clearTransientTool(); - gAgent.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on - return LLTool::handleMouseUp(x, y, mask); -} - -BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask) -{ - mPieMouseButtonDown = FALSE; - LLToolMgr::getInstance()->clearTransientTool(); - return LLTool::handleRightMouseUp(x, y, mask); -} - - -BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - if (gDebugClicks) - { - llinfos << "LLToolPie handleDoubleClick (becoming mouseDown)" << llendl; - } - - if (gSavedSettings.getBOOL("DoubleClickAutoPilot") || gSavedSettings.getBOOL("DoubleClickTeleport")) - { - if (mPick.mPickType == LLPickInfo::PICK_LAND - && !mPick.mPosGlobal.isExactlyZero()) - { - handle_go_to(); - return TRUE; - } - else if (mPick.mObjectID.notNull() - && !mPick.mPosGlobal.isExactlyZero()) - { - // Hit an object - // Do not go to attachments... - if (!mPick.getObject()->isHUDAttachment()) - { - // HACK: Call the last hit position the point we hit on the object - //gLastHitPosGlobal += gLastHitObjectOffset; - handle_go_to(); - return TRUE; - } - } - } else - /* code added to support double click teleports */ - if (gSavedSettings.getBOOL("DoubleClickTeleport")) - { - LLViewerObject* objp = mPick.getObject(); - LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL; - bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment(); - bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND; - bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero(); - bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch()); - bool has_click_action = final_click_action(objp); - if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action))) - { - LLVector3d pos = mPick.mPosGlobal; - pos.mdV[VZ] += gAgent.getAvatarObject()->getPelvisToFoot(); - gAgent.teleportViaLocationLookAt(pos); - return TRUE; - } - } - - return FALSE; - - /* JC - don't do go-there, because then double-clicking on physical - objects gets you into trouble. - - // If double-click on object or land, go there. - LLViewerObject *object = gViewerWindow->getLastPick().getObject(); - if (object) - { - if (object->isAvatar()) - { - LLFloaterAvatarInfo::showFromAvatar(object->getID()); - } - else - { - handle_go_to(NULL); - } - } - else if (!gLastHitPosGlobal.isExactlyZero()) - { - handle_go_to(NULL); - } - - return TRUE; - */ -} - - -void LLToolPie::handleDeselect() -{ - if( hasMouseCapture() ) - { - setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly - } - // remove temporary selection for pie menu - LLSelectMgr::getInstance()->validateSelection(); -} - -LLTool* LLToolPie::getOverrideTool(MASK mask) -{ - if (mask == MASK_CONTROL) - { - return LLToolGrab::getInstance(); - } - else if (mask == (MASK_CONTROL | MASK_SHIFT)) - { - return LLToolGrab::getInstance(); - } - - return LLTool::getOverrideTool(mask); -} - -void LLToolPie::stopEditing() -{ - if( hasMouseCapture() ) - { - setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly - } -} - -void LLToolPie::onMouseCaptureLost() -{ - mMouseOutsideSlop = FALSE; -} - - -// true if x,y outside small box around start_x,start_y -BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y) -{ - S32 dx = x - start_x; - S32 dy = y - start_y; - - return (dx <= -2 || 2 <= dx || dy <= -2 || 2 <= dy); -} - - -void LLToolPie::render() -{ - return; -} - -static void handle_click_action_play() -{ - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!parcel) return; - - LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); - switch(status) - { - case LLViewerMediaImpl::MEDIA_PLAYING: - LLViewerParcelMedia::pause(); - break; - - case LLViewerMediaImpl::MEDIA_PAUSED: - LLViewerParcelMedia::start(); - break; - - default: - LLViewerParcelMedia::play(parcel); - break; - } -} - -static bool handle_media_click(const LLPickInfo& pick) -{ - //FIXME: how do we handle object in different parcel than us? - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - LLPointer objectp = pick.getObject(); - - - if (!parcel || - objectp.isNull() || - pick.mObjectFace < 0 || - pick.mObjectFace >= objectp->getNumTEs()) - { - LLSelectMgr::getInstance()->deselect(); - LLViewerMediaFocus::getInstance()->clearFocus(); - - return false; - } - - - - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - // is media playing on this face? - const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); - - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); - if (tep - && media_impl.notNull() - && media_impl->hasMedia() - && gSavedSettings.getBOOL("MediaOnAPrimUI")) - { - LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); - if (! selection->contains(pick.getObject(), pick.mObjectFace)) - { - LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); - } - else - { - media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY); - media_impl->mouseCapture(); // the mouse-up will happen when capture is lost - } - - return true; - } - - LLSelectMgr::getInstance()->deselect(); - LLViewerMediaFocus::getInstance()->clearFocus(); - - return false; -} - -static bool handle_media_hover(const LLPickInfo& pick) -{ - //FIXME: how do we handle object in different parcel than us? - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!parcel) return false; - - LLPointer objectp = pick.getObject(); - - // Early out cases. Must clear mouse over media focus flag - // did not hit an object or did not hit a valid face - if ( objectp.isNull() || - pick.mObjectFace < 0 || - pick.mObjectFace >= objectp->getNumTEs() ) - { - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); - return false; - } - - - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - // is media playing on this face? - const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); - if (tep - && media_impl.notNull() - && media_impl->hasMedia() - && gSavedSettings.getBOOL("MediaOnAPrimUI")) - { - if(LLViewerMediaFocus::getInstance()->getFocus()) - { - media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY); - } - - // Set mouse over flag if unset - if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag()) - { - LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace); - LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl); - LLViewerMediaFocus::getInstance()->setPickInfo(pick); - } - - return true; - } - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); - - return false; -} - - -static void handle_click_action_open_media(LLPointer objectp) -{ - //FIXME: how do we handle object in different parcel than us? - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!parcel) return; - - // did we hit an object? - if (objectp.isNull()) return; - - // did we hit a valid face on the object? - S32 face = LLToolPie::getInstance()->getPick().mObjectFace; - if( face < 0 || face >= objectp->getNumTEs() ) return; - - // is media playing on this face? - if (LLViewerMedia::getMediaImplFromTextureID(objectp->getTE(face)->getID()) != NULL) - { - handle_click_action_play(); - return; - } - - std::string media_url = std::string ( parcel->getMediaURL () ); - std::string media_type = std::string ( parcel->getMediaType() ); - LLStringUtil::trim(media_url); - - // Get the scheme, see if that is handled as well. - LLURI uri(media_url); - std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http"; - - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - LLWeb::loadURL(media_url); -} - -static ECursorType cursor_from_parcel_media(U8 click_action) -{ - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - //FIXME: how do we handle object in different parcel than us? - ECursorType open_cursor = UI_CURSOR_ARROW; - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!parcel) return open_cursor; - - std::string media_url = std::string ( parcel->getMediaURL () ); - std::string media_type = std::string ( parcel->getMediaType() ); - LLStringUtil::trim(media_url); - - open_cursor = UI_CURSOR_TOOLMEDIAOPEN; - - LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); - switch(status) - { - case LLViewerMediaImpl::MEDIA_PLAYING: - return click_action == CLICK_ACTION_PLAY ? UI_CURSOR_TOOLPAUSE : open_cursor; - default: - return UI_CURSOR_TOOLPLAY; - } -} + } + } + + if (always_show) + { + // ignore return value + LLTool::handleRightMouseDown(x, y, mask); + } + else + { + // ignore return value + LLTool::handleMouseDown(x, y, mask); + } + + // We handled the event. + return TRUE; +} + +BOOL LLToolPie::useClickAction(BOOL always_show, + MASK mask, + LLViewerObject* object, + LLViewerObject* parent) +{ + return !always_show + && mask == MASK_NONE + && object + && !object->isAttachment() + && LLPrimitive::isPrimitive(object->getPCode()) + && (object->getClickAction() + || parent->getClickAction()); + +} + +U8 final_click_action(LLViewerObject* obj) +{ + if (!obj) return CLICK_ACTION_NONE; + if (obj->isAttachment()) return CLICK_ACTION_NONE; + + U8 click_action = CLICK_ACTION_TOUCH; + LLViewerObject* parent = obj->getRootEdit(); + if (obj->getClickAction() + || (parent && parent->getClickAction())) + { + if (obj->getClickAction()) + { + click_action = obj->getClickAction(); + } + else if (parent && parent->getClickAction()) + { + click_action = parent->getClickAction(); + } + } + return click_action; +} + +ECursorType cursor_from_object(LLViewerObject* object) +{ + LLViewerObject* parent = NULL; + if (object) + { + parent = object->getRootEdit(); + } + U8 click_action = final_click_action(object); + ECursorType cursor = UI_CURSOR_ARROW; + switch(click_action) + { + case CLICK_ACTION_SIT: + if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // not already sitting? + { + cursor = UI_CURSOR_TOOLSIT; + } + break; + case CLICK_ACTION_BUY: + cursor = UI_CURSOR_TOOLBUY; + break; + case CLICK_ACTION_OPEN: + // Open always opens the parent. + if (parent && parent->allowOpen()) + { + cursor = UI_CURSOR_TOOLOPEN; + } + break; + case CLICK_ACTION_PAY: + if ((object && object->flagTakesMoney()) + || (parent && parent->flagTakesMoney())) + { + cursor = UI_CURSOR_TOOLPAY; + } + break; + case CLICK_ACTION_PLAY: + case CLICK_ACTION_OPEN_MEDIA: + cursor = cursor_from_parcel_media(click_action); + break; + default: + break; + } + return cursor; +} + +void LLToolPie::resetSelection() +{ + mLeftClickSelection = NULL; + mClickActionObject = NULL; + mClickAction = 0; +} + +// When we get object properties after left-clicking on an object +// with left-click = buy, if it's the same object, do the buy. + +// static +void LLToolPie::selectionPropertiesReceived() +{ + // Make sure all data has been received. + // This function will be called repeatedly as the data comes in. + if (!LLSelectMgr::getInstance()->selectGetAllValid()) + { + return; + } + + LLObjectSelection* selection = LLToolPie::getInstance()->getLeftClickSelection(); + if (selection) + { + LLViewerObject* selected_object = selection->getPrimaryObject(); + // since we don't currently have a way to lock a selection, it could have changed + // after we initially clicked on the object + if (selected_object == LLToolPie::getInstance()->getClickActionObject()) + { + U8 click_action = LLToolPie::getInstance()->getClickAction(); + switch (click_action) + { + case CLICK_ACTION_BUY: + handle_buy(NULL); + break; + case CLICK_ACTION_PAY: + handle_give_money_dialog(); + break; + case CLICK_ACTION_OPEN: + handle_object_open(); + break; + default: + break; + } + } + } + LLToolPie::getInstance()->resetSelection(); +} + +BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) +{ + /* + // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag + // gets started. + const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() ); + const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; + const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; + // ...normal modes can only yaw + if (x < ROTATE_H_MARGIN) + { + gAgent.yaw(rotate_angle); + mMouseOutsideSlop = TRUE; + } + else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) + { + gAgent.yaw(-rotate_angle); + mMouseOutsideSlop = TRUE; + } + */ + + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + + LLViewerObject *object = NULL; + LLViewerObject *parent = NULL; + object = gViewerWindow->getHoverPick().getObject(); + + if (object) + { + parent = object->getRootEdit(); + + if (object && useClickAction(FALSE, mask, object, parent)) + { + ECursorType cursor = cursor_from_object(object); + gViewerWindow->getWindow()->setCursor(cursor); + } + else if (handle_media_hover(gViewerWindow->getHoverPick())) + { + // cursor set by media object + } + else if ((object && !object->isAvatar() && object->usePhysics()) + || (parent && !parent->isAvatar() && parent->usePhysics())) + { + gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); + } + else if ( (object && object->flagHandleTouch()) + || (parent && parent->flagHandleTouch())) + { + gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND); + } + } + else + { + // We need to clear media hover flag + if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) + { + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + } + + } + + return TRUE; +} + +BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) +{ + LLViewerObject* obj = mPick.getObject(); + U8 click_action = final_click_action(obj); + if (click_action != CLICK_ACTION_NONE) + { + switch(click_action) + { + case CLICK_ACTION_BUY: + case CLICK_ACTION_PAY: + case CLICK_ACTION_OPEN: + // Because these actions open UI dialogs, we won't change + // the cursor again until the next hover and GL pick over + // the world. Keep the cursor an arrow, assuming that + // after the user moves off the UI, they won't be on the + // same object anymore. + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + // Make sure the hover-picked object is ignored. + gHoverView->resetLastHoverObject(); + break; + default: + break; + } + } + mGrabMouseButtonDown = FALSE; + LLToolMgr::getInstance()->clearTransientTool(); + gAgent.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on + return LLTool::handleMouseUp(x, y, mask); +} + +BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + mPieMouseButtonDown = FALSE; + LLToolMgr::getInstance()->clearTransientTool(); + return LLTool::handleRightMouseUp(x, y, mask); +} + + +BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if (gDebugClicks) + { + llinfos << "LLToolPie handleDoubleClick (becoming mouseDown)" << llendl; + } + + if (gSavedSettings.getBOOL("DoubleClickAutoPilot") || gSavedSettings.getBOOL("DoubleClickTeleport")) + { + if (mPick.mPickType == LLPickInfo::PICK_LAND + && !mPick.mPosGlobal.isExactlyZero()) + { + handle_go_to(); + return TRUE; + } + else if (mPick.mObjectID.notNull() + && !mPick.mPosGlobal.isExactlyZero()) + { + // Hit an object + // Do not go to attachments... + if (!mPick.getObject()->isHUDAttachment()) + { + // HACK: Call the last hit position the point we hit on the object + //gLastHitPosGlobal += gLastHitObjectOffset; + handle_go_to(); + return TRUE; + } + } + } else + /* code added to support double click teleports */ + if (gSavedSettings.getBOOL("DoubleClickTeleport")) + { + LLViewerObject* objp = mPick.getObject(); + LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL; + bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment(); + bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND; + bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero(); + bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch()); + bool has_click_action = final_click_action(objp); + if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action))) + { + LLVector3d pos = mPick.mPosGlobal; + pos.mdV[VZ] += gAgent.getAvatarObject()->getPelvisToFoot(); + gAgent.teleportViaLocationLookAt(pos); + return TRUE; + } + } + + return FALSE; + + /* JC - don't do go-there, because then double-clicking on physical + objects gets you into trouble. + + // If double-click on object or land, go there. + LLViewerObject *object = gViewerWindow->getLastPick().getObject(); + if (object) + { + if (object->isAvatar()) + { + LLFloaterAvatarInfo::showFromAvatar(object->getID()); + } + else + { + handle_go_to(NULL); + } + } + else if (!gLastHitPosGlobal.isExactlyZero()) + { + handle_go_to(NULL); + } + + return TRUE; + */ +} + + +void LLToolPie::handleDeselect() +{ + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly + } + // remove temporary selection for pie menu + LLSelectMgr::getInstance()->validateSelection(); +} + +LLTool* LLToolPie::getOverrideTool(MASK mask) +{ + if (mask == MASK_CONTROL) + { + return LLToolGrab::getInstance(); + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return LLToolGrab::getInstance(); + } + + return LLTool::getOverrideTool(mask); +} + +void LLToolPie::stopEditing() +{ + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly + } +} + +void LLToolPie::onMouseCaptureLost() +{ + mMouseOutsideSlop = FALSE; +} + + +// true if x,y outside small box around start_x,start_y +BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y) +{ + S32 dx = x - start_x; + S32 dy = y - start_y; + + return (dx <= -2 || 2 <= dx || dy <= -2 || 2 <= dy); +} + + +void LLToolPie::render() +{ + return; +} + +static void handle_click_action_play() +{ + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return; + + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); + switch(status) + { + case LLViewerMediaImpl::MEDIA_PLAYING: + LLViewerParcelMedia::pause(); + break; + + case LLViewerMediaImpl::MEDIA_PAUSED: + LLViewerParcelMedia::start(); + break; + + default: + LLViewerParcelMedia::play(parcel); + break; + } +} + +static bool handle_media_click(const LLPickInfo& pick) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + LLPointer objectp = pick.getObject(); + + + if (!parcel || + objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs()) + { + LLSelectMgr::getInstance()->deselect(); + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; + } + + + + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + // is media playing on this face? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); + if (tep + && media_impl.notNull() + && media_impl->hasMedia() + && gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); + if (! selection->contains(pick.getObject(), pick.mObjectFace)) + { + LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); + } + else + { + media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY); + media_impl->mouseCapture(); // the mouse-up will happen when capture is lost + } + + return true; + } + + LLSelectMgr::getInstance()->deselect(); + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; +} + +static bool handle_media_hover(const LLPickInfo& pick) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return false; + + LLPointer objectp = pick.getObject(); + + // Early out cases. Must clear mouse over media focus flag + // did not hit an object or did not hit a valid face + if ( objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs() ) + { + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + return false; + } + + + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + // is media playing on this face? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); + if (tep + && media_impl.notNull() + && media_impl->hasMedia() + && gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + if(LLViewerMediaFocus::getInstance()->getFocus()) + { + media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY); + } + + // Set mouse over flag if unset + if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag()) + { + LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace); + LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl); + LLViewerMediaFocus::getInstance()->setPickInfo(pick); + } + + return true; + } + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + + return false; +} + + +static void handle_click_action_open_media(LLPointer objectp) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return; + + // did we hit an object? + if (objectp.isNull()) return; + + // did we hit a valid face on the object? + S32 face = LLToolPie::getInstance()->getPick().mObjectFace; + if( face < 0 || face >= objectp->getNumTEs() ) return; + + // is media playing on this face? + if (LLViewerMedia::getMediaImplFromTextureID(objectp->getTE(face)->getID()) != NULL) + { + handle_click_action_play(); + return; + } + + std::string media_url = std::string ( parcel->getMediaURL () ); + std::string media_type = std::string ( parcel->getMediaType() ); + LLStringUtil::trim(media_url); + + // Get the scheme, see if that is handled as well. + LLURI uri(media_url); + std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http"; + + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + LLWeb::loadURL(media_url); +} + +static ECursorType cursor_from_parcel_media(U8 click_action) +{ + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + //FIXME: how do we handle object in different parcel than us? + ECursorType open_cursor = UI_CURSOR_ARROW; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return open_cursor; + + std::string media_url = std::string ( parcel->getMediaURL () ); + std::string media_type = std::string ( parcel->getMediaType() ); + LLStringUtil::trim(media_url); + + open_cursor = UI_CURSOR_TOOLMEDIAOPEN; + + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); + switch(status) + { + case LLViewerMediaImpl::MEDIA_PLAYING: + return click_action == CLICK_ACTION_PLAY ? UI_CURSOR_TOOLPAUSE : open_cursor; + default: + return UI_CURSOR_TOOLPLAY; + } +} diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 8ac40c19a..78250669b 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -65,6 +65,11 @@ #include "llviewercamera.h" #include "llviewerstats.h" +// +#include "llparcel.h" // always rez +#include "llviewerparcelmgr.h" // always rez +// + const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f); //static @@ -233,7 +238,18 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + + // Alway rez objects as land group if available. + if (gSavedSettings.getBOOL("AscentAlwaysRezInGroup")) + { + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(gAgent.isInGroup(parcel->getGroupID())) + gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getGroupID()); + else if(gAgent.isInGroup(parcel->getOwnerID())) + gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getOwnerID()); + else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + } else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU8Fast(_PREHASH_Material, material); diff --git a/indra/newview/lluserauth.cpp b/indra/newview/lluserauth.cpp index f8d85f0cc..9a7457a97 100644 --- a/indra/newview/lluserauth.cpp +++ b/indra/newview/lluserauth.cpp @@ -147,18 +147,10 @@ void LLUserAuth::authenticate( XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("SpecifiedChannel").c_str(), 0); // XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0); - // - if(gSavedSettings.getBOOL("SpecifyMAC")) - XMLRPC_VectorAppendString(params, "mac", gSavedSettings.getString("SpecifiedMAC").c_str(), 0); - else - // + XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0); // A bit of security through obscurity: id0 is volume_serial - // - if(gSavedSettings.getBOOL("SpecifyID0")) - XMLRPC_VectorAppendString(params, "id0", gSavedSettings.getString("SpecifiedID0").c_str(), 0); - else - // + XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0); if (skip_optional) { @@ -257,18 +249,12 @@ void LLUserAuth::authenticate( XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("SpecifiedChannel").c_str(), 0); // XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0); - // - if(gSavedSettings.getBOOL("SpecifyMAC")) - XMLRPC_VectorAppendString(params, "mac", gSavedSettings.getString("SpecifiedMAC").c_str(), 0); - else - // + XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0); // A bit of security through obscurity: id0 is volume_serial - // - if(gSavedSettings.getBOOL("SpecifyID0")) - XMLRPC_VectorAppendString(params, "id0", gSavedSettings.getString("SpecifiedID0").c_str(), 0); - else - // + // ^^^^^^^^^^^^^^^^^^^^ + // you fucking idiot - charbl + XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0); if (skip_optional) { diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 9cab44af7..9c9a3f706 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -557,6 +557,7 @@ void settings_setup_listeners() gSavedSettings.getControl("UserLogFile")->getSignal()->connect(boost::bind(&handleLogFileChanged, _1)); gSavedSettings.getControl("RenderHideGroupTitle")->getSignal()->connect(boost::bind(handleHideGroupTitleChanged, _1)); gSavedSettings.getControl("EffectColor")->getSignal()->connect(boost::bind(handleEffectColorChanged, _1)); + gSavedPerAccountSettings.getControl("EffectColor")->getSignal()->connect(boost::bind(handleEffectColorChanged, _1)); gSavedSettings.getControl("VectorizePerfTest")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1)); gSavedSettings.getControl("VectorizeEnable")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1)); gSavedSettings.getControl("VectorizeProcessor")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1)); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 89272b844..73300c709 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1,4 +1,3 @@ - /** * @file llviewermenu.cpp * @brief Builds menus out of items. @@ -44,6 +43,7 @@ #include "llaudioengine.h" #include "indra_constants.h" #include "llassetstorage.h" + #include "llchat.h" #include "llfeaturemanager.h" #include "llfocusmgr.h" @@ -59,6 +59,7 @@ #include "message.h" #include "raytrace.h" #include "llsdserialize.h" +#include "llsdutil.h" // #include "lllocalinventory.h" #include "llfloaterimport.h" @@ -82,6 +83,7 @@ #include "llclipboard.h" #include "llcompilequeue.h" #include "llconsole.h" +#include "llcontrol.h" #include "llviewercontrol.h" #include "lldebugview.h" #include "lldir.h" @@ -91,6 +93,7 @@ #include "llface.h" #include "llfirstuse.h" #include "llfloater.h" + #include "llfloaterabout.h" #include "llfloaterbuycurrency.h" #include "llfloateractivespeakers.h" @@ -120,6 +123,7 @@ #include "llfloatergroupinfo.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" + #include "llfloaterhtmlcurrency.h" #include "llfloatermediabrowser.h" // gViewerHtmlHelp #include "llfloaterhtmlsimple.h" @@ -129,6 +133,7 @@ #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" + #include "llfloatermute.h" #include "llfloateropenobject.h" #include "llfloaterpermissionsmgr.h" @@ -139,6 +144,7 @@ #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" #include "llfloatersettingsdebug.h" + #include "llfloaterenvsettings.h" #include "llfloaterstats.h" #include "llfloaterteleport.h" @@ -174,7 +180,10 @@ #include "llmutelist.h" #include "llnotify.h" #include "llpanelobject.h" + #include "llparcel.h" + + #include "llprimitive.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -241,6 +250,8 @@ #include "llfloaterexportregion.h" // +#include "scriptcounter.h" + using namespace LLVOAvatarDefines; void init_client_menu(LLMenuGL* menu); void init_server_menu(LLMenuGL* menu); @@ -255,6 +266,11 @@ void init_debug_baked_texture_menu(LLMenuGL* menu); BOOL enable_land_build(void*); BOOL enable_object_build(void*); + + + + + LLVOAvatar* find_avatar_from_object( LLViewerObject* object ); LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ); @@ -304,6 +320,7 @@ LLPieMenu* gDetachPieMenu = NULL; LLPieMenu* gDetachScreenPieMenu = NULL; LLPieMenu* gDetachBodyPartPieMenus[8]; +LLMenuItemCallGL* gFakeAway = NULL; LLMenuItemCallGL* gAFKMenu = NULL; LLMenuItemCallGL* gBusyMenu = NULL; @@ -318,6 +335,7 @@ void handle_leave_group(void *); void handle_compress_image(void*); BOOL enable_save_as(void *); + // Edit menu void handle_dump_group_info(void *); void handle_dump_capabilities_info(void *); @@ -329,6 +347,8 @@ void handle_region_dump_settings(void*); void handle_region_dump_temp_asset_data(void*); void handle_region_clear_temp_asset_data(void*); + + // Object pie menu BOOL sitting_on_selection(); @@ -401,6 +421,10 @@ void handle_god_mode(void*); void handle_leave_god_mode(void*); // +void handle_fake_away_status(void*); +void handle_force_ground_sit(void*); +void handle_phantom_avatar(void*); +void handle_hide_typing_notification(void*); void handle_close_all_notifications(void*); void handle_reopen_with_hex_editor(void*); void handle_open_message_log(void*); @@ -509,6 +533,14 @@ void handle_grab_texture(void*); BOOL enable_grab_texture(void*); void handle_dump_region_object_cache(void*); + + + + + + + + BOOL menu_ui_enabled(void *user_data); BOOL menu_check_control( void* user_data); void menu_toggle_variable( void* user_data ); @@ -751,20 +783,17 @@ void init_client_menu(LLMenuGL* menu) // { LLMenuGL* sub = NULL; - sub = new LLMenuGL("Useful Features"); + sub = new LLMenuGL("Ascent"); + sub->append(new LLMenuItemCallGL( "Fake Away Status", &handle_fake_away_status, NULL)); + sub->append(new LLMenuItemCallGL( "Force Ground Sit", &handle_force_ground_sit, NULL)); + sub->append(new LLMenuItemCallGL( "Phantom Avatar", &handle_phantom_avatar, NULL)); + sub->append(new LLMenuItemCallGL( "Toggle IM Typing Notification", &handle_hide_typing_notification, NULL)); sub->append(new LLMenuItemCallGL( "Close All Dialogs", &handle_close_all_notifications, NULL, NULL, 'D', MASK_CONTROL | MASK_ALT | MASK_SHIFT)); - sub->append(new LLMenuItemCallGL( "Reopen with Hex Editor", - &handle_reopen_with_hex_editor, NULL)); - sub->append(new LLMenuItemCallGL( "Message Log", &handle_open_message_log, NULL)); sub->append(new LLMenuItemCallGL( "Message Builder", &handle_open_message_builder, NULL)); - sub->append(new LLMenuItemCallGL( "Local Assets...", - &handle_local_assets, NULL)); - sub->append(new LLMenuItemCallGL( "VFS Explorer", - &handle_vfs_explorer, NULL)); sub->append(new LLMenuItemCallGL( "Sound Explorer", &handle_sounds_explorer, NULL)); sub->append(new LLMenuItemCallGL( "Asset Blacklist", @@ -2263,27 +2292,6 @@ class LLObjectCopyUUID : public view_listener_t } }; -class LLObjectEnableSaveAs : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -class LLObjectSaveAs : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLFloaterExport* floater = new LLFloaterExport(); - floater->center(); - return true; - } -}; - class LLObjectEnableImport : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2342,6 +2350,81 @@ class LLObjectImport : public view_listener_t } }; +class LLObjectData : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if(object) + { + LLVector3 vPos = object->getPosition(); + LLQuaternion rRot = object->getRotation(); + + F32 posX = vPos.mV[0]; + F32 posY = vPos.mV[1]; + F32 posZ = vPos.mV[2]; + + F32 rotX = rRot.mQ[0]; + F32 rotY = rRot.mQ[1]; + F32 rotZ = rRot.mQ[2]; + F32 rotR = rRot.mQ[3]; + + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = llformat("LSL Helper:\nPosition: <%f, %f, %f>\nRotation: <%f, %f, %f, %f>", posX, posY, posZ, rotX, rotY, rotZ, rotR); + LLFloaterChat::addChat(chat); + } + + return true; + } +}; + +class LLObjectMeasure : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if(object) + { + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + + if (LLAgent::exlStartMeasurePoint.isExactlyZero()) + { + LLAgent::exlStartMeasurePoint = object->getPosition(); + + chat.mText = llformat("Start point set"); + LLFloaterChat::addChat(chat); + } + else if (LLAgent::exlEndMeasurePoint.isExactlyZero()) + { + LLAgent::exlEndMeasurePoint = object->getPosition(); + + chat.mText = llformat("End point set"); + LLFloaterChat::addChat(chat); + } + else + { + LLAgent::exlStartMeasurePoint = LLVector3::zero; + LLAgent::exlEndMeasurePoint = LLVector3::zero; + return false; + } + + if (!LLAgent::exlStartMeasurePoint.isExactlyZero() && !LLAgent::exlEndMeasurePoint.isExactlyZero()) + { + F32 fdist = dist_vec(LLAgent::exlStartMeasurePoint, LLAgent::exlEndMeasurePoint); + LLAgent::exlStartMeasurePoint = LLVector3::zero; + LLAgent::exlEndMeasurePoint = LLVector3::zero; + + chat.mText = llformat("Distance: %fm", fdist); + LLFloaterChat::addChat(chat); + } + } + + return true; + } +}; + class LLAvatarAnims : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2443,6 +2526,60 @@ bool callback_freeze(const LLSD& notification, const LLSD& response) return false; } +class LLScriptCount : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + ScriptCounter::serializeSelection(false); + return true; + } +}; + +class LLScriptDelete : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + ScriptCounter::serializeSelection(true); + return true; + } +}; + +class LLObjectVisibleScriptCount : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + bool new_value = (object != NULL); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + + return true; + } +}; + +class LLObjectEnableScriptDelete : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + bool new_value = (object != NULL); + if(new_value) + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + if(object) + if(!object->permModify()) + { + new_value=false; + break; + } + } + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + + return true; + } +}; class LLAvatarFreeze : public view_listener_t { @@ -2632,6 +2769,22 @@ class LLAvatarEject : public view_listener_t } }; + +class LLAvatarCopyUUID : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(!avatar) return true; + + LLUUID uuid = avatar->getID(); + char buffer[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ + uuid.toString(buffer); + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); + return true; + } +}; + class LLAvatarEnableFreezeEject : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -3071,19 +3224,7 @@ void process_grant_godlike_powers(LLMessageSystem* msg, void**) void handle_reopen_with_hex_editor(void*) { - LLFloater* top = gFloaterView->getFrontmost(); - if (top) - { - LLUUID item_id = top->getItemID(); - if(item_id.notNull()) - { - LLInventoryItem* item = gInventory.getItem(item_id); - if(item) - { - DOFloaterHex::show(item_id); - } - } - } + } void handle_open_message_log(void*) @@ -3103,12 +3244,12 @@ void handle_edit_ao(void*) void handle_local_assets(void*) { - LLFloaterVFS::show(); + } void handle_vfs_explorer(void*) { - LLFloaterVFSExplorer::show(); + } void handle_sounds_explorer(void*) @@ -3132,6 +3273,79 @@ void handle_close_all_notifications(void*) } } +void handle_fake_away_status(void*) +{ + if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); + + if (gSavedSettings.getBOOL("FakeAway") == TRUE) + { + gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); + gSavedSettings.setBOOL("FakeAway", FALSE); + gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); + } + else + { + gSavedSettings.declareBOOL("FakeAway", TRUE, "", NO_PERSIST); + gSavedSettings.setBOOL("FakeAway", TRUE); + gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); + } +} + +void handle_hide_typing_notification(void*) +{ + if (!gSavedSettings.controlExists("HideTypingNotification")) + gSavedSettings.declareBOOL("HideTypingNotification", FALSE, "Hide your 'Name is typing...' message when Instant Messaging."); + + BOOL hide = gSavedSettings.getBOOL("HideTypingNotification"); + if (hide) + { + gSavedSettings.declareBOOL("HideTypingNotification", FALSE, "Hide your 'Name is typing...' message when Instant Messaging."); + gSavedSettings.setBOOL("HideTypingNotification", FALSE); + } + else + { + gSavedSettings.declareBOOL("HideTypingNotification", TRUE, "Hide your 'Name is typing...' message when Instant Messaging."); + gSavedSettings.setBOOL("HideTypingNotification", TRUE); + } + + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = llformat("IM Typing Notifications: %s",(hide ? "On" : "Off")); + LLFloaterChat::addChat(chat); +} + +void handle_force_ground_sit(void*) +{ + if (gAgent.getAvatarObject()) + { + if(!gAgent.getAvatarObject()->mIsSitting) + { + gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + } + } +} + +void handle_phantom_avatar(void*) +{ + BOOL ph = LLAgent::getPhantom(); + + if (ph) + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + else + gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + + LLAgent::togglePhantom(); + ph = LLAgent::getPhantom(); + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = llformat("%s%s","Phantom ",(ph ? "On" : "Off")); + LLFloaterChat::addChat(chat); +} + // /* @@ -3935,14 +4149,14 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) msg->nextBlockFast(_PREHASH_ObjectData); msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); // - if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) + if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { - // - // VEFFECT: DerezObject - LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal(object->getPositionGlobal()); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - // + // + // VEFFECT: DerezObject + LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(object->getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + // } // } @@ -5227,6 +5441,26 @@ class LLWorldSitOnGround : public view_listener_t } }; +class LLWorldFakeAway : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); + + if (gSavedSettings.getBOOL("FakeAway") == TRUE) + { + gSavedSettings.setBOOL("FakeAway", FALSE); + gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); + } + else + { + gSavedSettings.setBOOL("FakeAway", TRUE); + gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); + } + return true; + } +}; + class LLWorldEnableSitOnGround : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -5683,10 +5917,6 @@ class LLShowFloater : public view_listener_t { JCFloaterAreaSearch::toggle(); } - else if (floater_name == "export region") - { - LLFloaterExportRegion::toggleInstance(LLSD()); - } else if (floater_name == "grid options") { LLFloaterBuildOptions::show(NULL); @@ -8081,6 +8311,1096 @@ static void addMenu(view_listener_t *menu, const std::string& name) menu->registerListener(gMenuHolder, name); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//Chalice - Old beacon style +class LLViewBeaconWidth : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string width = userdata.asString(); + if(width == "1") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 1); + } + else if(width == "4") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 4); + } + else if(width == "16") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 16); + } + else if(width == "32") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 32); + } + + return true; + } +}; + +//PURPLESL - Old beacon style +class LLViewToggleBeacon : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string beacon = userdata.asString(); + if (beacon == "scriptsbeacon") + { + LLPipeline::toggleRenderScriptedBeacons(NULL); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) + { + LLPipeline::toggleRenderScriptedTouchBeacons(NULL); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); + } + } + else if (beacon == "physicalbeacon") + { + LLPipeline::toggleRenderPhysicalBeacons(NULL); + gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) ); + } + else if (beacon == "soundsbeacon") + { + LLPipeline::toggleRenderSoundBeacons(NULL); + gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) ); + } + else if (beacon == "particlesbeacon") + { + LLPipeline::toggleRenderParticleBeacons(NULL); + gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) ); + } + else if (beacon == "scripttouchbeacon") + { + LLPipeline::toggleRenderScriptedTouchBeacons(NULL); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) + { + LLPipeline::toggleRenderScriptedBeacons(NULL); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); + } + } + else if (beacon == "renderbeacons") + { + LLPipeline::toggleRenderBeacons(NULL); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) + { + LLPipeline::toggleRenderHighlights(NULL); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); + } + } + else if (beacon == "renderhighlights") + { + LLPipeline::toggleRenderHighlights(NULL); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) + { + LLPipeline::toggleRenderBeacons(NULL); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); + } + } + + return true; + } +}; +//PURPLESL - Old beacon style +class LLViewCheckBeaconEnabled : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + std::string beacon = userdata["data"].asString(); + bool new_value = false; + if (beacon == "scriptsbeacon") + { + new_value = gSavedSettings.getBOOL( "scriptsbeacon"); + LLPipeline::setRenderScriptedBeacons(new_value); + } + else if (beacon == "physicalbeacon") + { + new_value = gSavedSettings.getBOOL( "physicalbeacon"); + LLPipeline::setRenderPhysicalBeacons(new_value); + } + else if (beacon == "soundsbeacon") + { + new_value = gSavedSettings.getBOOL( "soundsbeacon"); + LLPipeline::setRenderSoundBeacons(new_value); + } + else if (beacon == "particlesbeacon") + { + new_value = gSavedSettings.getBOOL( "particlesbeacon"); + LLPipeline::setRenderParticleBeacons(new_value); + } + else if (beacon == "scripttouchbeacon") + { + new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); + LLPipeline::setRenderScriptedTouchBeacons(new_value); + } + else if (beacon == "renderbeacons") + { + new_value = gSavedSettings.getBOOL( "renderbeacons"); + LLPipeline::setRenderBeacons(new_value); + } + else if (beacon == "renderhighlights") + { + new_value = gSavedSettings.getBOOL( "renderhighlights"); + LLPipeline::setRenderHighlights(new_value); + } + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -8151,6 +9471,8 @@ void initialize_menus() addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); + addMenu(new LLViewToggleBeacon(), "View.ToggleBeacon"); + addMenu(new LLViewBeaconWidth(), "View.BeaconWidth"); addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); addMenu(new LLZoomer(1.2f), "View.ZoomOut"); @@ -8168,9 +9490,26 @@ void initialize_menus() addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); + addMenu(new LLViewCheckBeaconEnabled(), "View.CheckBeaconEnabled"); addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); + + + + + + + + + + + + + + + + // World menu addMenu(new LLWorldChat(), "World.Chat"); addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); @@ -8181,6 +9520,7 @@ void initialize_menus() addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation"); addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); + addMenu(new LLWorldFakeAway(), "World.FakeAway"); addMenu(new LLWorldSetAway(), "World.SetAway"); addMenu(new LLWorldSetBusy(), "World.SetBusy"); @@ -8196,11 +9536,13 @@ void initialize_menus() (new LLWorldPostProcess())->registerListener(gMenuHolder, "World.PostProcess"); (new LLWorldDayCycle())->registerListener(gMenuHolder, "World.DayCycle"); + // Tools menu addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects"); addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding"); + addMenu(new LLToolsShowSelectionHighlights(), "Tools.ShowSelectionHighlights"); addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection"); addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius"); @@ -8217,6 +9559,8 @@ void initialize_menus() addMenu(new LLToolsBuyOrTake(), "Tools.BuyOrTake"); addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy"); addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy"); + + addMenu(new LLScriptDelete(), "Tools.ScriptDelete"); // addMenu(new LLToolsEnableAdminDelete(), "Tools.EnableAdminDelete"); addMenu(new LLToolsAdminDelete(), "Tools.AdminDelete"); @@ -8246,10 +9590,13 @@ void initialize_menus() addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments"); // Avatar pie menu + + addMenu(new LLObjectMute(), "Avatar.Mute"); addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend"); addMenu(new LLAvatarFreeze(), "Avatar.Freeze"); addMenu(new LLAvatarDebug(), "Avatar.Debug"); + addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); addMenu(new LLAvatarEnableDebug(), "Avatar.EnableDebug"); addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); @@ -8261,6 +9608,7 @@ void initialize_menus() addMenu(new LLObjectEnableMute(), "Avatar.EnableMute"); addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject"); + addMenu(new LLAvatarCopyUUID(), "Avatar.CopyUUID"); // Object pie menu addMenu(new LLObjectOpen(), "Object.Open"); @@ -8273,8 +9621,10 @@ void initialize_menus() addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse"); addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse"); // - addMenu(new LLObjectSaveAs(), "Object.SaveAs"); addMenu(new LLObjectImport(), "Object.Import"); + addMenu(new LLObjectMeasure(), "Object.Measure"); + addMenu(new LLObjectData(), "Object.Data"); + addMenu(new LLScriptCount(), "Object.ScriptCount"); // addMenu(new LLObjectMute(), "Object.Mute"); addMenu(new LLObjectBuy(), "Object.Buy"); @@ -8289,7 +9639,6 @@ void initialize_menus() addMenu(new LLObjectEnableReturn(), "Object.EnableReturn"); addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); // - addMenu(new LLObjectEnableSaveAs(), "Object.EnableSaveAs"); addMenu(new LLObjectEnableImport(), "Object.EnableImport"); // addMenu(new LLObjectEnableMute(), "Object.EnableMute"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index d6f6bd231..3fcbf4972 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -36,16 +36,20 @@ // project includes #include "llagent.h" + #include "llfilepicker.h" #include "llfloateranimpreview.h" #include "llfloaterbuycurrency.h" + #include "llfloaterimagepreview.h" #include "llfloaternamedesc.h" #include "llfloatersnapshot.h" + #include "llinventorymodel.h" // gInventory #include "llresourcedata.h" #include "llfloaterperms.h" #include "llstatusbar.h" + #include "llviewercontrol.h" // gSavedSettings #include "llviewerimagelist.h" #include "lluictrlfactory.h" @@ -80,6 +84,8 @@ // system libraries #include +//#include "importtracker.h" + typedef LLMemberListener view_listener_t; @@ -108,7 +114,7 @@ class LLFileEnableUpload : public view_listener_t #if LL_WINDOWS static std::string SOUND_EXTENSIONS = "wav"; static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; -static std::string ANIM_EXTENSIONS = "bvh"; +static std::string ANIM_EXTENSIONS = "bvh anim animatn"; #ifdef _CORY_TESTING static std::string GEOMETRY_EXTENSIONS = "slg"; #endif @@ -151,6 +157,12 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) to upload for a particular task. If the file is valid for the given action, returns the string to the full path filename, else returns NULL. Data is the load filter for the type of file as defined in LLFilePicker. + + Eventually I'd really like to have a built-in browser that gave you all + valid filetypes, default permissions, "Temp when available", and a single + upload button. Maybe let it show the contents of multiple folders. The main + purpose of this features is to deal with the problem of SL just up and + disconnecting if you take more than like 30 seconds to look for a file. -HgB **/ const std::string upload_pick(void* data) { @@ -242,9 +254,7 @@ const std::string upload_pick(void* data) //now we check to see //if the file is actually a valid image/sound/etc. - // Screw their checks - /* - // + //Consider completely disabling this, see how SL handles it. Maybe we can get full song uploads again! -HgB if (type == LLFilePicker::FFLOAD_WAV) { // pre-qualify wavs to make sure the format is acceptable @@ -258,11 +268,7 @@ const std::string upload_pick(void* data) return std::string(); } }//end if a wave/sound file - // - */ - // - return filename; } @@ -462,6 +468,167 @@ void upload_error(const std::string& error_message, const std::string& label, co LLFilePicker::instance().reset(); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class LLFileEnableCloseWindow : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -778,13 +945,6 @@ void upload_new_resource(const std::string& src_filename, std::string name, return; } } - // - else if(exten == "ogg") - { - asset_type = LLAssetType::AT_SOUND; // tag it as audio - filename = src_filename; - } - // else if(exten == "tmp") { // This is a generic .lin resource file @@ -950,6 +1110,13 @@ void upload_new_resource(const std::string& src_filename, std::string name, // } // + // + else if(exten == "ogg") + { + asset_type = LLAssetType::AT_SOUND; // tag it as audio + filename = src_filename; + } + // else if (exten == "animatn") { asset_type = LLAssetType::AT_ANIMATION; @@ -1193,12 +1360,10 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLUploadDialog::modalUploadFinished(); delete data; - // - /* - // // *NOTE: This is a pretty big hack. What this does is check the // file picker if there are any more pending uploads. If so, // upload that file. + /* Agreed, let's not use it. -HgB const std::string& next_file = LLFilePicker::instance().getNextFile(); if(is_balance_sufficient && !next_file.empty()) { @@ -1219,9 +1384,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost userdata); } - // */ - // } void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, @@ -1346,21 +1509,18 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty data->mAssetInfo.setName(name); data->mAssetInfo.setDescription(desc); data->mPreferredLocation = destination_folder_type; - // + LLAssetStorage::LLStoreAssetCallback asset_callback = temporary ? &temp_upload_callback : &upload_done_callback; - // if (callback) { asset_callback = callback; } - // gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, asset_callback, (void*)data, temporary, TRUE, temporary); - // } } @@ -1386,7 +1546,7 @@ void init_menu_file() (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); - + //Emerald has a second llFileSaveTexture here... Same as the original. Odd. -HgB (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); } diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index c92e82da3..0e03429e9 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -78,4 +78,6 @@ void upload_new_resource(const LLTransactionID &tid, S32 expected_upload_cost, void *userdata); +const std::string upload_pick(void* data); + #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f970df1b6..3301bf511 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3197,6 +3197,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) return; } + if(gAgent.getPhantom()) return; //Don't want to do this while phantom + // We have already requested to log out. Don't send agent updates. if(LLAppViewer::instance()->logoutRequestSent()) { @@ -5914,16 +5916,3 @@ void LLOfferInfo::forceResponse(InventoryOfferResponse response) params.functor(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2)); LLNotifications::instance().forceResponse(params, response); } - -// lol -void spoof_dropped_callback(LLNetCanary::entry entry) -{ - if(gSavedSettings.getBOOL("SpoofProtectionAlerts")) - { - LLSD args; - args["[MESSAGE]"] = llformat("A suspicious %s packet was dropped based on your IP Spoofing Protection settings.", entry.name.c_str()); - LLNotifications::instance().add("SystemMessageTip",args); - } -} -// - diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index d33fdf039..1a84cefc8 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -197,9 +197,6 @@ void process_decline_callingcard(LLMessageSystem* msg, void**); // Message system exception prototypes void invalid_message_callback(LLMessageSystem*, void*, EMessageException); -// -void spoof_dropped_callback(LLNetCanary::entry entry); -// void process_initiate_download(LLMessageSystem* msg, void**); void start_new_inventory_observer(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0ee0a4a1c..8f4157ade 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -46,8 +46,10 @@ #include "lldriverparam.h" #include "lleditingmotion.h" #include "llemote.h" + #include "llfirstuse.h" #include "llheadrotmotion.h" + #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventoryview.h" @@ -67,6 +69,7 @@ #include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" #include "llviewercamera.h" +#include "llviewercontrol.h" #include "llviewerimagelist.h" #include "llviewermedia.h" #include "llviewermenu.h" @@ -83,6 +86,7 @@ #include "llvoiceclient.h" #include "llvoicevisualizer.h" // Ventrella +#include "llsdserialize.h" // #include "llfloaterexploreanimations.h" #include "llao.h" @@ -272,14 +276,14 @@ class LLVOAvatarXmlInfo public: LLVOAvatarXmlInfo(); ~LLVOAvatarXmlInfo(); - + private: BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); BOOL parseXmlMeshNodes(LLXmlTreeNode* root); BOOL parseXmlColorNodes(LLXmlTreeNode* root); BOOL parseXmlLayerNodes(LLXmlTreeNode* root); BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - + struct LLVOAvatarMeshInfo { typedef std::pair morph_info_pair_t; @@ -675,6 +679,9 @@ S32 LLVOAvatar::sScratchTexBytes = 0; F32 LLVOAvatar::sRenderDistance = 256.f; S32 LLVOAvatar::sNumVisibleAvatars = 0; S32 LLVOAvatar::sNumLODChangesThisFrame = 0; +LLSD LLVOAvatar::sClientResolutionList; + + const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = @@ -700,11 +707,17 @@ F32 LLVOAvatar::sLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; + + + + + F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; F32 LLVOAvatar::sGreyUpdateTime = 0.f; + //----------------------------------------------------------------------------- // Helper functions //----------------------------------------------------------------------------- @@ -999,6 +1012,16 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCurrentGesticulationLevel = 0; } + + + + + + + + + + //------------------------------------------------------------------------ // LLVOAvatar::~LLVOAvatar() //------------------------------------------------------------------------ @@ -1043,8 +1066,8 @@ LLVOAvatar::~LLVOAvatar() std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); mMeshes.clear(); - - for (std::vector::iterator jointIter = mMeshLOD.begin(); + std::vector::iterator jointIter; + for (jointIter = mMeshLOD.begin(); jointIter != mMeshLOD.end(); jointIter++) { LLViewerJoint* joint = (LLViewerJoint *) *jointIter; @@ -1152,6 +1175,47 @@ void LLVOAvatar::dumpScratchTextureByteCount() llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // static void LLVOAvatar::dumpBakedStatus() { @@ -1209,7 +1273,7 @@ void LLVOAvatar::dumpBakedStatus() else { llcont << " Unbaked ("; - + for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); iter++) @@ -1446,6 +1510,9 @@ void LLVOAvatar::initClass() llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } + { + loadClientTags(); + } } @@ -1782,6 +1849,9 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) { LLMemType mt(LLMemType::MTYPE_AVATAR); + + if (!info) + return FALSE; //------------------------------------------------------------------------- // allocate joints //------------------------------------------------------------------------- @@ -2059,6 +2129,12 @@ void LLVOAvatar::buildCharacter() } } + + + + + + if (!attachment_found) { gAttachPieMenu->appendSeparator(); @@ -2113,6 +2189,12 @@ void LLVOAvatar::buildCharacter() } } + + + + + + for (S32 pass = 0; pass < 2; pass++) { for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); @@ -2124,6 +2206,7 @@ void LLVOAvatar::buildCharacter() { continue; } + LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), NULL, &object_selected_and_point_valid, &attach_label, attachment); @@ -2183,8 +2266,13 @@ void LLVOAvatar::buildCharacter() LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); if (attachment) { + + LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), NULL, object_selected_and_point_valid); + + + gAttachBodyPartPieMenus[group]->append(item); item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), @@ -2611,9 +2699,20 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } + //Emerald performs some force-bakes stuff here. Added it in because we noticed slow responses with client tag ident. -HgB + if(mIsSelf) + { + for(U8 i=0;iforceActive(); + } + } + idleUpdateVoiceVisualizer( voice_enabled ); idleUpdateMisc( detailed_update ); idleUpdateAppearanceAnimation(); + idleUpdateLipSync( voice_enabled ); idleUpdateLoadingEffect(); idleUpdateBelowWater(); // wind effect uses this @@ -2683,6 +2782,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { gAgent.clearAFK(); } + mIdleTimer.reset(); } else { @@ -2843,12 +2943,19 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() { gAgent.sendAgentSetAppearance(); } + mIdleTimer.reset(); } else { F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); F32 morph_amt; + + + + + + if (last_blend_frac == 1.f) { morph_amt = 1.f; @@ -2871,6 +2978,8 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } } + + // apply all params for (param = getFirstVisualParam(); param; @@ -2885,6 +2994,106 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void LLVOAvatar::idleUpdateLipSync(bool voice_enabled) { // Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync @@ -2914,6 +3123,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled) mLipSyncActive = true; LLCharacter::updateVisualParams(); dirtyMesh(); + mIdleTimer.reset(); } } @@ -2960,6 +3170,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() } } + void LLVOAvatar::idleUpdateWindEffect() { // update wind effect @@ -3017,9 +3228,144 @@ void LLVOAvatar::idleUpdateWindEffect() } } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +bool LLVOAvatar::updateClientTags() +{/* Won't do anything for now, we don't have a definitions site set up. -HGB + std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_list.xml"); + LLSD response = LLHTTPClient::blockingGet("http://www.destructivelabs.net/remote/tags/client_list.xml"); + if(response.has("body")) + { + const LLSD &client_list = response["body"]; + + if(client_list.has("isComplete")) + { + llofstream export_file; + export_file.open(client_list_filename); + LLSDSerialize::toPrettyXML(client_list, export_file); + export_file.close(); + return true; + } + }*/ + return false; +} + +bool LLVOAvatar::loadClientTags() +{ + //Changed the file name to keep Emerald from overwriting it. Hokey stuff in there, and it's missing clients. -HGB + std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_definitions.xml"); + + if(!LLFile::isfile(client_list_filename)) + { + client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "client_definitions.xml"); + } + + if(LLFile::isfile(client_list_filename)) + { + LLSD client_list; + + llifstream importer(client_list_filename); + LLSDSerialize::fromXMLDocument(client_list, importer); + if(client_list.has("isComplete")) + { + sClientResolutionList = client_list; + }else + { + return false; + } + }else + { + return false; + } + + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* avatarp = (LLVOAvatar*) *iter; + if(avatarp) + { + LLVector3 root_pos_last = avatarp->mRoot.getWorldPosition(); + avatarp->idleUpdateNameTag(root_pos_last); + } + } + return true; +} + void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useComment) { std::string uuid_str = getTE(TEX_HEAD_BODYPAINT)->getID().asString(); //UUID of the head texture + if (mIsSelf) + { + if (!gSavedSettings.getBOOL("AscentShowSelfTagColor")) + { + color = gColors.getColor( "AvatarNameColor" ); + return; + } + else if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) + { + uuid_str = gSavedSettings.getString("AscentSpoofClientUUID"); + } + else + { + uuid_str = gSavedPerAccountSettings.getString("AscentSpoofClientUUID"); + } + } if(getTEImage(TEX_HEAD_BODYPAINT)->getID() == IMG_DEFAULT_AVATAR) { BOOL res = FALSE; @@ -3058,149 +3404,36 @@ void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useCom && getTEImage(TEX_UPPER_BODYPAINT)->getID().asString() == "4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6" && getTEImage(TEX_LOWER_BODYPAINT)->getID().asString() == "4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6") { - color = LLColor4(1.f, 1.0f, 1.0f); - client = "Unknown viewer"; + color = LLColor4(0.5f, 0.0f, 0.0f); + client = "Unknown"; } return; } else { - color = LLColor4(0.5f, 0.5f, 0.5f); + color = LLColor4(1.0f, 1.0f, 1.0f); //White, since tags are white on their side. -HgB client = "Viewer 2.0"; return; } } if(getTEImage(TEX_HEAD_BODYPAINT)->isMissingAsset()) { - color = LLColor4(1.f, 1.0f, 1.0f); - client = "Unknown viewer"; + color = LLColor4(0.5f, 0.0f, 0.0f); + client = "Unknown"; } - else if (uuid_str == "ccda2b3b-e72c-a112-e126-fee238b67218") + else if(LLVOAvatar::sClientResolutionList.has("isComplete") && LLVOAvatar::sClientResolutionList.has(uuid_str)) { - // textures other than head are 4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6 - color = LLColor4(0.f, 1.0f, 0.0f); - client = "Emerald"; - - } - else if (uuid_str == "0bcd5f5d-a4ce-9ea4-f9e8-15132653b3d8") - { - color = LLColor4(1.0f, 0.3f, 0.5f); - client = "MoyMix"; - - } - else if (uuid_str == "5855f37d-63e5-3918-1404-8ffa3820eb6d") - { - color = LLColor4(1.0f, 0.3f, 0.5f); - client = "MoyMix/B"; - - } - else if (uuid_str == "9ba526b6-f43d-6b60-42de-ce62a25ee7fb") - { - color = LLColor4(1.0f, 0.3f, 0.5f); - client = "MoyMix/nolife"; - - } - //else if (uuid_str == "abbca853-30ba-49c1-a1e7-2a5b9a70573f") - //{ - // color = LLColor4(0.5f, 0.75f, 1.0f); - // strcat(line, " (CryoLife/" + "A)"); - // - //} - else if (uuid_str == "0f6723d2-5b23-6b58-08ab-308112b33786") - { - color = LLColor4(0.5f, 0.75f, 1.0f); - client = "CryoLife"; - - } - else if (uuid_str == "2c9c1e0b-e5d1-263e-16b1-7fc6d169f3d6") - { - color = LLColor4(0.5f, 0.75f, 1.0f); - client = "Phoxy SL"; - - } - else if (uuid_str == "c252d89d-6f7c-7d90-f430-d140d2e3fbbe") - { - color = LLColor4(0.7f, 0.7f, 0.7f); - client = "VLife"; - - } - else if (uuid_str == "5aa5c70d-d787-571b-0495-4fc1bdef1500") - { - color = LLColor4(1.f, 0.0f, 0.0f); - client = "GridProxy/LordGregGreg"; - - } - else if (uuid_str == "8183e823-c443-2142-6eb6-2ab763d4f81c") - { - color = LLColor4(1.f, 1.f, 0.0f); - client = "GridProxy/DayOh"; - - } - else if (uuid_str == "f3fd74a6-fee7-4b2f-93ae-ddcb5991da04") - { - color = LLColor4(1.0f, 0.0f, 1.0f); - client = "PSL/A"; - - } - else if (uuid_str == "77662f23-c77a-9b4d-5558-26b757b2144c") - { - color = LLColor4(1.0f, 0.0f, 1.0f); - client = "PSL/B"; - - } - else if (uuid_str == "1c29480c-c608-df87-28bb-964fb64c5366") - { - color = LLColor4(1.f, 1.0f, 1.0f); - client = "Emerald/GEMINI"; - - } - else if (uuid_str == "e6f9c019-8783-dc3e-b265-41f1510333fc") - { - color = LLColor4(0.4f,0.4f,0.4f); - client = "Onyx"; - - } - else if (uuid_str == "5262d71a-88f7-ef40-3b15-00ea148ab4b5") - { - color = LLColor4(0.9f, 0.9f, 0.9f); - client = "GEMINI Bot"; - - } - else if (uuid_str == "adcbe893-7643-fd12-f61c-0b39717e2e32") - { - color = LLColor4(1.0f, 0.5f, 0.4f); - client = "tyk3n"; - - } - else if (uuid_str == "f5a48821-9a98-d09e-8d6a-50cc08ba9a47") - { - color = gColors.getColor( "AvatarNameColor" ); - client = "NeilLife"; - - } - else if (uuid_str == "cc7a030f-282f-c165-44d2-b5ee572e72bf") - { - color = LLColor4::purple; - client = "Imprudence"; - - } - else if (uuid_str == "380ae30b-f2c7-b07c-041e-5688e89a6fc1") - { - color = LLColor4(0.65f, 0.93f, 0.14f); - client = "Nano"; - - } - else if (uuid_str == "c58fca06-33b3-827d-d81c-a886a631affc") - { - color = LLColor4(1.0f,0.61176f,0.0f); - client = "Whale"; - - } - else if (uuid_str == "872c0005-3095-0967-866d-11cd71115c22") - { - color = LLColor4(0.25f,0.5f,0.75f); - client = "<-- Fag"; - + LLSD cllsd = LLVOAvatar::sClientResolutionList[uuid_str]; + client = cllsd["name"].asString(); + LLColor4 colour; + colour.setValue(cllsd["color"]); + if(cllsd["multiple"].asReal() != 0) + { + color += colour; + color *= 1.0/(cllsd["multiple"].asReal()+1.0f); + } + else + color = colour; } else { @@ -3209,6 +3442,11 @@ void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useCom //llinfos << "Apparently this tag isn't registered: " << uuid_str << llendl; } + if ((mIsSelf)&&(!gSavedSettings.getBOOL("AscentShowSelfTagColor"))) + { + color = gColors.getColor( "AvatarNameColor" ); + } + if(useComment) { LLUUID baked_head_id = getTE(9)->getID(); @@ -3240,6 +3478,123 @@ void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useCom } } } + +LLColor4 LLVOAvatar::getTagColorByUUID(std::string uuid_str) +{ + if (uuid_str == "0bcd5f5d-a4ce-9ea4-f9e8-15132653b3d8") + { + return LLColor4(1.0f, 0.3f, 0.5f); + //client = "MoyMix"; + } + else if (uuid_str == "5855f37d-63e5-3918-1404-8ffa3820eb6d") + { + return LLColor4(1.0f, 0.3f, 0.5f); + //client = "MoyMix/B"; + } + else if (uuid_str == "9ba526b6-f43d-6b60-42de-ce62a25ee7fb") + { + return LLColor4(1.0f, 0.3f, 0.5f); + //client = "MoyMix/nolife"; + } + else if (uuid_str == "0f6723d2-5b23-6b58-08ab-308112b33786") + { + return LLColor4(0.5f, 0.75f, 1.0f); + //client = "CryoLife"; + } + else if (uuid_str == "2c9c1e0b-e5d1-263e-16b1-7fc6d169f3d6") + { + return LLColor4(0.5f, 0.75f, 1.0f); + //client = "Phoxy SL"; + } + else if (uuid_str == "c252d89d-6f7c-7d90-f430-d140d2e3fbbe") + { + return LLColor4(0.7f, 0.7f, 0.7f); + //client = "VLife"; + } + else if (uuid_str == "5aa5c70d-d787-571b-0495-4fc1bdef1500") + { + return LLColor4(1.f, 0.0f, 0.0f); + //client = "GridProxy/LordGregGreg"; + } + else if (uuid_str == "8183e823-c443-2142-6eb6-2ab763d4f81c") + { + return LLColor4(1.f, 1.f, 0.0f); + //client = "GridProxy/DayOh"; + } + else if (uuid_str == "f3fd74a6-fee7-4b2f-93ae-ddcb5991da04") + { + return LLColor4(1.0f, 0.0f, 1.0f); + //client = "PSL/A"; + } + else if (uuid_str == "77662f23-c77a-9b4d-5558-26b757b2144c") + { + return LLColor4(1.0f, 0.0f, 1.0f); + //client = "PSL/B"; + } + else if (uuid_str == "1c29480c-c608-df87-28bb-964fb64c5366") + { + return LLColor4(1.f, 1.0f, 1.0f); + //client = "Emerald/GEMINI"; + } + else if (uuid_str == "e6f9c019-8783-dc3e-b265-41f1510333fc") + { + return LLColor4(0.4f,0.4f,0.4f); + //client = "Onyx"; + } + else if (uuid_str == "5262d71a-88f7-ef40-3b15-00ea148ab4b5") + { + return LLColor4(0.9f, 0.9f, 0.9f); + //client = "GEMINI Bot"; + } + else if (uuid_str == "adcbe893-7643-fd12-f61c-0b39717e2e32") + { + return LLColor4(1.0f, 0.5f, 0.4f); + //client = "tyk3n"; + } + else if (uuid_str == "f5a48821-9a98-d09e-8d6a-50cc08ba9a47") + { + return gColors.getColor( "AvatarNameColor" ); + //client = "NeilLife"; + } + else if (uuid_str == "cc7a030f-282f-c165-44d2-b5ee572e72bf") + { + return LLColor4::purple; + //client = "Imprudence"; + } + else if (uuid_str == "380ae30b-f2c7-b07c-041e-5688e89a6fc1") + { + return LLColor4(0.65f, 0.93f, 0.14f); + //client = "Nano"; + } + else if (uuid_str == "c58fca06-33b3-827d-d81c-a886a631affc") + { + return LLColor4(1.0f,0.61176f,0.0f); + //client = "Whale"; + } + else if (uuid_str == "872c0005-3095-0967-866d-11cd71115c22") + { + return LLColor4(0.25f,0.5f,0.75f); + //client = "<-- Fag"; + } + else if (uuid_str == "00000000-0000-0000-0000-000000000000") + { + return LLColor4(0.5f, 0.5f, 0.5f); + //client = "Viewer 2.0"; + } + else if (uuid_str == "734fed29-4c51-63e5-1648-6589949d7585") + { + return LLColor4(0.60000f, 0.42745f, 0.80784f); + //client = "Explicit"; + } + else if (uuid_str == "8873757c-092a-98fb-1afd-ecd347566fcd") + { + return LLColor4(0.375f, 1.0f, 1.0f); + //client = "Ascent"; + } + + return gColors.getColor( "AvatarNameColor" ); +} + void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) { // update chat bubble @@ -3254,6 +3609,9 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) const F32 time_visible = mTimeVisible.getElapsedTimeF32(); const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds + + + BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); BOOL render_name = visible_chat || @@ -3287,7 +3645,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) // std::string client; // - // First Calculate Alpha // If alpha > 0, create mNameText if necessary, otherwise delete it { @@ -3329,13 +3686,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) LLColor4 avatar_name_color = gColors.getColor( "AvatarNameColor" ); // - if(isFullyLoaded() && !mIsSelf) + if(isFullyLoaded()) { getClientInfo(client,avatar_name_color); } - // + avatar_name_color.setAlpha(alpha); + + //llinfos << "Show Self Tag is set to " << gSavedSettings.getBOOL("AscentShowSelfTagColor") << llendl; + mNameText->setColor(avatar_name_color); + LLQuaternion root_rot = mRoot.getWorldRotation(); mNameText->setUsePixelSize(TRUE); @@ -3373,8 +3734,11 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) if (mNameText.notNull() && firstname && lastname) { BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); + if(mNameAway && ! is_away) mIdleTimer.reset(); BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + if(mNameBusy && ! is_busy) mIdleTimer.reset(); BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); + if(mNameAppearance && ! is_appearance) mIdleTimer.reset(); BOOL is_muted; if (mIsSelf) { @@ -3394,6 +3758,10 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) || client.length() ) // { std::string line; + + + + if (!sRenderGroupTitles) { // If all group titles are turned off, stack first name @@ -3415,50 +3783,67 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) line += " "; line += lastname->getString(); - BOOL need_comma = FALSE; + + + + + + std::string additions; + BOOL need_comma = FALSE; + if (client.length() || is_away || is_muted || is_busy) { - line += " ("; if (client != "") { - line += client; - need_comma = TRUE; + if ((!mIsSelf)||(gSavedSettings.getBOOL("AscentShowSelfTag"))) + { + additions += client; + need_comma = TRUE; + } } if (is_away) { if (need_comma) { - line += ", "; + additions += ", "; } - line += "Away"; + additions += "Away"; need_comma = TRUE; } if (is_busy) { if (need_comma) { - line += ", "; + additions += ", "; } - line += "Busy"; + additions += "Busy"; need_comma = TRUE; } if (is_muted) { if (need_comma) { - line += ", "; + additions += ", "; } - line += "Muted"; + additions += "Muted"; need_comma = TRUE; } - line += ")"; + if (additions.length()) + line += " (" + additions + ")"; + } if (is_appearance) { line += "\n"; line += "(Editing Appearance)"; } + if(!mIsSelf && mIdleTimer.getElapsedTimeF32() > 120) + { + line += "\n"; + line += getIdleTime(); + } + mNameAway = is_away; mNameBusy = is_busy; mNameMute = is_muted; @@ -3471,6 +3856,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) if (visible_chat) { + mIdleTimer.reset(); mNameText->setDropShadow(TRUE); mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_LEFT); @@ -3542,7 +3928,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) mNameText->addLine("...", new_chat); break; } - + mIdleTimer.reset(); } } else @@ -3574,6 +3960,42 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void LLVOAvatar::idleUpdateTractorBeam() { //-------------------------------------------------------------------- @@ -3583,9 +4005,8 @@ void LLVOAvatar::idleUpdateTractorBeam() { return; } - - // - if(gSavedSettings.getBOOL("DisablePointAtAndBeam")) + + if(gSavedSettings.getBOOL("DisablePointAtAndBeam")) { return; } @@ -3609,6 +4030,26 @@ void LLVOAvatar::idleUpdateTractorBeam() { mBeam = NULL; } + + + + + + + + + + + + + + + + + + + + else if (!mBeam || mBeam->isDead()) { // VEFFECT: Tractor Beam @@ -3665,6 +4106,87 @@ void LLVOAvatar::idleUpdateTractorBeam() } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void LLVOAvatar::idleUpdateBelowWater() { F32 avatar_height = (F32)(getPositionGlobal().mdV[VZ]); @@ -4504,6 +5026,12 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked && !LLDrawPoolAvatar::sSkipTransparent; + + + + + + LLGLState test(GL_ALPHA_TEST, should_alpha_mask); if (should_alpha_mask) @@ -4615,6 +5143,10 @@ U32 LLVOAvatar::renderRigid() return 0; } + + + + const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked && !LLDrawPoolAvatar::sSkipTransparent; @@ -4970,7 +5502,7 @@ void LLVOAvatar::processAnimationStateChanges() { LLMemType mt(LLMemType::MTYPE_AVATAR); - if (gNoRender) + if (gNoRender)//||mLockTPose) (For future use -HGB) { return; } @@ -5011,6 +5543,11 @@ void LLVOAvatar::processAnimationStateChanges() // playing, but not signaled, so stop if (found_anim == mSignaledAnimations.end()) { + + + + + processSingleAnimationStateChange(anim_it->first, FALSE); // LLFloaterExploreAnimations::stopAnim(getID(), anim_it->first); @@ -5044,6 +5581,16 @@ void LLVOAvatar::processAnimationStateChanges() ++anim_it; } + + + + + + + + + + // clear source information for animations which have been stopped if (mIsSelf) { @@ -5064,6 +5611,70 @@ void LLVOAvatar::processAnimationStateChanges() stop_glerror(); } +//Here's that undeform function I was talking about. -HGB +std::string undeformers[] = +{ + "7a8a3dfc-acd1-7ac3-9cdf-71cd9be89969", + "3feba1c0-971b-f2bb-1b9c-79e81b096c94", + "383ef55f-5e70-02fb-8ef4-1b591b09fd49", + "e2f6bc07-97a5-1f55-6c5f-fbcb02511651", + "1370bf7d-eb29-c1dd-fc3c-cc8e06d57ac0", + "5833be17-3d69-faa0-8f18-58696a326b44", + "7746596d-b88a-216a-2335-06e28167ed31", + "edf75cf0-a2f3-d126-7cdf-5009382ec10b", + "430e8872-1095-4cff-5a39-7c991f32fffb", + "a83bab1b-2ff0-4365-1b6b-6b6e52efc69d", + "7db75c3d-ae67-4312-9734-1510f12a1392", + "551b8c1f-5241-b73e-7ce2-d78fc4ac316f", + "91d73df8-5dfa-e1f2-0a32-77327e56b8dd", + "b2b2fb93-aad5-a7a8-9731-ee8ed72f7acd", + "984eabe8-0953-a93b-f33d-6e21c405cc78", + "f6212696-dc74-b17f-4ea8-f90c37cb032e", + "aa825c4d-aa84-df7d-6ae6-fbf2dcb6f281", + "14ef74d1-93ad-09cb-7a39-fbac3bd80e64" +}; + +void LLVOAvatar::undeform() +{ + if(!mIsSelf) return; + + AnimIterator anim_it; + for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) + { + AnimIterator found_anim = mSignaledAnimations.find(anim_it->first); + + if (found_anim == mSignaledAnimations.end()) + { + processSingleAnimationStateChange(anim_it->first, FALSE); + mPlayingAnimations.erase(anim_it++); + continue; + } + ++anim_it; + } + + AnimSourceIterator source_it = mAnimationSources.begin(); + + for (source_it = mAnimationSources.begin(); source_it != mAnimationSources.end();) + { + if (mSignaledAnimations.find(source_it->second) == mSignaledAnimations.end()) + { + mAnimationSources.erase(source_it++); + } + else + { + ++source_it; + } + } + U8 i=0; + for(i; i < 18; ++i) + { + gAgent.sendAnimationRequest( (LLUUID)undeformers[i], ANIM_REQUEST_START ); + startMotion((LLUUID)undeformers[i]); + } + + stop_glerror(); +} + //----------------------------------------------------------------------------- @@ -5099,6 +5710,9 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL } } } + + + else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) { mIsSitting = TRUE; @@ -5151,9 +5765,22 @@ void LLVOAvatar::resetAnimations() flushAllMotions(); } +//----------------------------------------------------------------------------- +// getIdleTime() +//----------------------------------------------------------------------------- + +std::string LLVOAvatar::getIdleTime() +{ + F32 elapsed_time = mIdleTimer.getElapsedTimeF32(); + U32 minutes = (U32)(elapsed_time/60); + + std::string output = llformat("(idle %dmin)", minutes); + return output; +} + //----------------------------------------------------------------------------- // startMotion() -// id is the asset if of the animation to start +// id is the asset id of the animation to start // time_offset is the offset into the animation at which to start playing //----------------------------------------------------------------------------- BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) @@ -5200,6 +5827,37 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) return LLCharacter::startMotion(id, time_offset); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //----------------------------------------------------------------------------- // stopMotion() //----------------------------------------------------------------------------- @@ -5270,6 +5928,11 @@ LLVector3 LLVOAvatar::getVolumePos(S32 joint_index, LLVector3& volume_offset) return mCollisionVolumes[joint_index].getVolumePos(volume_offset); } + + + + + //----------------------------------------------------------------------------- // findCollisionVolume() //----------------------------------------------------------------------------- @@ -6228,6 +6891,21 @@ void LLVOAvatar::hideSkirt() } + + + + + + + + + + + + + + + //----------------------------------------------------------------------------- // requestLayerSetUpdate() //----------------------------------------------------------------------------- @@ -6545,6 +7223,30 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) } } + + + + + + + + + + + + + + + + + + + + + + + + //----------------------------------------------------------------------------- // getOffObject() //----------------------------------------------------------------------------- @@ -6622,6 +7324,16 @@ void LLVOAvatar::getOffObject() } } + + + + + + + + + + //----------------------------------------------------------------------------- // findAvatarFromAttachment() //----------------------------------------------------------------------------- @@ -6710,6 +7422,20 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id) } + + + + + + + + + + + + + + //----------------------------------------------------------------------------- // static // onLocalTextureLoaded() @@ -6988,6 +7714,7 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**) } } + BOOL LLVOAvatar::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw) { if (!isIndexLocalTexture(index)) return FALSE; @@ -7156,6 +7883,11 @@ BOOL LLVOAvatar::updateIsFullyLoaded() } + + + + + BOOL LLVOAvatar::isFullyLoaded() { if (gSavedSettings.getBOOL("RenderUnloadedAvatar")) @@ -7604,7 +8336,7 @@ void LLVOAvatar::clearChat() S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) { // If the texture is not local, we don't care and treat it as fully loaded - if (!isIndexLocalTexture(index)) return 0; + if (!isIndexLocalTexture(index)) return FALSE; LocalTextureData &local_tex_data = mLocalTextureData[index]; if (index >= 0 @@ -7810,6 +8542,10 @@ void LLVOAvatar::releaseUnnecessaryTextures() } } + + + + //----------------------------------------------------------------------------- // static // onCustomizeStart() @@ -8390,6 +9126,24 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + + + + + + + + + + + + + + + + + + if (is_first_appearance_message || (param->getWeight() != newWeight)) { //llinfos << "Received update for param " << param->getDisplayName() << " at value " << newWeight << llendl; @@ -8942,10 +9696,7 @@ void LLVOAvatar::dumpLocalTextures() llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " << "(" << image->getWidth() << ", " << image->getHeight() << ") " -// -//#if !LL_RELEASE_FOR_DOWNLOAD -#if 1 -// +#if !LL_RELEASE_FOR_DOWNLOAD // End users don't get to trivially see avatar texture IDs, // makes textures easier to steal << image->getID() << " " @@ -9665,6 +10416,8 @@ void LLVOAvatar::idleUpdateRenderCost() mText->setColor(LLColor4(red,green,0,1)); } + + // static BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { @@ -9723,6 +10476,9 @@ U32 calc_shame(LLVOVolume* volume, std::set &textures) U32 bump = 0; U32 planar = 0; + const LLVector3& sc = volume->getScale(); + scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2]; + if (volume->isFlexible()) { flexi = 1; @@ -9732,9 +10488,6 @@ U32 calc_shame(LLVOVolume* volume, std::set &textures) particles = 1; } - const LLVector3& sc = volume->getScale(); - scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2]; - LLDrawable* drawablep = volume->mDrawable; if (volume->isSculpted()) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6c4efd9c5..aebfa6aa9 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -50,6 +50,8 @@ #include "llwearable.h" #include "llvoavatardefines.h" + + extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; extern const LLUUID ANIM_AGENT_EDITING; @@ -65,12 +67,15 @@ class LLTexLayerSet; class LLVoiceVisualizer; class LLHUDText; class LLHUDEffectSpiral; + class LLTexGlobalColor; class LLVOAvatarBoneInfo; class LLVOAvatarSkeletonInfo; class LLVOAvatarXmlInfo; + + //------------------------------------------------------------------------ // LLVOAvatar //------------------------------------------------------------------------ @@ -90,6 +95,7 @@ public: // void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); + LLColor4 getTagColorByUUID(std::string uuid_str); std::string extraMetadata; // @@ -112,6 +118,7 @@ public: void idleUpdateLipSync(bool voice_enabled); void idleUpdateLoadingEffect(); void idleUpdateWindEffect(); + void idleUpdateNameTag(const LLVector3& root_pos_last); void idleUpdateRenderCost(); void idleUpdateTractorBeam(); @@ -213,7 +220,16 @@ public: static void onCustomizeStart(); static void onCustomizeEnd(); -public: + + + + LLFrameTimer mIdleTimer; + void undeform(); + + std::string getIdleTime(); + + + static void dumpTotalLocalTextureByteCount(); protected: void getLocalTextureByteCount( S32* gl_byte_count ); @@ -244,7 +260,7 @@ public: void addChat(const LLChat& chat); void clearChat(); - void startTyping() { mTyping = TRUE; mTypingTimer.reset(); } + void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();} void stopTyping() { mTyping = FALSE; } // Returns "FirstName LastName" @@ -276,6 +292,7 @@ public: void dirtyMesh(); // Dirty the avatar mesh void hideSkirt(); + virtual void setParent(LLViewerObject* parent); virtual void addChild(LLViewerObject *childp); virtual void removeChild(LLViewerObject *childp); @@ -357,11 +374,17 @@ public: void setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ); void setupComposites(); + + + + + //-------------------------------------------------------------------- // Handling partially loaded avatars (Ruth) //-------------------------------------------------------------------- public: BOOL isFullyLoaded(); + BOOL updateIsFullyLoaded(); private: BOOL mFullyLoaded; @@ -502,6 +525,59 @@ private: BOOL mAppearanceAnimSetByUser; F32 mLastAppearanceBlendTime; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //-------------------------------------------------------------------- // Attachments //-------------------------------------------------------------------- @@ -534,6 +610,7 @@ public: static BOOL sJointDebug; // output total number of joints being touched for each avatar static BOOL sDebugAvatarRotation; + static S32 sNumVisibleAvatars; // Number of instances of this class //-------------------------------------------------------------------- @@ -546,6 +623,19 @@ public: LLViewerJoint mRoot; // avatar skeleton BOOL mIsSitting; // sitting state + static bool updateClientTags(); + static bool loadClientTags(); + + + + + + + + + + + //-------------------------------------------------------------------- // Private member variables. //-------------------------------------------------------------------- @@ -601,10 +691,21 @@ private: LLVoiceVisualizer* mVoiceVisualizer; int mCurrentGesticulationLevel; + + + + // Animation timer LLTimer mAnimTimer; F32 mTimeLast; + static LLSD sClientResolutionList; + + bool isUnknownClient(); + static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar); + friend class LLFloaterAvatarList; + + LLPointer mBeam; LLFrameTimer mBeamTimer; @@ -729,7 +830,6 @@ private: U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts - }; typedef std::vector bakedtexturedata_vec_t; bakedtexturedata_vec_t mBakedTextureData; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index c8ce227da..9df2dce0d 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -155,12 +155,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Linden Lab" - VALUE "FileDescription", "Snowglobe" + VALUE "FileDescription", "Ascent" VALUE "FileVersion", "1.4.0.0" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2010, Linden Research, Inc." - VALUE "OriginalFilename", "Snowglobe.exe" - VALUE "ProductName", "Snowglobe" + VALUE "OriginalFilename", "Ascent.exe" + VALUE "ProductName", "Ascent" VALUE "ProductVersion", "1.4.0.0" END END diff --git a/indra/newview/scriptcounter.cpp b/indra/newview/scriptcounter.cpp new file mode 100644 index 000000000..6572d41af --- /dev/null +++ b/indra/newview/scriptcounter.cpp @@ -0,0 +1,403 @@ +/* Copyright (c) 2009 + * + * Modular Systems All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. Neither the name Modular Systems nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS “AS IS” + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llchat.h" +#include "llfloaterchat.h" +#include "scriptcounter.h" +#include "llselectmgr.h" +#include "llviewerobjectlist.h" +#include "llvoavatar.h" +#include "llviewerregion.h" +#include "llwindow.h" +#include "lltransfersourceasset.h" +#include "llviewercontrol.h" +#include "llviewernetwork.h" +#include "llviewerobject.h" +#include + +ScriptCounter* ScriptCounter::sInstance; +U32 ScriptCounter::invqueries; +U32 ScriptCounter::status; +U32 ScriptCounter::scriptcount; +LLUUID ScriptCounter::reqObjectID; +LLDynamicArray ScriptCounter::delUUIDS; +bool ScriptCounter::doDelete; +std::set ScriptCounter::objIDS; +int ScriptCounter::objectCount; +LLViewerObject* ScriptCounter::foo; +void cmdline_printchat(std::string chat); +std::stringstream ScriptCounter::sstr; +int ScriptCounter::countingDone; + +ScriptCounter::ScriptCounter() +{ + llassert_always(sInstance == NULL); + sInstance = this; + +} + +ScriptCounter::~ScriptCounter() +{ + sInstance = NULL; +} +void ScriptCounter::init() +{ + if(!sInstance) + sInstance = new ScriptCounter(); + status = IDLE; +} + +LLVOAvatar* find_avatar_from_object( LLViewerObject* object ); + +LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ); + +void ScriptCounter::showResult(std::string output) +{ + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = output; + LLFloaterChat::addChat(chat); + //sstr << scriptcount; + //cmdline_printchat(sstr.str()); + init(); +} + +void ScriptCounter::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data) +{ + LLUUID object_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID,object_id ); + std::string name; + std::string user_msg; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); + if(reqObjectID.notNull()) + if(object_id == reqObjectID) + { + if(doDelete) + { + user_msg = llformat("Deleted %u scripts from object %s.", scriptcount, name); + } + else + { + user_msg = llformat("Counted %u scripts in object %s.", scriptcount, name); + } + reqObjectID.setNull(); + if(countingDone) + { + showResult(user_msg); + } + } +} + +void ScriptCounter::processObjectProperties(LLMessageSystem* msg, void** user_data) +{ + std::string user_msg; + LLUUID object_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID,object_id ); + std::string name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); + if(reqObjectID.notNull()) + if(object_id == reqObjectID) + { + if(doDelete) + { + user_msg = llformat("Deleted %u scripts from object %s.", scriptcount, name); + } + else + { + user_msg = llformat("Counted %u scripts in object %s.", scriptcount, name); + } + reqObjectID.setNull(); + if(countingDone) + { + showResult(user_msg); + } + } +} + +void ScriptCounter::serializeSelection(bool delScript) +{ + LLDynamicArray catfayse; + foo=LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + sstr.str(""); + doDelete=false; + scriptcount=0; + objIDS.clear(); + delUUIDS.clear(); + objectCount=0; + countingDone=false; + reqObjectID.setNull(); + if(foo) + { + if(foo->isAvatar()) + { + LLVOAvatar* av=find_avatar_from_object(foo); + if(av) + { + for (LLVOAvatar::attachment_map_t::iterator iter = av->mAttachmentPoints.begin(); + iter != av->mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment->getValid()) + continue ; + LLViewerObject* object = attachment->getObject(); + if(object) + { + catfayse.put(object); + objectCount++; + } + } + } + } + else + { + for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + if(object) + { + catfayse.put(object); + objectCount++; + } + } + doDelete=delScript; + } + F32 throttle = gSavedSettings.getF32("OutBandwidth"); + if((throttle == 0.f) || (throttle > 128000.f)) + { + gMessageSystem->mPacketRing.setOutBandwidth(128000); + gMessageSystem->mPacketRing.setUseOutThrottle(TRUE); + } + showResult(llformat("Counting scripts, please wait...")); + if((objectCount == 1) && !(foo->isAvatar())) + { + LLViewerObject *reqObject=((LLViewerObject*)foo->getRoot()); + if(reqObject->isAvatar()) + { + for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); + iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++ ) + { + LLSelectNode *nodep = *iter; + LLViewerObject* objectp = nodep->getObject(); + if (objectp->isRootEdit()) + { + reqObjectID=objectp->getID(); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectSelect); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); + msg->sendReliable(gAgent.getRegionHost()); + break; + } + } + } + else + { + reqObjectID=reqObject->getID(); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_RequestFlags, 0 ); + msg->addUUIDFast(_PREHASH_ObjectID, reqObjectID); + gAgent.sendReliableMessage(); + } + } + serialize(catfayse); + } +} + +void ScriptCounter::serialize(LLDynamicArray objects) +{ + init(); + status = COUNTING; + for(LLDynamicArray::iterator itr = objects.begin(); itr != objects.end(); ++itr) + { + LLViewerObject* object = *itr; + if (object) + subserialize(object); + } + if(invqueries == 0) + init(); +} + +void ScriptCounter::subserialize(LLViewerObject* linkset) +{ + LLViewerObject* object = linkset; + LLDynamicArray count_objects; + count_objects.put(object); + LLViewerObject::child_list_t child_list = object->getChildren(); + for (LLViewerObject::child_list_t::iterator i = child_list.begin(); i != child_list.end(); ++i) + { + LLViewerObject* child = *i; + if(!child->isAvatar()) + count_objects.put(child); + } + S32 object_index = 0; + while ((object_index < count_objects.count())) + { + object = count_objects.get(object_index++); + LLUUID id = object->getID(); + objIDS.insert(id.asString()); + llinfos << "Counting scripts in prim " << object->getID().asString() << llendl; + object->registerInventoryListener(sInstance,NULL); + object->dirtyInventory(); + object->requestInventory(); + invqueries += 1; + } +} + +void ScriptCounter::completechk() +{ + std::string user_msg; + llinfos << "Completechk called." << llendl; + if(invqueries == 0) + { + llinfos << "InvQueries = 0..." << llendl; + if(reqObjectID.isNull()) + { + llinfos << "reqObjectId is null..." << llendl; + if(foo->isAvatar()) + { + int valid=1; + LLVOAvatar *av=find_avatar_from_object(foo); + LLNameValue *firstname; + LLNameValue *lastname; + if(!av) + valid=0; + else + { + firstname = av->getNVPair("FirstName"); + lastname = av->getNVPair("LastName"); + if(!firstname || !lastname) + valid=0; + if(valid) + { + user_msg = llformat("Counted %u scripts in %u attachments on %s %s.", scriptcount, objectCount, firstname->getString(), lastname->getString()); + //sstr << "Counted scripts from " << << " attachments on " << firstname->getString() << " " << lastname->getString() << ": "; + } + } + if(!valid) + { + user_msg = llformat("Counted %u scripts in %u attachments on selected avatar.", scriptcount, objectCount); + //sstr << "Counted scripts from " << objectCount << " attachments on avatar: "; + } + } + else + { + if(doDelete) + { + user_msg = llformat("Deleted %u scripts in %u objects.", scriptcount, objectCount); + //sstr << "Deleted scripts in " << objectCount << " objects: "; + } + else + { + user_msg = llformat("Counted %u scripts in %u objects.", scriptcount, objectCount); + //sstr << "Counted scripts in " << objectCount << " objects: "; + } + } + F32 throttle = gSavedSettings.getF32("OutBandwidth"); + if(throttle != 0.f) + { + gMessageSystem->mPacketRing.setOutBandwidth(throttle); + gMessageSystem->mPacketRing.setUseOutThrottle(TRUE); + } + else + { + gMessageSystem->mPacketRing.setOutBandwidth(0.0); + gMessageSystem->mPacketRing.setUseOutThrottle(FALSE); + } + llinfos << "Sending readout to chat..." << llendl; + showResult(user_msg); + } + else + countingDone=true; + } +} + +void ScriptCounter::inventoryChanged(LLViewerObject* obj, + InventoryObjectList* inv, + S32 serial_num, + void* user_data) +{ + llinfos << "InventoryChanged called..." << llendl; + if(status == IDLE) + { + obj->removeInventoryListener(sInstance); + return; + } + if(objIDS.find(obj->getID().asString()) != objIDS.end()) + { + if(inv) + { + InventoryObjectList::const_iterator it = inv->begin(); + InventoryObjectList::const_iterator end = inv->end(); + for( ; it != end; ++it) + { + LLInventoryObject* asset = (*it); + if(asset) + { + if(asset->getType() == LLAssetType::AT_LSL_TEXT) + { + scriptcount+=1; + if(doDelete==true) + delUUIDS.push_back(asset->getUUID()); + } + } + } + if(doDelete==true) + { + while (delUUIDS.count() > 0) + { + const LLUUID toDelete=delUUIDS[0]; + delUUIDS.remove(0); + if(toDelete.notNull()) + obj->removeInventory(toDelete); + } + } + } + llinfos << "Attempting completechk..." << llendl; + invqueries -= 1; + objIDS.erase(obj->getID().asString()); + reqObjectID.setNull(); + obj->removeInventoryListener(sInstance); + completechk(); + } +} \ No newline at end of file diff --git a/indra/newview/scriptcounter.h b/indra/newview/scriptcounter.h new file mode 100644 index 000000000..95c6c9985 --- /dev/null +++ b/indra/newview/scriptcounter.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2009 + * + * Modular Systems All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. Neither the name Modular Systems nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS “AS IS” + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "llagent.h" +#include "llvoinventorylistener.h" + +class ScriptCounter : public LLVOInventoryListener +{ +public: + ScriptCounter(); + ~ScriptCounter(); + +private: + static ScriptCounter* sInstance; + static void init(); + static LLSD* getprim(LLUUID id); + static void completechk(); +public: + static void processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data); + static void processObjectProperties(LLMessageSystem* msg, void** user_data); + void inventoryChanged(LLViewerObject* obj, + InventoryObjectList* inv, + S32 serial_num, + void* data); + + static ScriptCounter* getInstance(){ init(); return sInstance; } + + static void serialize(LLDynamicArray objects); + static void serializeSelection(bool delScript); + static void finalize(LLSD data); + static void showResult(std::string output); + +private: + static void subserialize(LLViewerObject* linkset); + + enum ExportState { IDLE, COUNTING }; + + static U32 status; + static U32 invqueries; + static U32 scriptcount; + static LLUUID reqObjectID; + static std::set objIDS; + static LLDynamicArray delUUIDS; + static int objectCount; + static LLViewerObject* foo; + static bool doDelete; + static std::stringstream sstr; + static int countingDone; +}; \ No newline at end of file diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index aa0b93a99..076dcaf97 100644 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -1,7 +1,7 @@ - Snowglobe includes source code contributions of the following residents: Able Whitman, Adam Marker, Agathos Frascati, Aimee Trescothick, Alejandro Rosenthal, Aleric Inglewood, Alissa Sabre, Angus Boyd, Ann Congrejo, Argent Stonecutter, Asuka Neely, Balp Allen, Benja Kepler, Biancaluce Robbiani, Blakar Ogre, blino Nakamura, Boroondas Gupte, Bulli Schumann, bushing Spatula, Carjay McGinnis, Catherine Pfeffer, Celierra Darling, Cron Stardust, Dale Glass, Drewan Keats, Dylan Haskell, Dzonatas Sol, Eddy Stryker, EponymousDylan Ra, Eva Nowicka, Farallon Greyskin, Feep Larsson, Flemming Congrejo, Fluf Fredriksson, Fremont Cunningham, Geneko Nemeth, Gigs Taggart, Ginko Bayliss, Grazer Kline, Gudmund Shepherd, Hamncheese Omlet, HappySmurf Papp, Henri Beauchamp, Hikkoshi Sakai, Hiro Sommambulist, Hoze Menges, Ian Kas, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Joghert LeSabre, Kage Pixel, Ken March, Kerutsen Sellery, Khyota Wulluf, Kunnis Basiat, Lisa Lowe, Lockhart Cordoso, maciek marksman, Magnus Balczo, Malwina Dollinger, march Korda, Matthew Dowd, McCabe Maxsted, Michelle2 Zenovka, Mm Alder, Mr Greggan, Nicholaz Beresford, Nounouch Hapmouche, Patric Mills, Paul Churchill, Paula Innis, Peekay Semyorka, Peter Lameth, Pf Shan, princess niven, Renault Clio, Ringo Tuxing, Robin Cornelius, Ryozu Kojima, Salahzar Stenvaag, Sammy Frederix, Scrippy Scofield, Seg Baphomet, Sergen Davies, SignpostMarv Martin, Simon Nolan, SpacedOut Frye, Sporked Friis, Stevex Janus, Still Defiant, Strife Onizuka, Tayra Dagostino, TBBle Kurosawa, Teardrops Fall, tenebrous pau, Tharax Ferraris, Thickbrick Sleaford, Thraxis Epsilon, tiamat bingyi, TraductoresAnonimos Alter, Tue Torok, Vadim Bigbear, Vixen Heron, Whoops Babii, Wilton Lundquist, Zarkonnen Decosta, Zi Ree, Zipherius Turas + Ascent includes source code contributions of the following residents: Able Whitman, Adam Marker, Agathos Frascati, Aimee Trescothick, Alejandro Rosenthal, Aleric Inglewood, Alissa Sabre, Angus Boyd, Ann Congrejo, Argent Stonecutter, Asuka Neely, Balp Allen, Benja Kepler, Biancaluce Robbiani, Blakar Ogre, blino Nakamura, Boroondas Gupte, Bulli Schumann, bushing Spatula, Carjay McGinnis, Catherine Pfeffer, Celierra Darling, Cron Stardust, Dale Glass, Drewan Keats, Dylan Haskell, Dzonatas Sol, Eddy Stryker, EponymousDylan Ra, Eva Nowicka, Farallon Greyskin, Feep Larsson, Flemming Congrejo, Fluf Fredriksson, Fremont Cunningham, Geneko Nemeth, Gigs Taggart, Ginko Bayliss, Grazer Kline, Gudmund Shepherd, Hamncheese Omlet, HappySmurf Papp, Henri Beauchamp, Hikkoshi Sakai, Hiro Sommambulist, Hoze Menges, Ian Kas, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Joghert LeSabre, Kage Pixel, Ken March, Kerutsen Sellery, Khyota Wulluf, Kunnis Basiat, Lisa Lowe, Lockhart Cordoso, maciek marksman, Magnus Balczo, Malwina Dollinger, march Korda, Matthew Dowd, McCabe Maxsted, Michelle2 Zenovka, Mm Alder, Mr Greggan, Nicholaz Beresford, Nounouch Hapmouche, Patric Mills, Paul Churchill, Paula Innis, Peekay Semyorka, Peter Lameth, Pf Shan, princess niven, Renault Clio, Ringo Tuxing, Robin Cornelius, Ryozu Kojima, Salahzar Stenvaag, Sammy Frederix, Scrippy Scofield, Seg Baphomet, Sergen Davies, SignpostMarv Martin, Simon Nolan, SpacedOut Frye, Sporked Friis, Stevex Janus, Still Defiant, Strife Onizuka, Tayra Dagostino, TBBle Kurosawa, Teardrops Fall, tenebrous pau, Tharax Ferraris, Thickbrick Sleaford, Thraxis Epsilon, tiamat bingyi, TraductoresAnonimos Alter, Tue Torok, Vadim Bigbear, Vixen Heron, Whoops Babii, Wilton Lundquist, Zarkonnen Decosta, Zi Ree, Zipherius Turas Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl und vielen anderen. diff --git a/indra/newview/skins/default/xui/en-us/floater_about.xml b/indra/newview/skins/default/xui/en-us/floater_about.xml index 5d803c112..ea12a0127 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about.xml @@ -2,23 +2,13 @@ + title="About Ascent" width="470"> - Inertia is a fork of snowglobe 1 trunk focusing on speed, security and making it easy to debug issues within SL - - Inertia includes source code contributions of the following people: Hazim Gazov, phr0z3nt0ast, Henri Beauchamp, Simman Federal, Apelsin, JCool410 Wildcat - - Inertia binary builds and support by: Simman Federal, electronbeam, asianman - - Significant contribution of the entire source base for SLPE and support of said source by: Philip - - Decryption advice and source code provided by: Anonymous, Anonymous furry - - Snowglobe includes source code contributions of the following residents: Able Whitman, Adam Marker, Agathos Frascati, Aimee Trescothick, Alejandro Rosenthal, Aleric Inglewood, Alissa Sabre, Angus Boyd, Ann Congrejo, Argent Stonecutter, Asuka Neely, Balp Allen, Benja Kepler, Biancaluce Robbiani, Blakar Ogre, blino Nakamura, Boroondas Gupte, Bulli Schumann, bushing Spatula, Carjay McGinnis, Catherine Pfeffer, Celierra Darling, Cron Stardust, Dale Glass, Drewan Keats, Dylan Haskell, Dzonatas Sol, Eddy Stryker, EponymousDylan Ra, Eva Nowicka, Farallon Greyskin, Feep Larsson, Flemming Congrejo, Fluf Fredriksson, Fremont Cunningham, Geneko Nemeth, Gigs Taggart, Ginko Bayliss, Grazer Kline, Gudmund Shepherd, Hamncheese Omlet, HappySmurf Papp, Henri Beauchamp, Hikkoshi Sakai, Hiro Sommambulist, Hoze Menges, Ian Kas, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Joghert LeSabre, Kage Pixel, Ken March, Kerutsen Sellery, Khyota Wulluf, Kunnis Basiat, Lisa Lowe, Lockhart Cordoso, maciek marksman, Magnus Balczo, Malwina Dollinger, march Korda, Matthew Dowd, McCabe Maxsted, Michelle2 Zenovka, Mm Alder, Mr Greggan, Nicholaz Beresford, Nounouch Hapmouche, Patric Mills, Paul Churchill, Paula Innis, Peekay Semyorka, Peter Lameth, Pf Shan, princess niven, Renault Clio, Ringo Tuxing, Robin Cornelius, Ryozu Kojima, Salahzar Stenvaag, Sammy Frederix, Scrippy Scofield, Seg Baphomet, Sergen Davies, SignpostMarv Martin, Simon Nolan, SpacedOut Frye, Sporked Friis, Stevex Janus, Still Defiant, Strife Onizuka, Tayra Dagostino, TBBle Kurosawa, Teardrops Fall, tenebrous pau, Tharax Ferraris, Thickbrick Sleaford, Thraxis Epsilon, tiamat bingyi, TraductoresAnonimos Alter, Tue Torok, Vadim Bigbear, Vixen Heron, Whoops Babii, Wilton Lundquist, Zarkonnen Decosta, Zi Ree, Zipherius Turas + Ascent includes source code contributions of the following residents: Able Whitman, Adam Marker, Agathos Frascati, Aimee Trescothick, Alejandro Rosenthal, Aleric Inglewood, Alissa Sabre, Angus Boyd, Ann Congrejo, Argent Stonecutter, Asuka Neely, Balp Allen, Benja Kepler, Biancaluce Robbiani, Blakar Ogre, blino Nakamura, Boroondas Gupte, Bulli Schumann, bushing Spatula, Carjay McGinnis, Catherine Pfeffer, Celierra Darling, Cron Stardust, Dale Glass, Drewan Keats, Dylan Haskell, Dzonatas Sol, Eddy Stryker, EponymousDylan Ra, Eva Nowicka, Farallon Greyskin, Feep Larsson, Flemming Congrejo, Fluf Fredriksson, Fremont Cunningham, Geneko Nemeth, Gigs Taggart, Ginko Bayliss, Grazer Kline, Gudmund Shepherd, Hamncheese Omlet, HappySmurf Papp, Henri Beauchamp, Hikkoshi Sakai, Hiro Sommambulist, Hoze Menges, Ian Kas, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Joghert LeSabre, Kage Pixel, Ken March, Kerutsen Sellery, Khyota Wulluf, Kunnis Basiat, Lisa Lowe, Lockhart Cordoso, maciek marksman, Magnus Balczo, Malwina Dollinger, march Korda, Matthew Dowd, McCabe Maxsted, Michelle2 Zenovka, Mm Alder, Mr Greggan, Nicholaz Beresford, Nounouch Hapmouche, Patric Mills, Paul Churchill, Paula Innis, Peekay Semyorka, Peter Lameth, Pf Shan, princess niven, Renault Clio, Ringo Tuxing, Robin Cornelius, Ryozu Kojima, Salahzar Stenvaag, Sammy Frederix, Scrippy Scofield, Seg Baphomet, Sergen Davies, SignpostMarv Martin, Simon Nolan, SpacedOut Frye, Sporked Friis, Stevex Janus, Still Defiant, Strife Onizuka, Tayra Dagostino, TBBle Kurosawa, Teardrops Fall, tenebrous pau, Tharax Ferraris, Thickbrick Sleaford, Thraxis Epsilon, tiamat bingyi, TraductoresAnonimos Alter, Tue Torok, Vadim Bigbear, Vixen Heron, Whoops Babii, Wilton Lundquist, Zarkonnen Decosta, Zi Ree, Zipherius Turas Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others. diff --git a/indra/newview/skins/default/xui/en-us/floater_about_land.xml b/indra/newview/skins/default/xui/en-us/floater_about_land.xml index 93ea17167..84a9e2ab2 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about_land.xml @@ -85,7 +85,10 @@ mouse_opaque="true" name="GroupText" v_pad="0" width="250" />