diff options
509 files changed, 21692 insertions, 14487 deletions
@@ -10,7 +10,7 @@ syntax: glob .*.swp #OSX image cache file *.DS_Store -*.orig +#*.orig LICENSES indra/.distcc build-linux-* @@ -50,6 +50,11 @@ indra/web/doc/asset-upload/plugins/verify-texture installed.xml libraries tarfile_tmp +debian/secondlife-viewer* +debian/secondlife-appearance-utility* +debian/files +build-stamp +configure-stamp ^indra/lib/python/mulib.* ^web/locale.* ^web/secondlife.com.* @@ -69,4 +74,4 @@ glob:indra/newview/filters.xml glob:indra/newview/avatar_icons_cache.txt glob:indra/newview/avatar_lad.log glob:*.diff -*.rej +#*.rej @@ -72,35 +72,35 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 DRTVWR-38_2.5.2-release 461c8c65b5c799ddfe365422f9be9c0095d91e7d 2.6.0-beta1-tip 9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2 9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2 +42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release +42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1 c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1 +c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release +c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release 56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1 d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1 -42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release -42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release -c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release -c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release +214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release +214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release 52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1 d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1 0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2 0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2 +8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release +8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release 3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work -214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release -214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release 7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1 7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1 -8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release -8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release 800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1 bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1 -5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release dac76a711da5f1489a01c1fa62ec97d99c25736d DRTVWR-51_2.6.6-release +5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1 beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1 be2000b946f8cb3de5f44b2d419287d4c48ec4eb 2.6.8-release @@ -119,50 +119,50 @@ e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start 9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1 e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1 -6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release +6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start 6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1 be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1 +057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release +057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release 19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1 09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1 +6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release +6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1 -057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release -057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release -6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release -6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release +493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release +493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start 2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1 2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1 -493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release -493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release -54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start -ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start 29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release 29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release 4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix 4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix +54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start +ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start 599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1 599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1 +fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release +fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release 6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1 b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1 -fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release -fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release +1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release +1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release 82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start 364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1 364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1 f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start 42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1 42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1 -1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release -1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2 e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2 b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start @@ -170,9 +170,9 @@ b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1 61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2 61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2 -586907287be581817b2422b5137971b22d54ea48 3.0.4-start 0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release 0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release +586907287be581817b2422b5137971b22d54ea48 3.0.4-start 92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start 2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1 @@ -193,11 +193,11 @@ e440cd1dfbd128d7d5467019e497f7f803640ad6 DRTVWR-95_3.2.0-beta1 c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start 9e390d76807fa70d356b8716fb83b8ce42a629ef 3.2.1-beta1 9e390d76807fa70d356b8716fb83b8ce42a629ef DRTVWR-100_3.2.1-beta1 +a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release +a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release 40b46edba007d15d0059c80864b708b99c1da368 3.2.2-start 523df3e67378541498d516d52af4402176a26bac 3.2.2-beta1 523df3e67378541498d516d52af4402176a26bac DRTVWR-102_3.2.2-beta1 -a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release -a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release 80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start @@ -248,57 +248,67 @@ bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156 6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148 2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155 24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153 +a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159 +9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157 5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160 f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1 f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144 -2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164 +089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161 600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162 +c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163 +2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164 80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165 fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2 af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169 4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3 6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release -a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159 -9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157 -089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161 -c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163 b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171 050e48759337249130f684b4a21080b683f61732 DRTVWR-168 09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170 f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158 f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1 +005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167 bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173 cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174 82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2 57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176 eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177 a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3 +888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175 4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180 5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183 6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4 9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184 ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5 28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release -005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167 -888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175 a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182 1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1 -9ee9387789701d597130f879d9011a4958753862 DRTVWR-189 +81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186 47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190 +cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181 +c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188 +9ee9387789701d597130f879d9011a4958753862 DRTVWR-189 421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192 +4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191 33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195 e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193 +78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194 7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196 ae5c83dd61d2d37c45f1d5b8bf2b036d87599f1b DRTVWR-198 507bdfbd6bf844a511c1ffeda4baa80016ed1346 DRTVWR-197 b1dbb1a83f48f93f6f878cff9e52d2cb635e145c 3.4.0-beta2 37402e2b19af970d51b0a814d79892cc5647532b DRTVWR-200 182a9bf30e81070361bb020a78003b1cf398e79c 3.4.0-beta3 +248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203 6dfb0fba782c9233dd95f24ec48146db0d3f210b DRTVWR-199 7c9102fb998885621919f2474a002c35b583539b 3.3.4-release2 7649a3dff5ec22d3727377e5f02efd0f421e4cb5 DRTVWR-201 84fb70dfe3444e75a44fb4bee43e2fc8221cebdd 3.4.0-beta4 +de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202 573e863be2f26d3687161def4b9fea9b7038dda8 3.4.0-beta5 +34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag +6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205 +7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206 8c9085066c78ed5f6c9379dc054c82a6fcdb1851 DRTVWR-207 351eea5f9dc192fc5ddea3b02958de97677a0a12 3.3.4-release3 af7b28e75bd5a629cd9e0dc46fb3f1757626f493 DRTVWR-212 @@ -309,6 +319,7 @@ ceed0b65a69f1eac20d523e0203320a32f9a3f3c DRTVWR-215 97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release 5adb2b8f96c3cac88ad7c7d996d707f1b29df336 3.4.1-beta1 b3f74858a1c8720c82d0978f3877a3fc8ba459ec 3.4.1-beta1a +b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219 2b779f233ee6f38c89cb921650c773a96e63da92 DRTVWR-220 0b9d95f4bfb6867cbf56eaec51633b0da2f1262d DRTVWR-221 e6e553761829dc0270eaaa712b7cb0622535b076 3.4.1-beta3 @@ -333,36 +344,31 @@ baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12 e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release -81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186 -cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181 -c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188 -4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191 -78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194 -248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203 -de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202 -34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag -6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205 -7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206 -b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219 32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217 704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1 +d799593b53ed733862e9a13871e318e886469377 DRTVWR-208 +e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223 288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216 e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2 +93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240 0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242 710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3 -e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243 -73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4 -16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release -d799593b53ed733862e9a13871e318e886469377 DRTVWR-208 -e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223 -93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240 2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209 f7bedce18ad52283e6072814db23318907261487 DRTVWR-238 7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210 +e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243 +73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4 +16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release 5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241 f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232 4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245 94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1 +4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229 +f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246 +39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247 +7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249 +f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230 +b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252 bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251 ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 @@ -371,31 +377,25 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258 c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259 +9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265 9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266 73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267 870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3 0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release -4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229 -f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246 -39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247 -7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249 -f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230 -b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 -9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 +391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268 b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 +a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272 +37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269 c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275 05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4 e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release -391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268 -a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272 -37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269 7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250 b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277 af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276 @@ -405,6 +405,8 @@ c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280 5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281 7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283 6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2 +37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282 +6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284 ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286 2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287 e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3 @@ -417,8 +419,6 @@ b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292 0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297 852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5 a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release -37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282 -6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284 092a9effbedd1a0276fa5ced520992ce00f96fbf CHUI-PV-0 279ef1dfc9b749a6cc499cf190fec0c090b6d682 DRTVWR-288 9b19edaf1d8ddf435f60fbbb444dd25db8f63953 3.5.0-beta1 @@ -431,4 +431,12 @@ f6ca5bb75bca975ff0bc77e71e615f6478c4559c 3.5.0-beta3 dd058a6093c493120d67c8e02c812c0f7b2d3db0 3.5.0-beta5 fd6b510e83f56830e45670c428653134899d3e25 DRTVWR-305 55339537d99afc394d1bb7fdb7d074bf321ca62f 3.5.0-beta6 +902caf2b9fdbdbc5c399c4d5ebcecaf9cb97bab8 DRTVWR-306 +5c6098fd17d40ee3a38ca6b64f6be9db7f61f0a8 3.5.0-beta7 +adc360e6bf21390d2665380951d85937cd29a604 3.5.0-release +1ada73295ed0eaa4a772ef079c29f57069342c32 DRTVWR-310 +20cdf370f5c8be6193bef6fb3a81cc3f81275191 3.5.1-beta1 +2319904200de367646b9a9442239a38d52c1eeb5 DRTVWR-313 +9d8726eca785acad694564516f16dd639faf45c0 3.5.1-beta2 +78a8fe6abf331944d6b6bb1ce1024a6bc08141f4 DRTVWR-298 50ccc12f38c3c99f03b374e32429cb043b73e2a6 DRTVWR-294 diff --git a/BuildParams b/BuildParams index e00fc384d4..c929c2d90d 100755 --- a/BuildParams +++ b/BuildParams @@ -21,6 +21,11 @@ email_status_this_is_os = true # Limit extent of codeticket updates to revisions after... codeticket_since = 3.3.0-release +# Override build system default toolchain +# Note that this will only affect automated builds. +Linux.gcc_version = /usr/bin/gcc-4.6 +Linux.cxx_version = /usr/bin/g++-4.6 + # ======================================== # Viewer Development # ======================================== diff --git a/autobuild.xml b/autobuild.xml index 8b9f7c889c..abf3e22ea1 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -18,9 +18,9 @@ <key>archive</key> <map> <key>hash</key> - <string>b2fe1c860613a68e74d4384be418ffee</string> + <string>e6071abd822c0688390382a26f8a782c</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Darwin/installer/glod-1.0pre4-darwin-20110610.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/267984/arch/Darwin/installer/glod-1.0pre4-darwin-20121211.tar.bz2</string> </map> <key>name</key> <string>darwin</string> @@ -30,9 +30,9 @@ <key>archive</key> <map> <key>hash</key> - <string>c0c64dae149d0892343e2ff300fd06b9</string> + <string>176736c52b3cde6ca8e7d9e173d91731</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Linux/installer/glod-1.0pre4-linux-20110611.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/268002/arch/Linux/installer/glod-1.0pre4-linux-20121212.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -483,14 +483,14 @@ </map> </map> </map> - <key>fmod</key> + <key>fmodex</key> <map> <key>license</key> - <string>fmod</string> + <string>fmodex</string> <key>license_file</key> - <string>LICENSES/fmod.txt</string> + <string>LICENSES/fmodex.txt</string> <key>name</key> - <string>fmod</string> + <string>fmodex</string> <key>platforms</key> <map> <key>darwin</key> @@ -498,9 +498,9 @@ <key>archive</key> <map> <key>hash</key> - <string>61ead113e6479452e6b690c84b4e9d30</string> + <string>89a3df89da75444877cf3197416fed67</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/Darwin/installer/fmod-3.75-darwin-20110222.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/270029/arch/Darwin/installer/fmodex-4.44-darwin-20130205.tar.bz2</string> </map> <key>name</key> <string>darwin</string> @@ -510,9 +510,9 @@ <key>archive</key> <map> <key>hash</key> - <string>0c61d643db54d2e5999be8254569d8b3</string> + <string>fd787931f49ece9bf99f4d1d1596f04b</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/Linux/installer/fmod-3.75-linux-20110223.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/269984/arch/Linux/installer/fmodex-4.44-linux-20130205.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -522,9 +522,9 @@ <key>archive</key> <map> <key>hash</key> - <string>d9a9a6ad86895353bcd63374a4c1a91d</string> + <string>9e0f62be63e74af18f670f864cac93da</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/CYGWIN/installer/fmod-3.75-windows-20110222.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/270026/arch/CYGWIN/installer/fmodex-4.44-windows-20130205.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -690,9 +690,9 @@ <key>archive</key> <map> <key>hash</key> - <string>26f2df1f0b0fa01e94e0253e322f3583</string> + <string>1b1f1e9975e3a671c9faf32fcf4b6d43</string> <key>url</key> - <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/glh_linear-linux-20101001.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glh_linear/rev/263308/arch/Linux/installer/glh_linear-0.0.0-linux-20120810.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -844,6 +844,42 @@ </map> </map> </map> + <key>gperftools</key> + <map> + <key>license</key> + <string>bsd</string> + <key>license_file</key> + <string>LICENSES/gperftools.txt</string> + <key>name</key> + <string>gperftools</string> + <key>platforms</key> + <map> + <key>linux</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>8aedfdcf670348c18a9991ae1b384a61</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/Linux/installer/gperftools-2.0-linux-20120727.tar.bz2</string> + </map> + <key>name</key> + <string>linux</string> + </map> + <key>windows</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>f62841804acb91e1309603a84f3f0ce8</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/CYGWIN/installer/gperftools-2.0-windows-20120727.tar.bz2</string> + </map> + <key>name</key> + <string>windows</string> + </map> + </map> + </map> <key>gstreamer</key> <map> <key>license</key> @@ -1240,6 +1276,32 @@ </map> </map> </map> + <key>llappearanceutility-source</key> + <map> + <key>license</key> + <string>TEMPORARY</string> + <key>license_file</key> + <string>LICENSES/llappearanceutility.txt</string> + <key>name</key> + <string>llappearanceutility-source</string> + <key>platforms</key> + <map> + <key>linux</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>5bc44db15eb3cca021382e40e04a9a38</string> + <key>url</key> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/271972/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130315.tar.bz2</string> + </map> + <key>name</key> + <string>linux</string> + </map> + </map> + <key>version</key> + <string>0.1</string> + </map> <key>llphysicsextensions_source</key> <map> <key>license</key> @@ -1269,9 +1331,9 @@ <key>archive</key> <map> <key>hash</key> - <string>b706fdeed4ce2182d434043dc33d9d1d</string> + <string>a6856b4d58a3b71321acad7e1fa9c8d4</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/263415/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20120814.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/265749/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20121011.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -1780,42 +1842,6 @@ </map> </map> </map> - <key>tcmalloc</key> - <map> - <key>license</key> - <string>bsd</string> - <key>license_file</key> - <string>LICENSES/google-perftools.txt</string> - <key>name</key> - <string>tcmalloc</string> - <key>platforms</key> - <map> - <key>linux</key> - <map> - <key>archive</key> - <map> - <key>hash</key> - <string>8aedfdcf670348c18a9991ae1b384a61</string> - <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/Linux/installer/gperftools-2.0-linux-20120727.tar.bz2</string> - </map> - <key>name</key> - <string>linux</string> - </map> - <key>windows</key> - <map> - <key>archive</key> - <map> - <key>hash</key> - <string>f62841804acb91e1309603a84f3f0ce8</string> - <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/CYGWIN/installer/gperftools-2.0-windows-20120727.tar.bz2</string> - </map> - <key>name</key> - <string>windows</string> - </map> - </map> - </map> <key>tut</key> <map> <key>license</key> @@ -2506,7 +2532,6 @@ <string>"Visual Studio 10"</string> <string>-DUNATTENDED:BOOL=ON</string> <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> </array> </map> <key>name</key> @@ -2595,7 +2620,6 @@ <string>-DUNATTENDED:BOOL=ON</string> <string>-DINSTALL_PROPRIETARY=FALSE</string> <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> </array> </map> <key>name</key> @@ -2683,7 +2707,6 @@ <string>-DUNATTENDED:BOOL=ON</string> <string>-DINSTALL_PROPRIETARY=FALSE</string> <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> </array> </map> <key>name</key> @@ -113,11 +113,23 @@ build() check_for "Before 'autobuild build'" ${build_dir}/packages/dictionaries "$AUTOBUILD" build --no-configure -c $variant - viewer_build_ok=$? + build_ok=$? end_section "Viewer$variant" + + # Run build extensions + if [ $build_ok -eq 0 -a -d ${build_dir}/packages/build-extensions ]; then + for extension in ${build_dir}/packages/build-extensions/*.sh; do + . $extension + if [ $build_ok -ne 0 ]; then + break + fi + done + fi + + # *TODO: Make this a build extension. package_llphysicsextensions_tpv tpvlib_build_ok=$? - if [ $viewer_build_ok -eq 0 -a $tpvlib_build_ok -eq 0 ] + if [ $build_ok -eq 0 -a $tpvlib_build_ok -eq 0 ] then echo true >"$build_dir"/build_ok else @@ -292,12 +304,86 @@ then end_section WaitParallel fi +# build debian package +if [ "$arch" == "Linux" ] +then + if $succeeded + then + if $build_viewer_deb && [ "$last_built_variant" == "Release" ] + then + begin_section "Build Viewer Debian Package" + local have_private_repo=false + # mangle the changelog + dch --force-bad-version \ + --distribution unstable \ + --newversion "${VIEWER_VERSION}" \ + "Automated build #$build_id, repository $branch revision $revision." \ + >> "$build_log" 2>&1 + + # build the debian package + $pkg_default_debuild_command >>"$build_log" 2>&1 || record_failure "\"$pkg_default_debuild_command\" failed." + + # Unmangle the changelog file + hg revert debian/changelog + + end_section "Build Viewer Debian Package" + + # Run debian extensions + if [ -d ${build_dir}/packages/debian-extensions ]; then + for extension in ${build_dir}/packages/debian-extensions/*.sh; do + . $extension + done + fi + # Move any .deb results. + mkdir -p ../packages_public + mkdir -p ../packages_private + mv ${build_dir}/packages/*.deb ../packages_public 2>/dev/null || true + mv ${build_dir}/packages/packages_private/*.deb ../packages_private 2>/dev/null || true + + # upload debian package and create repository + begin_section "Upload Debian Repository" + for deb_file in `/bin/ls ../packages_public/*.deb ../*.deb 2>/dev/null`; do + upload_item debian $deb_file binary/octet-stream + done + for deb_file in `/bin/ls ../packages_private/*.deb 2>/dev/null`; do + upload_item debian_private $deb_file binary/octet-stream + have_private_repo=true + done + + create_deb_repo + + # Rename the local debian_repo* directories so that the master buildscript + # doesn't make a remote repo again. + for debian_repo_type in debian_repo debian_repo_private; do + if [ -d "$build_log_dir/$debian_repo_type" ]; then + mv $build_log_dir/$debian_repo_type $build_log_dir/${debian_repo_type}_pushed + fi + done + + if [ $have_private_repo = true ]; then + eval "$python_command \"$redirect\" '\${private_S3PROXY_URL}${S3PREFIX}repo/$repo/rev/$revision/index.html'"\ + >"$build_log_dir/private.html" || fatal generating redirect + upload_item global_redirect "$build_log_dir/private.html" text/html + + fi + + end_section "Upload Debian Repository" + + else + echo skipping debian build + fi + else + echo skipping debian build due to failed build. + fi +fi + + # check status and upload results to S3 if $succeeded then if $build_viewer then - begin_section Upload + begin_section Upload Installer # Upload installer - note that ONLY THE FIRST ITEM uploaded as "installer" # will appear in the version manager. package=$(installer_$arch) @@ -317,8 +403,9 @@ then do upload_item symbolfile "$build_dir/$symbolfile" binary/octet-stream done - + # Upload the llphysicsextensions_tpv package, if one was produced + # *TODO: Make this an upload-extension if [ -r "$build_dir/llphysicsextensions_package" ] then llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package) @@ -332,15 +419,22 @@ then ;; esac + # Run upload extensions + if [ -d ${build_dir}/packages/upload-extensions ]; then + for extension in ${build_dir}/packages/upload-extensions/*.sh; do + . $extension + done + fi + # Upload stub installers upload_stub_installers "$build_dir_stubs" fi - end_section Upload + end_section Upload Installer else - echo skipping viewer + echo skipping upload of installer fi else - echo skipping upload of build results due to failed build. + echo skipping upload of installer due to failed build. fi # The branch independent build.sh script invoking this script will finish processing diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000000..ce54b54c6f --- /dev/null +++ b/debian/changelog @@ -0,0 +1,18 @@ +secondlife-viewer (0.3) unstable; urgency=low + + * Initial debian configuration + + -- Don Kjer <don@lindenlab.com> Wed, 04 Jul 2012 00:43:03 +0000 + +secondlife-viewer (0.2) unstable; urgency=low + + * Adding default LSB headers for squeeze + + -- Tyler Kohler <tyler@lindenlab.com> Thu, 24 Mar 2011 09:43:36 -0700 + +secondlife-viewer (0.1) unstable; urgency=low + + * Cloned from debian package skeleton. + + -- Lex Linden <lex@lindenlab.com> Mon, 20 Sep 2010 08:01:59 -0700 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000..50b9ed9a26 --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: secondlife-viewer +Section: unknown +Priority: extra +Maintainer: Don Linden <don@lindenlab.com> +Build-Depends: debhelper (>= 5) +Homepage: http://secondlife.com +Standards-Version: 3.7.2 + +Package: secondlife-viewer +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + ia32-libs, + ia32-libs-gtk +Description: Second Life Viewer + Second Life is an online virtual world developed by Linden Lab. + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000000..106fa3802f --- /dev/null +++ b/debian/copyright @@ -0,0 +1,32 @@ +Second Life Viewer Copyright: 2000-2012 Linden Research, Inc. + +License: + +3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion +APR Copyright (C) 2011 The Apache Software Foundation +Collada DOM Copyright 2006 Sony Computer Entertainment Inc. +cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) +DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. +expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. +FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. +GL Copyright (C) 1999-2004 Brian Paul. +GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. +google-perftools Copyright (c) 2005, Google Inc. +Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. +jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) +jpeglib Copyright (C) 1991-1998, Thomas G. Lane. +ogg/vorbis Copyright (C) 2002, Xiphophorus +OpenSSL Copyright (C) 1998-2008 The OpenSSL Project. +PCRE Copyright (c) 1997-2012 University of Cambridge +SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga +SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +xmlrpc-epi Copyright (C) 2000 Epinions, Inc. +zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. + +Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. + +This software contains source code provided by NVIDIA Corporation. + +All rights reserved. See licenses.txt for details. + +Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000000..2c4f8ea858 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,43 @@ +#!/bin/sh +# postinst script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postinst> `configure' <most-recently-configured-version> +# * <old-postinst> `abort-upgrade' <new version> +# * <conflictor's-postinst> `abort-remove' `in-favour' <package> +# <new-version> +# * <postinst> `abort-remove' +# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' +# <failed-install-package> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000000..a575936ab0 --- /dev/null +++ b/debian/postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postrm> `remove' +# * <postrm> `purge' +# * <old-postrm> `upgrade' <new-version> +# * <new-postrm> `failed-upgrade' <old-version> +# * <new-postrm> `abort-install' +# * <new-postrm> `abort-install' <old-version> +# * <new-postrm> `abort-upgrade' <old-version> +# * <disappearer's-postrm> `disappear' <overwriter> +# <overwriter-version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000000..f62243440f --- /dev/null +++ b/debian/preinst @@ -0,0 +1,39 @@ +#!/bin/sh +# preinst script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <new-preinst> `install' +# * <new-preinst> `install' <old-version> +# * <new-preinst> `upgrade' <old-version> +# * <old-preinst> `abort-upgrade' <new-version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/prerm b/debian/prerm new file mode 100644 index 0000000000..405b8f9c87 --- /dev/null +++ b/debian/prerm @@ -0,0 +1,42 @@ +#!/bin/sh +# prerm script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <prerm> `remove' +# * <old-prerm> `upgrade' <new-version> +# * <new-prerm> `failed-upgrade' <old-version> +# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version> +# * <deconfigured's-prerm> `deconfigure' `in-favour' +# <package-being-installed> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000000..305fc58bb4 --- /dev/null +++ b/debian/rules @@ -0,0 +1,118 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +BASEDIR=opt/linden + +VIEWER_PKG=secondlife-viewer +VIEWER_PACKAGEDIR=build-linux-i686/newview/packaged +VIEWER_DESTDIR=$(CURDIR)/debian/$(VIEWER_PKG) +VIEWER_VERSION:=$(shell dpkg-parsechangelog | grep ^Version | sed 's/^Version: //') +VIEWER_INSTALLDIR:=$(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + #$(MAKE) + #docbook-to-man debian/secondlife-viewer.sgml > secondlife-viewer.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + #-$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/secondlife-viewer. + for file in $$(find $(VIEWER_PACKAGEDIR) -type f -o -type l | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \ + # create containing directory \ + install -v -m 755 -o root -g root -d "$$(dirname "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file")"; \ + PERM=644; \ + if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + PERM=755; \ + fi; \ + if [ -L "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + REAL="$$( readlink -f $(VIEWER_PACKAGEDIR)/$$file )"; \ + RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(VIEWER_PACKAGEDIR)/~~' )"; \ + echo dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \ + dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \ + else \ + install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file"; \ + fi; \ + done + dh_link -p $(VIEWER_PKG) /$(VIEWER_INSTALLDIR)/secondlife /usr/bin/secondlife + dh_link -p $(VIEWER_PKG) $(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/viewer/SecondLife + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python + +# To add an init script, uncomment this line and edit debian/init.d and +# customize debian/secondlife-viewer.default to suit your needs. +# dh_installinit + +# To add cron jobs, uncomment this line and make a crontab file named +# debian/cron.d, and it will be installed in /etc/cron.d/ +# dh_installcron + +# dh_installinfo + dh_installman + dh_link +# dh_strip + dh_compress +# dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb +# dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/doc/contributions.txt b/doc/contributions.txt index 32dd3c1a2e..9f2f51f248 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -299,6 +299,7 @@ ChickyBabes Zuzu Christopher Organiser Ciaran Laval Cinder Roxley + BUG-2326 STORM-1703 Clara Young Coaldust Numbers @@ -1067,10 +1068,12 @@ Sheet Spotter Shnurui Troughton Shyotl Kuhr MAINT-1138 + MAINT-2334 Siana Gearz STORM-960 STORM-1088 MAINT-1138 + MAINT-2334 sicarius Thorne Sicarius Toxx SignpostMarv Martin @@ -1088,6 +1091,8 @@ SLB Wirefly Slee Mayo SEC-1075 snowy Sidran +Sovereign Engineer + MAINT-2334 SpacedOut Frye VWR-34 VWR-45 @@ -1341,3 +1346,4 @@ Zoex Flanagan + diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 001bb4b935..0a54163644 100755 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -41,6 +41,7 @@ endif ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${CMAKE_BINARY_DIR} add_subdirectory(cmake) add_subdirectory(${LIBS_OPEN_PREFIX}llaudio) +add_subdirectory(${LIBS_OPEN_PREFIX}llappearance) add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter) add_subdirectory(${LIBS_OPEN_PREFIX}llcommon) add_subdirectory(${LIBS_OPEN_PREFIX}llcorehttp) @@ -63,71 +64,53 @@ if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts) endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts) add_custom_target(viewer) -if (VIEWER) - add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) - add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) - add_subdirectory(${LIBS_OPEN_PREFIX}llui) - add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components) - - # Legacy C++ tests. Build always, run if LL_TESTS is true. - add_subdirectory(${VIEWER_PREFIX}test) - - # viewer media plugins - add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) - - # llplugin testbed code (is this the right way to include it?) - if (LL_TESTS AND NOT LINUX) - add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) - endif (LL_TESTS AND NOT LINUX) - - if (LINUX) - add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) - add_dependencies(viewer linux-crash-logger-strip-target) - elseif (DARWIN) - add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) - add_subdirectory(${VIEWER_PREFIX}mac_updater) - add_dependencies(viewer mac-updater mac-crash-logger) - elseif (WINDOWS) - add_subdirectory(${VIEWER_PREFIX}win_crash_logger) - # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake - if (EXISTS ${VIEWER_DIR}win_setup) - add_subdirectory(${VIEWER_DIR}win_setup) - endif (EXISTS ${VIEWER_DIR}win_setup) - add_subdirectory(${VIEWER_PREFIX}win_updater) - # add_dependencies(viewer windows-updater windows-setup windows-crash-logger) - add_dependencies(viewer windows-updater windows-crash-logger) - elseif (SOLARIS) - add_subdirectory(solaris_crash_logger) - add_dependencies(viewer solaris-crash-logger) - endif (LINUX) - - add_subdirectory(${VIEWER_PREFIX}newview) - add_dependencies(viewer secondlife-bin) -endif (VIEWER) - -# Linux builds the viewer and server in 2 separate projects -# In order for build server to work on linux, -# the viewer project needs a server target. -# This is not true for mac and windows. -if (LINUX) - add_custom_target(server) +add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) +add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) +add_subdirectory(${LIBS_OPEN_PREFIX}llui) +add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components) + +# Legacy C++ tests. Build always, run if LL_TESTS is true. +add_subdirectory(${VIEWER_PREFIX}test) + +# viewer media plugins +add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) + +# llplugin testbed code (is this the right way to include it?) +if (LL_TESTS AND NOT LINUX) + add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) +endif (LL_TESTS AND NOT LINUX) + +if (LINUX) + add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) + add_subdirectory(${VIEWER_PREFIX}linux_updater) + if (INSTALL_PROPRIETARY) + include(LLAppearanceUtility) + add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR}) + endif (INSTALL_PROPRIETARY) + add_dependencies(viewer linux-crash-logger-strip-target linux-updater) +elseif (DARWIN) + add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) + add_subdirectory(${VIEWER_PREFIX}mac_updater) + add_dependencies(viewer mac-updater mac-crash-logger) +elseif (WINDOWS) + add_subdirectory(${VIEWER_PREFIX}win_crash_logger) + # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake + if (EXISTS ${VIEWER_DIR}win_setup) + add_subdirectory(${VIEWER_DIR}win_setup) + endif (EXISTS ${VIEWER_DIR}win_setup) + add_subdirectory(${VIEWER_PREFIX}win_updater) + # add_dependencies(viewer windows-updater windows-setup windows-crash-logger) + add_dependencies(viewer windows-updater windows-crash-logger) +elseif (SOLARIS) + add_subdirectory(solaris_crash_logger) + add_dependencies(viewer solaris-crash-logger) endif (LINUX) -if (SERVER) - if (NOT LINUX) - add_custom_target(server) - endif (NOT LINUX) - include(${SERVER_PREFIX}Server.cmake) -endif (SERVER) - -# Windows builds include tools like VFS tool -if (SERVER) - if (WINDOWS) - add_subdirectory(${SERVER_PREFIX}tools) - endif (WINDOWS) -endif (SERVER) + +add_subdirectory(${VIEWER_PREFIX}newview) +add_dependencies(viewer secondlife-bin) if (LL_TESTS) - # Define after the custom viewer and server targets are created so + # Define after the custom targets are created so # individual apps can add themselves as dependencies add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests) endif (LL_TESTS) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 452fd5f356..fb5c759493 100755 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -2,6 +2,9 @@ # # Compilation options shared by all Second Life components. +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + include(Variables) # Portable compilation flags. @@ -150,41 +153,21 @@ if (LINUX) -pthread ) - if (SERVER) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60") - if (EXISTS /etc/debian_version) - FILE(READ /etc/debian_version DEBIAN_VERSION) - else (EXISTS /etc/debian_version) - set(DEBIAN_VERSION "") - endif (EXISTS /etc/debian_version) - - if (NOT DEBIAN_VERSION STREQUAL "3.1") - add_definitions(-DCTYPE_WORKAROUND) - endif (NOT DEBIAN_VERSION STREQUAL "3.1") - - if (EXISTS /usr/lib/mysql4/mysql) - link_directories(/usr/lib/mysql4/mysql) - endif (EXISTS /usr/lib/mysql4/mysql) - - endif (SERVER) - - if (VIEWER) - add_definitions(-DAPPID=secondlife) - add_definitions(-fvisibility=hidden) - # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway. - add_definitions(-DLL_IGNORE_SIGCHLD) - if (WORD_SIZE EQUAL 32) - add_definitions(-march=pentium4) - endif (WORD_SIZE EQUAL 32) - add_definitions(-mfpmath=sse) - #add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2 - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - # linking can be very memory-hungry, especially the final viewer link - set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory") - endif (NOT STANDALONE) - endif (VIEWER) + add_definitions(-DAPPID=secondlife) + add_definitions(-fvisibility=hidden) + # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway. + add_definitions(-DLL_IGNORE_SIGCHLD) + if (WORD_SIZE EQUAL 32) + add_definitions(-march=pentium4) + endif (WORD_SIZE EQUAL 32) + add_definitions(-mfpmath=sse) + #add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2 + if (NOT STANDALONE) + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) + # linking can be very memory-hungry, especially the final viewer link + set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory") + endif (NOT STANDALONE) set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}") @@ -198,7 +181,7 @@ if (DARWIN) # ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). # As a workaround, define _XOPEN_SOURCE before including ucontext.h. add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE) - set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") + set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") set(DARWIN_extra_cstar_flags "-mlong-branch -g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}") @@ -254,6 +237,4 @@ else (STANDALONE) ) endif (STANDALONE) -if(SERVER) - include_directories(${LIBS_PREBUILT_DIR}/include/havok) -endif(SERVER) +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index daafa00fe2..492ba2adea 100755 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -49,9 +49,7 @@ else (STANDALONE) set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/apr-1) if (LINUX) - if (VIEWER) - list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid) - endif (VIEWER) + list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid) list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} rt) endif (LINUX) endif (STANDALONE) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 569034a6fb..10a23ea068 100755 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -14,48 +14,66 @@ set(cmake_SOURCE_FILES Boost.cmake BuildVersion.cmake CARes.cmake - CURL.cmake CMakeCopyIfDifferent.cmake + ConfigurePkgConfig.cmake + CURL.cmake Copy3rdPartyLibs.cmake - CSharpMacros.cmake DBusGlib.cmake + DeploySharedLibs.cmake DirectX.cmake + DragDrop.cmake EXPAT.cmake + ExamplePlugin.cmake FindAPR.cmake + FindAutobuild.cmake FindBerkeleyDB.cmake FindCARes.cmake - FindELFIO.cmake - FindFMOD.cmake + FindFMODEX.cmake + FindGLH.cmake + FindGoogleBreakpad.cmake FindGooglePerfTools.cmake - FindMono.cmake - FindMySQL.cmake + FindHUNSPELL.cmake + FindJsonCpp.cmake + FindNDOF.cmake FindOpenJPEG.cmake + FindSCP.cmake FindXmlRpcEpi.cmake FindZLIB.cmake - FMOD.cmake + FMODEX.cmake FreeType.cmake + GLEXT.cmake + GLH.cmake GLOD.cmake GStreamer010Plugin.cmake + GetPrerequisites_2_8.cmake + Glui.cmake + Glut.cmake + GoogleBreakpad.cmake + GoogleMock.cmake GooglePerfTools.cmake + Havok.cmake Hunspell.cmake JPEG.cmake + JsonCpp.cmake LLAddBuildTest.cmake + LLAppearance.cmake + LLAppearanceUtility.cmake LLAudio.cmake LLCharacter.cmake LLCommon.cmake LLCrashLogger.cmake - LLDatabase.cmake LLImage.cmake LLImageJ2COJ.cmake LLInventory.cmake LLKDU.cmake + LLLogin.cmake LLMath.cmake LLMessage.cmake + LLPhysicsExtensions.cmake LLPlugin.cmake LLPrimitive.cmake - LLPhysicsExtensions.cmake LLRender.cmake - LLScene.cmake + LLSharedLibs.cmake LLTestCommand.cmake LLUI.cmake LLVFS.cmake @@ -63,21 +81,26 @@ set(cmake_SOURCE_FILES LLXML.cmake LScript.cmake Linking.cmake - MonoEmbed.cmake - MySQL.cmake + MediaPluginBase.cmake NDOF.cmake OPENAL.cmake OpenGL.cmake OpenJPEG.cmake OpenSSL.cmake PNG.cmake - Python.cmake + PluginAPI.cmake Prebuilt.cmake + PulseAudio.cmake + Python.cmake + QuickTimePlugin.cmake TemplateCheck.cmake Tut.cmake UI.cmake UnixInstall.cmake Variables.cmake + ViewerMiscLibs.cmake + VisualLeakDetector.cmake + WebKitLibPlugin.cmake XmlRpcEpi.cmake ZLIB.cmake ) @@ -88,10 +111,6 @@ set(master_SOURCE_FILES ../CMakeLists.txt ) -if (SERVER) - list(APPEND master_SOURCE_FILES ../Server.cmake) -endif (SERVER) - source_group("Master Rules" FILES ${master_SOURCE_FILES}) set_source_files_properties(${cmake_SOURCE_FILES} ${master_SOURCE_FILES} diff --git a/indra/cmake/CSharpMacros.cmake b/indra/cmake/CSharpMacros.cmake deleted file mode 100755 index a4dd815043..0000000000 --- a/indra/cmake/CSharpMacros.cmake +++ /dev/null @@ -1,142 +0,0 @@ -# - This is a support module for easy Mono/C# handling with CMake -# It defines the following macros: -# -# ADD_CS_LIBRARY (<target> <source>) -# ADD_CS_EXECUTABLE (<target> <source>) -# INSTALL_GAC (<target>) -# -# Note that the order of the arguments is important. -# -# You can optionally set the variable CS_FLAGS to tell the macros whether -# to pass additional flags to the compiler. This is particularly useful to -# set assembly references, unsafe code, etc... These flags are always reset -# after the target was added so you don't have to care about that. -# -# copyright (c) 2007 Arno Rehn arno@arnorehn.de -# -# Redistribution and use is allowed according to the terms of the GPL license. - - -# ----- support macros ----- -MACRO(GET_CS_LIBRARY_TARGET_DIR) - IF (NOT LIBRARY_OUTPUT_PATH) - SET(CS_LIBRARY_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) - ELSE (NOT LIBRARY_OUTPUT_PATH) - SET(CS_LIBRARY_TARGET_DIR ${LIBRARY_OUTPUT_PATH}) - ENDIF (NOT LIBRARY_OUTPUT_PATH) -ENDMACRO(GET_CS_LIBRARY_TARGET_DIR) - -MACRO(GET_CS_EXECUTABLE_TARGET_DIR) - IF (NOT EXECUTABLE_OUTPUT_PATH) - SET(CS_EXECUTABLE_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) - ELSE (NOT EXECUTABLE_OUTPUT_PATH) - SET(CS_EXECUTABLE_TARGET_DIR ${EXECUTABLE_OUTPUT_PATH}) - ENDIF (NOT EXECUTABLE_OUTPUT_PATH) -ENDMACRO(GET_CS_EXECUTABLE_TARGET_DIR) - -MACRO(MAKE_PROPER_FILE_LIST) - FOREACH(file ${ARGN}) - # first assume it's a relative path - FILE(GLOB globbed ${CMAKE_CURRENT_SOURCE_DIR}/${file}) - IF(globbed) - FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file} native) - ELSE(globbed) - FILE(TO_NATIVE_PATH ${file} native) - ENDIF(globbed) - SET(proper_file_list ${proper_file_list} ${native}) - SET(native "") - ENDFOREACH(file) -ENDMACRO(MAKE_PROPER_FILE_LIST) -# ----- end support macros ----- - -MACRO(ADD_CS_LIBRARY target) - GET_CS_LIBRARY_TARGET_DIR() - - SET(target_DLL "${CS_LIBRARY_TARGET_DIR}/${target}.dll") - MAKE_PROPER_FILE_LIST(${ARGN}) - FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_DLL}) - - SET(target_KEY "${CMAKE_CURRENT_SOURCE_DIR}/${target}.key") - SET(target_CS_FLAGS "${CS_FLAGS}") - IF(${target}_CS_FLAGS) - LIST(APPEND target_CS_FLAGS ${${target}_CS_FLAGS}) - ENDIF(${target}_CS_FLAGS) - IF(EXISTS ${target_KEY}) - LIST(APPEND target_CS_FLAGS -keyfile:${target_KEY}) - ENDIF(EXISTS ${target_KEY}) - - FOREACH(ref ${${target}_REFS}) - SET(ref_DLL ${CMAKE_CURRENT_BINARY_DIR}/${ref}.dll) - IF(EXISTS ${ref_DLL}) - LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) - ELSE(EXISTS ${ref_DLL}) - LIST(APPEND target_CS_FLAGS -r:${ref}) - ENDIF(EXISTS ${ref_DLL}) - ENDFOREACH(ref ${${target}_REFS}) - - ADD_CUSTOM_COMMAND (OUTPUT ${target_DLL} - COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_DLL} -target:library ${proper_file_list} - MAIN_DEPENDENCY ${proper_file_list} - DEPENDS ${ARGN} - COMMENT "Building ${relative_path}") - ADD_CUSTOM_TARGET (${target} ALL DEPENDS ${target_DLL}) - - FOREACH(ref ${${target}_REFS}) - GET_TARGET_PROPERTY(is_target ${ref} TYPE) - IF(is_target) - ADD_DEPENDENCIES(${target} ${ref}) - ENDIF(is_target) - ENDFOREACH(ref ${${target}_REFS}) - - SET(relative_path "") - SET(proper_file_list "") -ENDMACRO(ADD_CS_LIBRARY) - -MACRO(ADD_CS_EXECUTABLE target) - GET_CS_EXECUTABLE_TARGET_DIR() - - # Seems like cmake doesn't like the ".exe" ending for custom commands. - # If we call it ${target}.exe, 'make' will later complain about a missing rule. - # Create a fake target instead. - SET(target_EXE "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe") - SET(target_TOUCH "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe-built") - GET_DIRECTORY_PROPERTY(clean ADDITIONAL_MAKE_CLEAN_FILES) - LIST(APPEND clean ${target}.exe) - SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean}") - MAKE_PROPER_FILE_LIST(${ARGN}) - FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_EXE}) - SET(target_CS_FLAGS "${CS_FLAGS}") - - FOREACH(ref ${${target}_REFS}) - SET(ref_DLL ${CMAKE_CURRENT_SOURCE_DIR}/${ref}.dll) - IF(EXISTS ${ref_DLL}) - LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) - ELSE(EXISTS ${ref_DLL}) - LIST(APPEND target_CS_FLAGS -r:${ref}) - ENDIF(EXISTS ${ref_DLL}) - ENDFOREACH(ref ${${target}_REFS}) - - ADD_CUSTOM_COMMAND (OUTPUT "${target_TOUCH}" - COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_EXE} ${proper_file_list} - COMMAND ${CMAKE_COMMAND} -E touch ${target_TOUCH} - MAIN_DEPENDENCY ${ARGN} - DEPENDS ${ARGN} - COMMENT "Building ${relative_path}") - ADD_CUSTOM_TARGET ("${target}" ALL DEPENDS "${target_TOUCH}") - - FOREACH(ref ${${target}_REFS}) - GET_TARGET_PROPERTY(is_target ${ref} TYPE) - IF(is_target) - ADD_DEPENDENCIES(${target} ${ref}) - ENDIF(is_target) - ENDFOREACH(ref ${${target}_REFS}) - - SET(relative_path "") - SET(proper_file_list "") -ENDMACRO(ADD_CS_EXECUTABLE) - -MACRO(INSTALL_GAC target) - GET_CS_LIBRARY_TARGET_DIR() - - INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${GACUTIL_EXECUTABLE} -i ${CS_LIBRARY_TARGET_DIR}/${target}.dll -package 2.0)") -ENDMACRO(INSTALL_GAC target) diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake new file mode 100644 index 0000000000..82ee3e7a5b --- /dev/null +++ b/indra/cmake/ConfigurePkgConfig.cmake @@ -0,0 +1,74 @@ +# -*- cmake -*- + +SET(DEBUG_PKG_CONFIG "YES") + +# Don't change this if manually set by user. +IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") + + # Guess at architecture-specific system library paths. + if (WORD_SIZE EQUAL 32) + SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib) + SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib) + SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu) + SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu) + else (WORD_SIZE EQUAL 32) + SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib) + SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib) + SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu) + SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu) + endif (WORD_SIZE EQUAL 32) + + # Use DPKG architecture, if available. + IF (${DPKG_ARCH}) + SET(PKG_CONFIG_MULTI_GUESS /usr/lib/${DPKG_ARCH}) + SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usrlocal/lib/${DPKG_ARCH}) + ENDIF (${DPKG_ARCH}) + + # Explicitly include anything listed in PKG_CONFIG_PATH + string(REPLACE ":" ";" PKG_CONFIG_PATH_LIST "$ENV{PKG_CONFIG_PATH}") + FOREACH(PKG_CONFIG_DIR ${PKG_CONFIG_PATH_LIST}) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_DIR}/pkgconfig") + ENDFOREACH(PKG_CONFIG_DIR) + + # Look for valid pkgconfig directories. + FIND_PATH(PKG_CONFIG_ENV pkgconfig ENV LD_LIBRARY_PATH) + FIND_PATH(PKG_CONFIG_MULTI pkgconfig HINT ${PKG_CONFIG_MULTI_GUESS}) + FIND_PATH(PKG_CONFIG_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_MULTI_LOCAL_GUESS}) + FIND_PATH(PKG_CONFIG_NO_MULTI pkgconfig HINT ${PKG_CONFIG_NO_MULTI_GUESS}) + FIND_PATH(PKG_CONFIG_NO_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_NO_MULTI_LOCAL_GUESS}) + + # Add anything we found to our list. + IF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_ENV}/pkgconfig") + ENDIF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) + + IF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI}/pkgconfig") + ENDIF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) + + IF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI_LOCAL}/pkgconfig") + ENDIF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) + + IF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI}/pkgconfig") + ENDIF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) + + IF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI_LOCAL}/pkgconfig") + ENDIF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) + + # Also add some non-architecture specific package locations. + SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:/usr/share/pkgconfig:/usr/local/share/pkgconfig") + + # Remove first unwanted ':' + string(SUBSTRING ${VALID_PKG_LIBDIRS} 1 -1 VALID_PKG_LIBDIRS) + + # Set PKG_CONFIG_LIBDIR environment. + SET(ENV{PKG_CONFIG_LIBDIR} ${VALID_PKG_LIBDIRS}) +ENDIF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") + +IF(DEBUG_PKG_CONFIG) + MESSAGE(STATUS "Using PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}") +ENDIF(DEBUG_PKG_CONFIG) + diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 2a73900c71..d58c557f9d 100755 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -62,10 +62,9 @@ if(WINDOWS) set(release_files ${release_files} libtcmalloc_minimal.dll) endif(USE_TCMALLOC) - if (FMOD) - set(debug_files ${debug_files} fmod.dll) - set(release_files ${release_files} fmod.dll) - endif (FMOD) + if (FMODEX) + set(release_files ${release_files} fmodex.dll) + endif (FMODEX) #******************************* # Copy MS C runtime dlls, required for packaging. @@ -222,8 +221,10 @@ elseif(DARWIN) libcollada14dom.dylib ) - # fmod is statically linked on darwin - set(fmod_files "") + if (FMODEX) + set(debug_files ${debug_files} libfmodexL.dylib) + set(release_files ${release_files} libfmodex.dylib) + endif (FMODEX) elseif(LINUX) # linux is weird, multiple side by side configurations aren't supported @@ -265,7 +266,7 @@ elseif(LINUX) libdb-5.1.so libexpat.so libexpat.so.1 - libglod.so + libGLOD.so libgmock_main.so libgmock.so.0 libgmodule-2.0.so @@ -287,9 +288,9 @@ elseif(LINUX) set(release_files ${release_files} "libtcmalloc_minimal.so") endif (USE_TCMALLOC) - if (FMOD) - set(release_files ${release_files} "libfmod-3.75.so") - endif (FMOD) + if (FMODEX) + set(release_file ${release_files} "libfmodex.so") + endif (FMODEX) else(WINDOWS) message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") @@ -304,8 +305,6 @@ else(WINDOWS) set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/release") set(release_files "") - set(fmod_files "") - set(debug_llkdu_src "") set(debug_llkdu_dst "") set(release_llkdu_src "") @@ -368,30 +367,6 @@ copy_if_different( ) set(third_party_targets ${third_party_targets} ${out_targets}) -if (FMOD_SDK_DIR) - copy_if_different( - ${FMOD_SDK_DIR} - "${CMAKE_CURRENT_BINARY_DIR}/Debug" - out_targets - ${fmod_files} - ) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different( - ${FMOD_SDK_DIR} - "${CMAKE_CURRENT_BINARY_DIR}/Release" - out_targets - ${fmod_files} - ) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different( - ${FMOD_SDK_DIR} - "${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo" - out_targets - ${fmod_files} - ) - set(all_targets ${all_targets} ${out_targets}) -endif (FMOD_SDK_DIR) - if(NOT STANDALONE) add_custom_target( stage_third_party_libs ALL diff --git a/indra/cmake/CopyBackToSource.cmake b/indra/cmake/CopyBackToSource.cmake deleted file mode 100755 index d217df9aec..0000000000 --- a/indra/cmake/CopyBackToSource.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -*- cmake -*- -# Copies a binary back to the source directory - -MACRO(COPY_BACK_TO_SOURCE target) - GET_TARGET_PROPERTY(FROM ${target} LOCATION) - SET(TO ${CMAKE_CURRENT_SOURCE_DIR}) - #MESSAGE("TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}") - ADD_CUSTOM_COMMAND( - TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO} - DEPENDS ${FROM} - COMMENT "Copying ${target} to ${CMAKE_CURRENT_BINARY_DIR}" - ) -ENDMACRO(COPY_BACK_TO_SOURCE) - - diff --git a/indra/cmake/DirectX.cmake b/indra/cmake/DirectX.cmake index b2a18805d4..25163d0322 100755 --- a/indra/cmake/DirectX.cmake +++ b/indra/cmake/DirectX.cmake @@ -1,8 +1,9 @@ # -*- cmake -*- -if (VIEWER AND WINDOWS) +if (WINDOWS) find_path(DIRECTX_INCLUDE_DIR dxdiag.h "$ENV{DXSDK_DIR}/Include" + "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2009)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Include" @@ -25,6 +26,7 @@ if (VIEWER AND WINDOWS) find_path(DIRECTX_LIBRARY_DIR dxguid.lib "$ENV{DXSDK_DIR}/Lib/x86" + "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2009)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Lib/x86" @@ -43,4 +45,4 @@ if (VIEWER AND WINDOWS) message(FATAL_ERROR "Could not find DirectX SDK Libraries") endif (DIRECTX_LIBRARY_DIR) -endif (VIEWER AND WINDOWS) +endif (WINDOWS) diff --git a/indra/cmake/DragDrop.cmake b/indra/cmake/DragDrop.cmake index c0424396e5..b70aa6b6ee 100755 --- a/indra/cmake/DragDrop.cmake +++ b/indra/cmake/DragDrop.cmake @@ -1,23 +1,20 @@ # -*- cmake -*- -if (VIEWER) +set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off") - set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off") +if (OS_DRAG_DROP) - if (OS_DRAG_DROP) + if (WINDOWS) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) + endif (WINDOWS) - if (WINDOWS) - add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) - endif (WINDOWS) + if (DARWIN) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) + endif (DARWIN) - if (DARWIN) - add_definitions(-DLL_OS_DRAGDROP_ENABLED=1) - endif (DARWIN) + if (LINUX) + add_definitions(-DLL_OS_DRAGDROP_ENABLED=0) + endif (LINUX) - if (LINUX) - add_definitions(-DLL_OS_DRAGDROP_ENABLED=0) - endif (LINUX) +endif (OS_DRAG_DROP) - endif (OS_DRAG_DROP) - -endif (VIEWER) diff --git a/indra/cmake/Externals.cmake b/indra/cmake/Externals.cmake deleted file mode 100755 index 26f3b56049..0000000000 --- a/indra/cmake/Externals.cmake +++ /dev/null @@ -1,34 +0,0 @@ -# -*- cmake -*- - -include(Python) -include(FindSVN) - -macro (use_svn_external _binary _path _url _rev) - if (NOT STANDALONE) - if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) - if(SVN_FOUND) - if(DEBUG_EXTERNALS) - message("cd ${_path} && ${SVN_EXECUTABLE} checkout -r ${_rev} ${_url} ${_binary}") - endif(DEBUG_EXTERNALS) - execute_process(COMMAND ${SVN_EXECUTABLE} - checkout - -r ${_rev} - ${_url} - ${_binary} - WORKING_DIRECTORY ${_path} - RESULT_VARIABLE ${_binary}_installed - ) - else(SVN_FOUND) - message(FATAL_ERROR "Failed to find SVN_EXECUTABLE") - endif(SVN_FOUND) - file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}") - else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) - set(${_binary}_installed 0) - endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) - if(NOT ${_binary}_installed EQUAL 0) - message(FATAL_ERROR - "Failed to download or unpack prebuilt '${_binary}'." - " Process returned ${${_binary}_installed}.") - endif (NOT ${_binary}_installed EQUAL 0) - endif (NOT STANDALONE) -endmacro (use_svn_external _binary _path _url _rev) diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake deleted file mode 100755 index 3586c1160a..0000000000 --- a/indra/cmake/FMOD.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# -*- cmake -*- - -# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON -# When building using proprietary binaries though (i.e. having access to LL private servers), -# we always build with FMOD. -# Open source devs should use the -DFMOD:BOOL=ON then if they want to build with FMOD, whether -# they are using STANDALONE or not. -if (INSTALL_PROPRIETARY) - set(FMOD ON CACHE BOOL "Use FMOD sound library.") -endif (INSTALL_PROPRIETARY) - -if (FMOD) - if (STANDALONE) - # In that case, we use the version of the library installed on the system - set(FMOD_FIND_REQUIRED ON) - include(FindFMOD) - else (STANDALONE) - if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - # If the path have been specified in the arguments, use that - set(FMOD_LIBRARIES ${FMOD_LIBRARY}) - MESSAGE(STATUS "Using FMOD path: ${FMOD_LIBRARIES}, ${FMOD_INCLUDE_DIR}") - else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - # If not, we're going to try to get the package listed in autobuild.xml - # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) - # as accessing the private LL location will fail if you don't have the credential - include(Prebuilt) - use_prebuilt_binary(fmod) - if (WINDOWS) - set(FMOD_LIBRARY fmod) - elseif (DARWIN) - set(FMOD_LIBRARY fmod) - elseif (LINUX) - set(FMOD_LIBRARY fmod-3.75) - endif (WINDOWS) - set(FMOD_LIBRARIES ${FMOD_LIBRARY}) - set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) - endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - endif (STANDALONE) -endif (FMOD) diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake new file mode 100644 index 0000000000..65bc1cabeb --- /dev/null +++ b/indra/cmake/FMODEX.cmake @@ -0,0 +1,46 @@ +# -*- cmake -*- + +# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with FMODEX. +# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether +# they are using STANDALONE or not. +if (INSTALL_PROPRIETARY) + set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.") +endif (INSTALL_PROPRIETARY) + +if (FMODEX) + if (STANDALONE) + # In that case, we use the version of the library installed on the system + set(FMODEX_FIND_REQUIRED ON) + include(FindFMODEX) + else (STANDALONE) + if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) + # If the path have been specified in the arguments, use that + set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) + MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}") + else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) + # If not, we're going to try to get the package listed in autobuild.xml + # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) + # as accessing the private LL location will fail if you don't have the credential + include(Prebuilt) + use_prebuilt_binary(fmodex) + if (WINDOWS) + set(FMODEX_LIBRARY + debug fmodexL_vc + optimized fmodex_vc) + elseif (DARWIN) + set(FMODEX_LIBRARY + debug fmodexL + optimized fmodex) + elseif (LINUX) + set(FMODEX_LIBRARY + debug fmodexL + optimized fmodex) + endif (WINDOWS) + set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) + set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex) + endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) + endif (STANDALONE) +endif (FMODEX) + diff --git a/indra/cmake/FindELFIO.cmake b/indra/cmake/FindELFIO.cmake deleted file mode 100755 index 8a5421ab9c..0000000000 --- a/indra/cmake/FindELFIO.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -# - Find ELFIO -# Find the ELFIO includes and library -# This module defines -# ELFIO_INCLUDE_DIR, where to find elfio.h, etc. -# ELFIO_LIBRARIES, the libraries needed to use ELFIO. -# ELFIO_FOUND, If false, do not try to use ELFIO. -# also defined, but not for general use are -# ELFIO_LIBRARY, where to find the ELFIO library. - -FIND_PATH(ELFIO_INCLUDE_DIR ELFIO/ELFIO.h -/usr/local/include -/usr/include -) - -SET(ELFIO_NAMES ${ELFIO_NAMES} ELFIO) -FIND_LIBRARY(ELFIO_LIBRARY - NAMES ${ELFIO_NAMES} - PATHS /usr/lib /usr/local/lib - ) - -IF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - SET(ELFIO_LIBRARIES ${ELFIO_LIBRARY}) - SET(ELFIO_FOUND "YES") -ELSE (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - SET(ELFIO_FOUND "NO") -ENDIF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR) - - -IF (ELFIO_FOUND) - IF (NOT ELFIO_FIND_QUIETLY) - MESSAGE(STATUS "Found ELFIO: ${ELFIO_LIBRARIES}") - ENDIF (NOT ELFIO_FIND_QUIETLY) -ELSE (ELFIO_FOUND) - IF (ELFIO_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find ELFIO library") - ENDIF (ELFIO_FIND_REQUIRED) -ENDIF (ELFIO_FOUND) - -# Deprecated declarations. -SET (NATIVE_ELFIO_INCLUDE_PATH ${ELFIO_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_ELFIO_LIB_PATH ${ELFIO_LIBRARY} PATH) - -MARK_AS_ADVANCED( - ELFIO_LIBRARY - ELFIO_INCLUDE_DIR - ) diff --git a/indra/cmake/FindFMOD.cmake b/indra/cmake/FindFMOD.cmake deleted file mode 100755 index 1ebbc8c96e..0000000000 --- a/indra/cmake/FindFMOD.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# -*- cmake -*- - -# - Find FMOD -# Find the FMOD includes and library -# This module defines -# FMOD_INCLUDE_DIR, where to find fmod.h and fmod_errors.h -# FMOD_LIBRARIES, the libraries needed to use FMOD. -# FMOD, If false, do not try to use FMOD. -# also defined, but not for general use are -# FMOD_LIBRARY, where to find the FMOD library. - -FIND_PATH(FMOD_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod) - -SET(FMOD_NAMES ${FMOD_NAMES} fmod fmodvc fmodex fmod-3.75) -FIND_LIBRARY(FMOD_LIBRARY - NAMES ${FMOD_NAMES} - PATH_SUFFIXES fmod - ) - -IF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - SET(FMOD_LIBRARIES ${FMOD_LIBRARY}) - SET(FMOD_FOUND "YES") -ELSE (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - SET(FMOD_FOUND "NO") -ENDIF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) - -IF (FMOD_FOUND) - IF (NOT FMOD_FIND_QUIETLY) - MESSAGE(STATUS "Found FMOD: ${FMOD_LIBRARIES}") - ENDIF (NOT FMOD_FIND_QUIETLY) -ELSE (FMOD_FOUND) - IF (FMOD_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find FMOD library") - ENDIF (FMOD_FIND_REQUIRED) -ENDIF (FMOD_FOUND) - -# Deprecated declarations. -SET (NATIVE_FMOD_INCLUDE_PATH ${FMOD_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_FMOD_LIB_PATH ${FMOD_LIBRARY} PATH) - -MARK_AS_ADVANCED( - FMOD_LIBRARY - FMOD_INCLUDE_DIR - ) diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake new file mode 100644 index 0000000000..b621727c0e --- /dev/null +++ b/indra/cmake/FindFMODEX.cmake @@ -0,0 +1,65 @@ +# -*- cmake -*- + +# - Find FMODEX +# Find the FMODEX includes and library +# This module defines +# FMODEX_INCLUDE_DIR, where to find fmod.h and fmod_errors.h +# FMODEX_LIBRARIES, the libraries needed to use FMODEX. +# FMODEX, If false, do not try to use FMODEX. +# also defined, but not for general use are +# FMODEX_LIBRARY, where to find the FMODEX library. + +FIND_PATH(FMODEX_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod) + +SET(FMODEX_NAMES ${FMODEX_NAMES} fmodex fmodvc fmodexL_vc) +FIND_LIBRARY(FMODEX_LIBRARY + NAMES ${FMODEX_NAMES} + PATH_SUFFIXES fmodex + ) + +IF (FMODEX_SDK_DIR OR WINDOWS) + if(WINDOWS) + set(FMODEX_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODEX") + STRING(REGEX REPLACE "\\\\" "/" FMODEX_SDK_DIR ${FMODEX_SDK_DIR}) + endif(WINDOWS) + find_library(FMODEX_LIBRARY + fmodex_vc fmodexL_vc + PATHS + ${FMODEX_SDK_DIR}/api/lib + ${FMODEX_SDK_DIR}/api + ${FMODEX_SDK_DIR} + ) + find_path(FMODEX_INCLUDE_DIR fmod.h + ${FMODEX_SDK_DIR}/api/inc + ${FMODEX_SDK_DIR}/api + ${FMODEX_SDK_DIR} + ) + find_path(FMODEX_INCLUDE_DIR fmod.h + ${FMODEX_SDK_DIR}/api/inc + ${FMODEX_SDK_DIR}/api + ${FMODEX_SDK_DIR} + ) + IF (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) + SET(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) + SET(FMODEX_FOUND "YES") + endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) +ENDIF (FMODEX_SDK_DIR OR WINDOWS) + +IF (FMODEX_FOUND) + IF (NOT FMODEX_FIND_QUIETLY) + MESSAGE(STATUS "Found FMODEX: ${FMODEX_LIBRARIES}") + ENDIF (NOT FMODEX_FIND_QUIETLY) +ELSE (FMODEX_FOUND) + IF (FMODEX_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find FMODEX library") + ENDIF (FMODEX_FIND_REQUIRED) +ENDIF (FMODEX_FOUND) + +# Deprecated declarations. +SET (NATIVE_FMODEX_INCLUDE_PATH ${FMODEX_INCLUDE_DIR} ) +GET_FILENAME_COMPONENT (NATIVE_FMODEX_LIB_PATH ${FMODEX_LIBRARY} PATH) + +MARK_AS_ADVANCED( + FMODEX_LIBRARY + FMODEX_INCLUDE_DIR + ) diff --git a/indra/cmake/FindLLQtWebkit.cmake b/indra/cmake/FindLLQtWebkit.cmake deleted file mode 100755 index 2f666d3bf0..0000000000 --- a/indra/cmake/FindLLQtWebkit.cmake +++ /dev/null @@ -1,62 +0,0 @@ -# -*- cmake -*- - -# - Find llqtwebkit -# Find the llqtwebkit includes and library -# This module defines -# LLQTWEBKIT_INCLUDE_DIR, where to find llqtwebkit.h, etc. -# LLQTWEBKIT_LIBRARY, the llqtwebkit library with full path. -# LLQTWEBKIT_FOUND, If false, do not try to use llqtwebkit. -# also defined, but not for general use are -# LLQTWEBKIT_LIBRARIES, the libraries needed to use llqtwebkit. -# LLQTWEBKIT_LIBRARY_DIRS, where to find the llqtwebkit library. -# LLQTWEBKIT_DEFINITIONS - You should add_definitions(${LLQTWEBKIT_DEFINITIONS}) -# before compiling code that includes llqtwebkit library files. - -# Try to use pkg-config first. -# This allows to have two different libllqtwebkit packages installed: -# one for viewer 2.x and one for viewer 1.x. -include(FindPkgConfig) -if (PKG_CONFIG_FOUND) - if (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - set(_PACKAGE_ARGS libllqtwebkit>=${LLQtWebkit_FIND_VERSION} REQUIRED) - else (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - set(_PACKAGE_ARGS libllqtwebkit) - endif (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) - if (NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS "2.8.2") - # As virtually nobody will have a pkg-config file for this, do this check always quiet. - # Unfortunately cmake 2.8.2 or higher is required for pkg_check_modules to have a 'QUIET'. - set(_PACKAGE_ARGS ${_PACKAGE_ARGS} QUIET) - endif () - pkg_check_modules(LLQTWEBKIT ${_PACKAGE_ARGS}) -endif (PKG_CONFIG_FOUND) -set(LLQTWEBKIT_DEFINITIONS ${LLQTWEBKIT_CFLAGS_OTHER}) - -find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_INCLUDE_DIRS}) - -find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS}) - -if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config. - set(LLQTWEBKIT_LIBRARIES llqtwebkit) - get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH) -endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) - -# Handle the QUIETLY and REQUIRED arguments and set LLQTWEBKIT_FOUND -# to TRUE if all listed variables are TRUE. -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - LLQTWEBKIT - DEFAULT_MSG - LLQTWEBKIT_LIBRARY - LLQTWEBKIT_INCLUDE_DIR - LLQTWEBKIT_LIBRARIES - LLQTWEBKIT_LIBRARY_DIRS - ) - -mark_as_advanced( - LLQTWEBKIT_LIBRARY - LLQTWEBKIT_INCLUDE_DIR - LLQTWEBKIT_LIBRARIES - LLQTWEBKIT_LIBRARY_DIRS - LLQTWEBKIT_DEFINITIONS - ) - diff --git a/indra/cmake/FindMT.cmake b/indra/cmake/FindMT.cmake deleted file mode 100755 index 5239a4c2f5..0000000000 --- a/indra/cmake/FindMT.cmake +++ /dev/null @@ -1,15 +0,0 @@ -#Find the windows manifest tool. - -FIND_PROGRAM(HAVE_MANIFEST_TOOL NAMES mt - PATHS - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/VC/bin" - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/Common7/Tools/Bin" - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/SDK/v2.0/Bin") -IF(HAVE_MANIFEST_TOOL) - MESSAGE(STATUS "Found Mainfest Tool. Embedding custom manifests.") -ELSE(HAVE_MANIFEST_TOOL) - MESSAGE(FATAL_ERROR "Manifest tool, mt.exe, can't be found.") -ENDIF(HAVE_MANIFEST_TOOL) - -STRING(REPLACE "/MANIFEST" "/MANIFEST:NO" CMAKE_EXE_LINKER_FLAGS - ${CMAKE_EXE_LINKER_FLAGS}) diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake deleted file mode 100755 index d956c48656..0000000000 --- a/indra/cmake/FindMono.cmake +++ /dev/null @@ -1,68 +0,0 @@ -# - Try to find the mono, mcs, gmcs and gacutil -# -# defines -# -# MONO_FOUND - system has mono, mcs, gmcs and gacutil -# MONO_PATH - where to find 'mono' -# MCS_PATH - where to find 'mcs' -# GMCS_PATH - where to find 'gmcs' -# GACUTIL_PATH - where to find 'gacutil' -# -# copyright (c) 2007 Arno Rehn arno@arnorehn.de -# -# Redistribution and use is allowed according to the terms of the GPL license. -# Removed the check for gmcs - -FIND_PROGRAM (MONO_EXECUTABLE mono - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (MCS_EXECUTABLE mcs - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (GMCS_EXECUTABLE gmcs - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (ILASM_EXECUTABLE - NAMES ilasm.bat ilasm - NO_DEFAULT_PATH - PATHS "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin -) - -SET (MONO_FOUND FALSE) - -IF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) - SET (MONO_FOUND TRUE) -ENDIF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) - -IF (MONO_FOUND) - IF (NOT Mono_FIND_QUIETLY) - MESSAGE(STATUS "Found mono: ${MONO_EXECUTABLE}") - MESSAGE(STATUS "Found mcs: ${MCS_EXECUTABLE}") - MESSAGE(STATUS "Found gacutil: ${GACUTIL_EXECUTABLE}") - ENDIF (NOT Mono_FIND_QUIETLY) -ELSE (MONO_FOUND) - IF (Mono_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find one or more of the following programs: mono, mcs, gacutil") - ENDIF (Mono_FIND_REQUIRED) -ENDIF (MONO_FOUND) - -MARK_AS_ADVANCED(MONO_EXECUTABLE MCS_EXECUTABLE GACUTIL_EXECUTABLE) diff --git a/indra/cmake/FindMySQL.cmake b/indra/cmake/FindMySQL.cmake deleted file mode 100755 index 431940328f..0000000000 --- a/indra/cmake/FindMySQL.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -# - Find MySQL -# Find the MySQL includes and library -# This module defines -# MYSQL_INCLUDE_DIR, where to find mysql.h, etc. -# MYSQL_LIBRARIES, the libraries needed to use Mysql. -# MYSQL_FOUND, If false, do not try to use Mysql. -# also defined, but not for general use are -# MYSQL_LIBRARY, where to find the Mysql library. - -FIND_PATH(MYSQL_INCLUDE_DIR mysql/mysql.h -/usr/local/include -/usr/include -) - -SET(MYSQL_NAMES ${MYSQL_NAMES} mysqlclient) -FIND_LIBRARY(MYSQL_LIBRARY - NAMES ${MYSQL_NAMES} - PATHS /usr/lib/mysql /usr/lib /usr/local/lib/mysql /usr/local/lib - ) - -IF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - SET(MYSQL_LIBRARIES ${MYSQL_LIBRARY}) - SET(MYSQL_FOUND "YES") -ELSE (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - SET(MYSQL_FOUND "NO") -ENDIF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - - -IF (MYSQL_FOUND) - IF (NOT MYSQL_FIND_QUIETLY) - MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARIES}") - ENDIF (NOT MYSQL_FIND_QUIETLY) -ELSE (MYSQL_FOUND) - IF (MYSQL_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find MySQL library") - ENDIF (MYSQL_FIND_REQUIRED) -ENDIF (MYSQL_FOUND) - -# Deprecated declarations. -SET (NATIVE_MYSQL_INCLUDE_PATH ${MYSQL_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_MYSQL_LIB_PATH ${MYSQL_LIBRARY} PATH) - -MARK_AS_ADVANCED( - MYSQL_LIBRARY - MYSQL_INCLUDE_DIR - ) diff --git a/indra/cmake/FindSVN.cmake b/indra/cmake/FindSVN.cmake deleted file mode 100755 index 3322be4ca9..0000000000 --- a/indra/cmake/FindSVN.cmake +++ /dev/null @@ -1,34 +0,0 @@ -# -*- cmake -*- -# -# Find the svn executable for exporting old svn:externals. -# -# Input variables: -# SVN_FIND_REQUIRED - set this if configuration should fail without scp -# -# Output variables: -# -# SVN_FOUND - set if svn was found -# SVN_EXECUTABLE - path to svn executable -# SVN_BATCH_FLAG - how to put svn into batch mode - - -SET(SVN_EXECUTABLE) -FIND_PROGRAM(SVN_EXECUTABLE NAMES svn svn.exe) - -IF (SVN_EXECUTABLE) - SET(SVN_FOUND ON) -ELSE (SVN_EXECUTABLE) - SET(SVN_FOUND OFF) -ENDIF (SVN_EXECUTABLE) - -IF (SVN_FOUND) - GET_FILENAME_COMPONENT(_svn_name ${SVN_EXECUTABLE} NAME_WE) - SET(SVN_BATCH_FLAG --non-interactive) -ELSE (SVN_FOUND) - IF (SVN_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find svn executable") - ENDIF (SVN_FIND_REQUIRED) -ENDIF (SVN_FOUND) - -MARK_AS_ADVANCED(SVN_EXECUTABLE SVN_FOUND SVN_BATCH_FLAG) - diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake new file mode 100644 index 0000000000..0a3dd976b4 --- /dev/null +++ b/indra/cmake/GLEXT.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- +include(Prebuilt) + +if (NOT STANDALONE) + use_prebuilt_binary(glext) + use_prebuilt_binary(glh_linear) + set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) +endif (NOT STANDALONE) diff --git a/indra/cmake/GLOD.cmake b/indra/cmake/GLOD.cmake index 77221d55ed..6bdbaf621e 100755 --- a/indra/cmake/GLOD.cmake +++ b/indra/cmake/GLOD.cmake @@ -6,4 +6,4 @@ if (NOT STANDALONE) endif (NOT STANDALONE) set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) -set(GLOD_LIBRARIES glod) +set(GLOD_LIBRARIES GLOD) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 73b3642ae6..f3fd008e49 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -10,7 +10,7 @@ if (STANDALONE) else (STANDALONE) if (WINDOWS) if (USE_TCMALLOC) - use_prebuilt_binary(tcmalloc) + use_prebuilt_binary(gperftools) set(TCMALLOC_LIBRARIES debug libtcmalloc_minimal-debug optimized libtcmalloc_minimal) @@ -23,7 +23,7 @@ else (STANDALONE) endif (WINDOWS) if (LINUX) if (USE_TCMALLOC) - use_prebuilt_binary(tcmalloc) + use_prebuilt_binary(gperftools) set(TCMALLOC_LIBRARIES tcmalloc) else (USE_TCMALLOC) diff --git a/indra/cmake/Havok.cmake b/indra/cmake/Havok.cmake index 5c0768abfa..44f81ce332 100755 --- a/indra/cmake/Havok.cmake +++ b/indra/cmake/Havok.cmake @@ -1,6 +1,10 @@ # -*- cmake -*- +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + use_prebuilt_binary(havok-source) + set(Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Source) list(APPEND Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Demo) @@ -8,14 +12,14 @@ set(HAVOK_DEBUG_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug) set(HAVOK_RELEASE_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok) if (LL_DEBUG_HAVOK) - if (WIN32) - # Always link relwithdebinfo to havok-hybrid on windows. - set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-hybrid) - else (WIN32) - set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug) - endif (WIN32) + if (WIN32) + # Always link relwithdebinfo to havok-hybrid on windows. + set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-hybrid) + else (WIN32) + set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug) + endif (WIN32) else (LL_DEBUG_HAVOK) - set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok) + set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok) endif (LL_DEBUG_HAVOK) set(HAVOK_LIBS @@ -45,39 +49,89 @@ unset(HK_DEBUG_LIBRARIES) unset(HK_RELEASE_LIBRARIES) unset(HK_RELWITHDEBINFO_LIBRARIES) +# *TODO: Figure out why we need to extract like this... foreach(HAVOK_LIB ${HAVOK_LIBS}) - find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH}) - find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH}) - find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}) - - if(LINUX) - set(cmd "mkdir") - set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}") - set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}") - set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}") - - exec_program( ${cmd} ${HAVOK_DEBUG_LIBRARY_PATH} ARGS ${debug_dir} OUTPUT_VARIABLE rv) - exec_program( ${cmd} ${HAVOK_RELEASE_LIBRARY_PATH} ARGS ${release_dir} OUTPUT_VARIABLE rv) - exec_program( ${cmd} ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH} ARGS ${relwithdebinfo_dir} OUTPUT_VARIABLE rv) - - set(cmd "ar") - set(arg " -xv") - set(arg "${arg} ../lib${HAVOK_LIB}.a") - exec_program( ${cmd} ${debug_dir} ARGS ${arg} OUTPUT_VARIABLE rv) - exec_program( ${cmd} ${release_dir} ARGS ${arg} OUTPUT_VARIABLE rv) - exec_program( ${cmd} ${relwithdebinfo_dir} ARGS ${arg} OUTPUT_VARIABLE rv) - - file(GLOB extracted_debug "${debug_dir}/*.o") - file(GLOB extracted_release "${release_dir}/*.o") - file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o") - list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug}) - list(APPEND HK_RELEASE_LIBRARIES ${extracted_release}) - list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo}) - else(LINUX) - # Win32 - list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}}) - list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}}) - list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}}) - endif (LINUX) + find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH}) + find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH}) + find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}) + + if(LINUX) + set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}") + set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}") + set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}") + + # Try to avoid extracting havok library each time we run cmake. + if("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted") + file(READ ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted "havok_${HAVOK_LIB}_extracted") + if(DEBUG_PREBUILT) + message(STATUS "havok_${HAVOK_LIB}_extracted: \"${havok_${HAVOK_LIB}_extracted}\"") + endif(DEBUG_PREBUILT) + endif("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted") + + if(${CMAKE_BINARY_DIR}/temp/havok-source_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0) + if(DEBUG_PREBUILT) + MESSAGE(STATUS "Extracting ${HAVOK_LIB}...") + endif(DEBUG_PREBUILT) + set(cmd "mkdir") + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "${cmd} ${debug_dir}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${HAVOK_DEBUG_LIBRARY_PATH} ARGS ${debug_dir} OUTPUT_VARIABLE rv) + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "${cmd} ${release_dir}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${HAVOK_RELEASE_LIBRARY_PATH} ARGS ${release_dir} OUTPUT_VARIABLE rv) + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "${cmd} ${relwithdebinfo_dir}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH} ARGS ${relwithdebinfo_dir} OUTPUT_VARIABLE rv) + + set(cmd "ar") + set(arg " -xv") + set(arg "${arg} ../lib${HAVOK_LIB}.a") + if(DEBUG_PREBUILT) + MESSAGE(STATUS "cd ${debug_dir} && ${cmd} ${arg}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${debug_dir} ARGS ${arg} OUTPUT_VARIABLE rv) + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "cd ${release_dir} && ${cmd} ${arg}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${release_dir} ARGS ${arg} OUTPUT_VARIABLE rv) + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "cd ${relwithdebinfo_dir} && ${cmd} ${arg}") + endif(DEBUG_PREBUILT) + exec_program( ${cmd} ${relwithdebinfo_dir} ARGS ${arg} OUTPUT_VARIABLE rv) + + # Just assume success for now. + set(havok_${HAVOK_LIB}_extracted 0) + file(WRITE ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted "${havok_${HAVOK_LIB}_extracted}") + + endif(${CMAKE_BINARY_DIR}/temp/havok-source_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0) + + file(GLOB extracted_debug "${debug_dir}/*.o") + file(GLOB extracted_release "${release_dir}/*.o") + file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o") + + if(DEBUG_PREBUILT) + MESSAGE(STATUS "extracted_debug ${debug_dir}/*.o") + MESSAGE(STATUS "extracted_release ${release_dir}/*.o") + MESSAGE(STATUS "extracted_relwithdebinfo ${relwithdebinfo_dir}/*.o") + endif(DEBUG_PREBUILT) + + list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug}) + list(APPEND HK_RELEASE_LIBRARIES ${extracted_release}) + list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo}) + else(LINUX) + # Win32 + list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}}) + list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}}) + list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}}) + endif (LINUX) endforeach(HAVOK_LIB) +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/LLAppearance.cmake b/indra/cmake/LLAppearance.cmake new file mode 100644 index 0000000000..bd3795a526 --- /dev/null +++ b/indra/cmake/LLAppearance.cmake @@ -0,0 +1,17 @@ +# -*- cmake -*- + +include(Variables) + +set(LLAPPEARANCE_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/llappearance + ) + +if (BUILD_HEADLESS) + set(LLAPPEARANCE_HEADLESS_LIBRARIES + llappearanceheadless + ) +endif (BUILD_HEADLESS) + +set(LLAPPEARANCE_LIBRARIES llappearance) + + diff --git a/indra/cmake/LLAppearanceUtility.cmake b/indra/cmake/LLAppearanceUtility.cmake new file mode 100644 index 0000000000..bea45543de --- /dev/null +++ b/indra/cmake/LLAppearanceUtility.cmake @@ -0,0 +1,12 @@ +# -*- cmake -*- +include(Prebuilt) + +# Linux proprietary build only +if (INSTALL_PROPRIETARY) + if(LINUX) + use_prebuilt_binary(llappearanceutility-source) + set(LLAPPEARANCEUTILITY_SRC_DIR ${LIBS_PREBUILT_DIR}/llappearanceutility/src) + set(LLAPPEARANCEUTILITY_BIN_DIR ${CMAKE_BINARY_DIR}/llappearanceutility) + endif (LINUX) +endif (INSTALL_PROPRIETARY) + diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index c254bf6f05..b52556a73e 100755 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -10,6 +10,8 @@ set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llcommon ${APRUTIL_INCLUDE_DIR} ${APR_INCLUDE_DIR} + ) +set(LLCOMMON_SYSTEM_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ) diff --git a/indra/cmake/LLDatabase.cmake b/indra/cmake/LLDatabase.cmake deleted file mode 100755 index 6526101386..0000000000 --- a/indra/cmake/LLDatabase.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -*- cmake -*- - -include(MySQL) - -set(LLDATABASE_INCLUDE_DIRS - ${LIBS_SERVER_DIR}/lldatabase - ${MYSQL_INCLUDE_DIR} - ) - -set(LLDATABASE_LIBRARIES lldatabase) diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake index 8427928151..ae71ee4c0d 100755 --- a/indra/cmake/LLRender.cmake +++ b/indra/cmake/LLRender.cmake @@ -1,5 +1,6 @@ # -*- cmake -*- +include(Variables) include(FreeType) include(GLH) @@ -8,27 +9,12 @@ set(LLRENDER_INCLUDE_DIRS ${GLH_INCLUDE_DIR} ) -if (SERVER AND LINUX) - set(LLRENDER_LIBRARIES - llrenderheadless - ) -else (SERVER AND LINUX) +if (BUILD_HEADLESS) + set(LLRENDER_HEADLESS_LIBRARIES + llrenderheadless + ) +endif (BUILD_HEADLESS) set(LLRENDER_LIBRARIES llrender ) -endif (SERVER AND LINUX) -# mapserver requires certain files to be copied so LL_MESA_HEADLESS can be set -# differently for different object files. -macro (copy_server_sources ) - foreach (PREFIX ${ARGV}) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp - COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp - ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp - ) - list(APPEND server_SOURCE_FILES ${PREFIX}_server.cpp) - endforeach (PREFIX ${_copied_SOURCES}) -endmacro (copy_server_sources _copied_SOURCES) diff --git a/indra/cmake/LLScene.cmake b/indra/cmake/LLScene.cmake deleted file mode 100755 index 96ad5085a2..0000000000 --- a/indra/cmake/LLScene.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -*- cmake -*- - -set(LLSCENE_INCLUDE_DIRS - ${LIBS_SERVER_DIR}/llscene - ) - -set(LLSCENE_LIBRARIES llscene) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index b4bb9a078a..0def507e65 100755 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -1,6 +1,7 @@ # -*- cmake -*- -include(OpenGL) +include(Variables) +include(GLEXT) include(Prebuilt) if (STANDALONE) @@ -13,17 +14,15 @@ if (STANDALONE) SDL_LIBRARY ) else (STANDALONE) - use_prebuilt_binary(mesa) - if (LINUX AND VIEWER) + if (LINUX) use_prebuilt_binary(SDL) set (SDL_FOUND TRUE) set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) set (SDL_LIBRARY SDL directfb fusion direct) - endif (LINUX AND VIEWER) + endif (LINUX) endif (STANDALONE) if (SDL_FOUND) - add_definitions(-DLL_SDL=1) include_directories(${SDL_INCLUDE_DIR}) endif (SDL_FOUND) @@ -32,12 +31,12 @@ set(LLWINDOW_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llwindow ) -if (SERVER AND LINUX) - set(LLWINDOW_LIBRARIES - llwindowheadless - ) -else (SERVER AND LINUX) - set(LLWINDOW_LIBRARIES - llwindow - ) -endif (SERVER AND LINUX) +if (BUILD_HEADLESS) + set(LLWINDOW_HEADLESS_LIBRARIES + llwindowheadless + ) +endif (BUILD_HEADLESS) + +set(LLWINDOW_LIBRARIES + llwindow + ) diff --git a/indra/cmake/LLXML.cmake b/indra/cmake/LLXML.cmake index 64dfdb604f..b093c76297 100755 --- a/indra/cmake/LLXML.cmake +++ b/indra/cmake/LLXML.cmake @@ -5,8 +5,10 @@ include(EXPAT) set(LLXML_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llxml - ${Boost_INCLUDE_DIRS} ${EXPAT_INCLUDE_DIRS} ) +set(LLXML_SYSTEM_INCLUDE_DIRS + ${Boost_INCLUDE_DIRS} + ) set(LLXML_LIBRARIES llxml) diff --git a/indra/cmake/LLXUIXML.cmake b/indra/cmake/LLXUIXML.cmake deleted file mode 100755 index b8bfe48c77..0000000000 --- a/indra/cmake/LLXUIXML.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -*- cmake -*- - -set(LLXUIXML_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/llxuixml - ) - -set(LLXUIXML_LIBRARIES llxuixml) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index c3e3a80fd0..b9c9e531fc 100755 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -1,5 +1,8 @@ # -*- cmake -*- +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + include(Variables) set(ARCH_PREBUILT_DIRS ${AUTOBUILD_INSTALL_DIR}/lib) @@ -69,3 +72,5 @@ else (WINDOWS) endif (WINDOWS) mark_as_advanced(DL_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES) + +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/MonoDeps.cmake b/indra/cmake/MonoDeps.cmake deleted file mode 100755 index 52d5491563..0000000000 --- a/indra/cmake/MonoDeps.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -set(MONO_PREBUILT_LIBRARIES_DIR ${LIBS_PREBUILT_DIR}/mono/1.0) - -set(MONO_PREBUILT_LIBRARIES - Iesi.Collections.dll - Iesi.Collections.pdb - Mono.CompilerServices.SymbolWriter.dll - Mono.PEToolkit.dll - Mono.PEToolkit.pdb - Mono.Security.dll - PEAPI.dll - RAIL.dll - RAIL.pdb - ) - - set(MONO_CORE_LIBRARIES - System.dll - System.Xml.dll - mscorlib.dll) - -if(WINDOWS) - set(MONO_DEPENDENCIES - DomainCreator - DomainRegister - LslLibrary - LslUserScript - Script - ScriptTypes - TestFormat - UserScript - UThread - UThreadInjector - ) -else(WINDOWS) - set(MONO_DEPENDENCIES - DomainCreator_POST_BUILD - DomainRegister_POST_BUILD - LslLibrary_POST_BUILD - LslUserScript_POST_BUILD - Script_POST_BUILD - ScriptTypes_POST_BUILD - TestFormat_POST_BUILD - UserScript_POST_BUILD - UThread_POST_BUILD - UThreadInjector_POST_BUILD - ) -endif(WINDOWS) diff --git a/indra/cmake/MonoEmbed.cmake b/indra/cmake/MonoEmbed.cmake deleted file mode 100755 index 30890aed21..0000000000 --- a/indra/cmake/MonoEmbed.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# -*- cmake -*- - -include(Prebuilt) -use_prebuilt_binary(libmono) - -SET(GLIB_2_0 glib-2.0) - -if (WINDOWS) - SET(MONO_LIB mono) -else (WINDOWS) - SET(MONO_LIB mono) - SET(M_LIBRARIES m) - SET(GTHREAD_2_0 gthread-2.0) -endif(WINDOWS) - - -IF (DARWIN) - - FIND_LIBRARY(MONO_LIBRARY NAMES Mono) - # Find_file doesnt work as expected. Hardcode relative to Mono.framework. - #FIND_FILE(GLIB_CONFIG glibconfig.h ${MONO_LIBRARY}) - #FIND_FILE(MONO_GLIB_LIBRARY glib.h ${MONO_LIBRARY}) - SET(MONO_GLIB_LIBRARY ${MONO_LIBRARY}/Headers/glib-2.0/) - SET(GLIB_CONFIG ${MONO_LIBRARY}/Libraries/glib-2.0/include/) - SET(MONO_LIB_DIRECTORY ${MONO_LIBRARY}/Libraries) - - IF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - MESSAGE(STATUS "Found Mono for embedding") - INCLUDE_DIRECTORIES(${MONO_GLIB_LIBRARY} ${GLIB_CONFIG}) - LINK_DIRECTORIES(${MONO_LIB_DIRECTORY}) - ELSE (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - MESSAGE(FATAL_ERROR "Mono not found for embedding") - MESSAGE(${MONO_LIBRARY}) - MESSAGE(${MONO_GLIB_LIBRARY}) - MESSAGE(${GLIB_CONFIG}) - ENDIF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - -ELSE (DARWIN) - - SET(MONO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) - SET(GLIB_2_0_PLATFORM_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/include/glib-2.0) - SET(GLIB_2_0_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/glib-2.0) - - INCLUDE_DIRECTORIES( - ${MONO_INCLUDE_DIR} - ${GLIB_2_0_PLATFORM_INCLUDE_DIR} - ${GLIB_2_0_INCLUDE_DIR}) - -ENDIF (DARWIN) - -SET(MONO_LIBRARIES - ${MONO_LIB} - ${M_LIBRARIES} - ${GLIB_2_0} - ${GTHREAD_2_0} -) diff --git a/indra/cmake/MySQL.cmake b/indra/cmake/MySQL.cmake deleted file mode 100755 index 218482449d..0000000000 --- a/indra/cmake/MySQL.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# -*- cmake -*- -include(Linking) -include(Prebuilt) - -use_prebuilt_binary(mysql) - -if (LINUX) - if (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") - set(MYSQL_LIBRARIES mysqlclient) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) - else (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") - # Use the native MySQL library on a 64-bit system. - set(MYSQL_FIND_QUIETLY ON) - set(MYSQL_FIND_REQUIRED ON) - include(FindMySQL) - endif (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") -elseif (WINDOWS) - set(MYSQL_LIBRARIES mysqlclient) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) -elseif (DARWIN) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) - set(MYSQL_LIBRARIES - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libmysqlclient.a - debug ${ARCH_PREBUILT_DIRS_DEBUG}/libmysqlclient.a - ) -endif (LINUX) diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake index 0a3dd976b4..2259c99293 100755 --- a/indra/cmake/OpenGL.cmake +++ b/indra/cmake/OpenGL.cmake @@ -1,8 +1,12 @@ # -*- cmake -*- + +include(Variables) include(Prebuilt) -if (NOT STANDALONE) - use_prebuilt_binary(glext) - use_prebuilt_binary(glh_linear) - set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) -endif (NOT STANDALONE) +if (BUILD_HEADLESS) + SET(OPENGL_glu_LIBRARY GLU) + SET(OPENGL_HEADLESS_LIBRARIES OSMesa16 dl GLU) +endif (BUILD_HEADLESS) + +include(FindOpenGL) + diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index dbb4dfc46c..ac0cbde253 100755 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -1,5 +1,8 @@ # -*- cmake -*- +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + include(FindAutobuild) if(INSTALL_PROPRIETARY) include(FindSCP) @@ -51,3 +54,5 @@ macro (use_prebuilt_binary _binary) endif (NOT ${_binary}_installed EQUAL 0) endif (NOT STANDALONE_${_binary}) endmacro (use_prebuilt_binary _binary) + +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 748c8c2bec..a81c9307fc 100755 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -23,7 +23,7 @@ if (WINDOWS) elseif (EXISTS /etc/debian_version) # On Debian and Ubuntu, avoid Python 2.4 if possible. - find_program(PYTHON_EXECUTABLE python2.5 python2.3 python PATHS /usr/bin) + find_program(PYTHON_EXECUTABLE python PATHS /usr/bin) if (PYTHON_EXECUTABLE) set(PYTHONINTERP_FOUND ON) diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 91e5258fb7..d0fd4df03a 100755 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -1,5 +1,6 @@ # -*- cmake -*- include(Prebuilt) +include(FreeType) if (STANDALONE) include(FindPkgConfig) @@ -47,6 +48,7 @@ else (STANDALONE) pangoft2-1.0 pangox-1.0 pangoxft-1.0 + ${FREETYPE_LIBRARIES} ) endif (LINUX) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 4b459f1a48..6ec621632b 100755 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -8,24 +8,20 @@ # DARWIN - Mac OS X # LINUX - Linux # WINDOWS - Windows -# -# What to build: -# -# VIEWER - viewer and other viewer-side components -# SERVER - simulator and other server-side bits # Relative and absolute paths to subtrees. +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + if(NOT DEFINED COMMON_CMAKE_DIR) set(COMMON_CMAKE_DIR "${CMAKE_SOURCE_DIR}/cmake") endif(NOT DEFINED COMMON_CMAKE_DIR) set(LIBS_CLOSED_PREFIX) set(LIBS_OPEN_PREFIX) -set(LIBS_SERVER_PREFIX) set(SCRIPTS_PREFIX ../scripts) -set(SERVER_PREFIX) set(VIEWER_PREFIX) set(INTEGRATION_TESTS_PREFIX) set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation") @@ -43,9 +39,7 @@ else(LIBS_COMMON_DIR) endif(LIBS_COMMON_DIR) set(LIBS_OPEN_DIR ${LIBS_COMMON_DIR}) -set(LIBS_SERVER_DIR ${CMAKE_SOURCE_DIR}/${LIBS_SERVER_PREFIX}) set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX}) -set(SERVER_DIR ${CMAKE_SOURCE_DIR}/${SERVER_PREFIX}) set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX}) set(AUTOBUILD_INSTALL_DIR ${CMAKE_BINARY_DIR}/packages) @@ -79,21 +73,57 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # If someone has specified a word size, use that to determine the # architecture. Otherwise, let the architecture specify the word size. if (WORD_SIZE EQUAL 32) + #message(STATUS "WORD_SIZE is 32") set(ARCH i686) elseif (WORD_SIZE EQUAL 64) + #message(STATUS "WORD_SIZE is 64") set(ARCH x86_64) else (WORD_SIZE EQUAL 32) + #message(STATUS "WORD_SIZE is UNDEFINED") execute_process(COMMAND uname -m COMMAND sed s/i.86/i686/ OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) if (ARCH STREQUAL x86_64) + #message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}") set(WORD_SIZE 64) else (ARCH STREQUAL x86_64) + #message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}") set(WORD_SIZE 32) endif (ARCH STREQUAL x86_64) endif (WORD_SIZE EQUAL 32) + if (WORD_SIZE EQUAL 32) + set(DEB_ARCHITECTURE i386) + set(FIND_LIBRARY_USE_LIB64_PATHS OFF) + set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH}) + else (WORD_SIZE EQUAL 32) + set(DEB_ARCHITECTURE amd64) + set(FIND_LIBRARY_USE_LIB64_PATHS ON) + endif (WORD_SIZE EQUAL 32) + + execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH + RESULT_VARIABLE DPKG_RESULT + OUTPUT_VARIABLE DPKG_ARCH + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + #message (STATUS "DPKG_RESULT ${DPKG_RESULT}, DPKG_ARCH ${DPKG_ARCH}") + if (DPKG_RESULT EQUAL 0) + set(CMAKE_LIBRARY_ARCHITECTURE ${DPKG_ARCH}) + set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib/${DPKG_ARCH} /usr/local/lib/${DPKG_ARCH} ${CMAKE_SYSTEM_LIBRARY_PATH}) + endif (DPKG_RESULT EQUAL 0) + + include(ConfigurePkgConfig) + set(LL_ARCH ${ARCH}_linux) set(LL_ARCH_DIR ${ARCH}-linux) + + if (INSTALL_PROPRIETARY) + # Only turn on headless if we can find osmesa libraries. + include(FindPkgConfig) + #pkg_check_modules(OSMESA osmesa) + #if (OSMESA_FOUND) + # set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") + #endif (OSMESA_FOUND) + endif (INSTALL_PROPRIETARY) + endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -140,7 +170,6 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Default deploy grid set(GRID agni CACHE STRING "Target Grid") -set(VIEWER ON CACHE BOOL "Build Second Life viewer.") set(VIEWER_CHANNEL "LindenDeveloper" CACHE STRING "Viewer Channel Name") set(VIEWER_LOGIN_CHANNEL ${VIEWER_CHANNEL} CACHE STRING "Fake login channel for A/B Testing") @@ -153,21 +182,8 @@ set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside") set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.") set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.") -if (NOT STANDALONE AND EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - set(SERVER ON CACHE BOOL "Build Second Life server software.") -endif (NOT STANDALONE AND EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - -if (LINUX AND SERVER AND VIEWER) - MESSAGE(FATAL_ERROR " -The indra source does not currently support building SERVER and VIEWER at the same time. -Please set one of these values to OFF in your CMake cache file. -(either by running ccmake or by editing CMakeCache.txt by hand) -For more information, please see JIRA DEV-14943 - Cmake Linux cannot build both VIEWER and SERVER in one build environment - ") -endif (LINUX AND SERVER AND VIEWER) - - set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") source_group("CMake Rules" FILES CMakeLists.txt) +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/VisualLeakDetector.cmake b/indra/cmake/VisualLeakDetector.cmake index d3ba554e46..27e93e28bb 100755 --- a/indra/cmake/VisualLeakDetector.cmake +++ b/indra/cmake/VisualLeakDetector.cmake @@ -1,15 +1,12 @@ # -*- cmake -*- -if (VIEWER) +set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off") - set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off") +if (INCLUDE_VLD_CMAKE) - if (INCLUDE_VLD_CMAKE) + if (WINDOWS) + add_definitions(-DINCLUDE_VLD=1) + endif (WINDOWS) - if (WINDOWS) - add_definitions(-DINCLUDE_VLD=1) - endif (WINDOWS) +endif (INCLUDE_VLD_CMAKE) - endif (INCLUDE_VLD_CMAKE) - -endif (VIEWER) diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt index af5c9fb2e7..36a7d38bb7 100755 --- a/indra/integration_tests/llimage_libtest/CMakeLists.txt +++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt @@ -16,6 +16,9 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) set(llimage_libtest_SOURCE_FILES llimage_libtest.cpp diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 91c9f20c10..e83b4e8cd7 100755 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -34,6 +34,10 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LIBS_PREBUILD_DIR}/include/hunspell ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llui_libtest_SOURCE_FILES llui_libtest.cpp diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt index a1f334ffad..41b92b00e0 100755 --- a/indra/linux_crash_logger/CMakeLists.txt +++ b/indra/linux_crash_logger/CMakeLists.txt @@ -22,6 +22,10 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(linux_crash_logger_SOURCE_FILES linux_crash_logger.cpp diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt new file mode 100644 index 0000000000..4a9e82f9b6 --- /dev/null +++ b/indra/linux_updater/CMakeLists.txt @@ -0,0 +1,57 @@ +# -*- cmake -*- + +project(linux_updater) + +include(00-Common) +include(CURL) +include(CARes) +include(OpenSSL) +include(UI) +include(LLCommon) +include(LLMessage) +include(LLVFS) +include(LLXML) +include(LLUI) +include(Linking) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} + ${CURL_INCLUDE_DIRS} + ${CARES_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIRS} + ${UI_INCLUDE_DIRS} + ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) + +set(linux_updater_SOURCE_FILES linux_updater.cpp) + +set(linux_updater_HEADER_FILES CMakeLists.txt) + +set_source_files_properties(${linux_updater_HEADER_FILES} + PROPERTIES HEADER_FILES_ONLY TRUE) + +list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES}) + +add_executable(linux-updater ${linux_updater_SOURCE_FILES}) + +target_link_libraries(linux-updater + ${CURL_LIBRARIES} + ${CARES_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${CRYPTO_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${UI_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLUI_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ) + +add_custom_target(linux-updater-target ALL + DEPENDS linux-updater) diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp new file mode 100644 index 0000000000..86fa596aef --- /dev/null +++ b/indra/linux_updater/linux_updater.cpp @@ -0,0 +1,924 @@ +/** + * @file linux_updater.cpp + * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden + * @brief Viewer update program for unix platforms that support GTK+ + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include <unistd.h> +#include <signal.h> +#include <errno.h> + +#include "linden_common.h" +#include "llerrorcontrol.h" +#include "llfile.h" +#include "lldir.h" +#include "lldiriterator.h" + +/*==========================================================================*| +// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy. +// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable. +#include "llxmlnode.h" +#include "lltrans.h" +|*==========================================================================*/ + +static class LLTrans +{ +public: + LLTrans(); + static std::string getString(const std::string& key); + +private: + std::string _getString(const std::string& key) const; + + typedef std::map<std::string, std::string> MessageMap; + MessageMap mMessages; +} sLLTransInstance; + +#include <curl/curl.h> +#include <map> +#include <boost/foreach.hpp> + +extern "C" { +#include <gtk/gtk.h> +} + +const guint UPDATE_PROGRESS_TIMEOUT = 100; +const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000; +const guint ROTATE_IMAGE_TIMEOUT = 8000; + +typedef struct _updater_app_state { + std::string app_name; + std::string url; + std::string file; + std::string image_dir; + std::string dest_dir; + std::string strings_dirs; + std::string strings_file; + + LLDirIterator *image_dir_iter; + + GtkWidget *window; + GtkWidget *progress_bar; + GtkWidget *image; + + double progress_value; + bool activity_mode; + + guint image_rotation_timeout_id; + guint progress_update_timeout_id; + guint update_progress_text_timeout_id; + + bool failure; +} UpdaterAppState; + +// List of entries from strings.xml to always replace +static std::set<std::string> default_trans_args; +void init_default_trans_args() +{ + default_trans_args.insert("SECOND_LIFE"); // World + default_trans_args.insert("APP_NAME"); + default_trans_args.insert("SECOND_LIFE_GRID"); + default_trans_args.insert("SUPPORT_SITE"); +} + +bool translate_init(std::string comma_delim_path_list, + std::string base_xml_name) +{ + return true; +/*==========================================================================*| + init_default_trans_args(); + + // extract paths string vector from comma-delimited flat string + std::vector<std::string> paths; + LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ',' + + for(std::vector<std::string>::iterator it = paths.begin(), end_it = paths.end(); + it != end_it; + ++it) + { + (*it) = gDirUtilp->findSkinnedFilename(*it, base_xml_name); + } + + // suck the translation xml files into memory + LLXMLNodePtr root; + bool success = LLXMLNode::getLayeredXMLNode(root, paths); + if (!success) + { + // couldn't load string table XML + return false; + } + else + { + // get those strings out of the XML + LLTrans::parseStrings(root, default_trans_args); + return true; + } +|*==========================================================================*/ +} + + +void updater_app_ui_init(void); +void updater_app_quit(UpdaterAppState *app_state); +void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); +std::string next_image_filename(std::string& image_path, LLDirIterator& iter); +void display_error(GtkWidget *parent, std::string title, std::string message); +BOOL install_package(std::string package_file, std::string destination); +BOOL spawn_viewer(UpdaterAppState *app_state); + +extern "C" { + void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state); + gpointer worker_thread_cb(gpointer *data); + int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow); + gboolean rotate_image_cb(gpointer data); + gboolean progress_update_timeout(gpointer data); + gboolean update_progress_text_timeout(gpointer data); +} + +void updater_app_ui_init(UpdaterAppState *app_state) +{ + GtkWidget *vbox; + GtkWidget *summary_label; + GtkWidget *description_label; + GtkWidget *frame; + + llassert(app_state != NULL); + + // set up window and main container + std::string window_title = LLTrans::getString("UpdaterWindowTitle"); + app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(app_state->window), + window_title.c_str()); + gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE); + gtk_window_set_position(GTK_WINDOW(app_state->window), + GTK_WIN_POS_CENTER_ALWAYS); + + gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12); + g_signal_connect(G_OBJECT(app_state->window), "delete-event", + G_CALLBACK(on_window_closed), app_state); + + vbox = gtk_vbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(app_state->window), vbox); + + // set top label + std::ostringstream label_ostr; + label_ostr << "<big><b>" + << LLTrans::getString("UpdaterNowUpdating") + << "</b></big>"; + + summary_label = gtk_label_new(NULL); + gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE); + gtk_label_set_markup(GTK_LABEL(summary_label), + label_ostr.str().c_str()); + gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0); + + // create the description label + description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str()); + gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE); + gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0); + + // If an image path has been set, load the background images + if (!app_state->image_dir.empty()) { + frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); + + // load the first image + app_state->image = gtk_image_new_from_file + (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str()); + gtk_widget_set_size_request(app_state->image, 340, 310); + gtk_container_add(GTK_CONTAINER(frame), app_state->image); + + // rotate the images every 5 seconds + app_state->image_rotation_timeout_id = g_timeout_add + (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state); + } + + // set up progress bar, and update it roughly every 1/10 of a second + app_state->progress_bar = gtk_progress_bar_new(); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), + LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str()); + gtk_box_pack_start(GTK_BOX(vbox), + app_state->progress_bar, FALSE, TRUE, 0); + app_state->progress_update_timeout_id = g_timeout_add + (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state); + app_state->update_progress_text_timeout_id = g_timeout_add + (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state); + + gtk_widget_show_all(app_state->window); +} + +gboolean rotate_image_cb(gpointer data) +{ + UpdaterAppState *app_state; + std::string filename; + + llassert(data != NULL); + app_state = (UpdaterAppState *) data; + + filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter); + + gdk_threads_enter(); + gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); + gdk_threads_leave(); + + return TRUE; +} + +std::string next_image_filename(std::string& image_path, LLDirIterator& iter) +{ + std::string image_filename; + iter.next(image_filename); + return gDirUtilp->add(image_path, image_filename); +} + +void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data) +{ + UpdaterAppState *app_state; + + llassert(data != NULL); + app_state = (UpdaterAppState *) data; + + updater_app_quit(app_state); +} + +void updater_app_quit(UpdaterAppState *app_state) +{ + if (app_state != NULL) + { + g_source_remove(app_state->progress_update_timeout_id); + + if (!app_state->image_dir.empty()) + { + g_source_remove(app_state->image_rotation_timeout_id); + } + } + + gtk_main_quit(); +} + +void display_error(GtkWidget *parent, std::string title, std::string message) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new(GTK_WINDOW(parent), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", message.c_str()); + gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +gpointer worker_thread_cb(gpointer data) +{ + UpdaterAppState *app_state; + CURL *curl; + CURLcode result; + FILE *package_file; + GError *error = NULL; + int fd; + + //g_return_val_if_fail (data != NULL, NULL); + app_state = (UpdaterAppState *) data; + + try { + + if(!app_state->url.empty()) + { + char* tmp_local_filename = NULL; + // create temporary file to store the package. + fd = g_file_open_tmp + ("secondlife-update-XXXXXX", &tmp_local_filename, &error); + if (error != NULL) + { + llerrs << "Unable to create temporary file: " + << error->message + << llendl; + + g_error_free(error); + throw 0; + } + + if(tmp_local_filename != NULL) + { + app_state->file = tmp_local_filename; + g_free(tmp_local_filename); + } + + package_file = fdopen(fd, "wb"); + if (package_file == NULL) + { + llerrs << "Failed to create temporary file: " + << app_state->file.c_str() + << llendl; + + gdk_threads_enter(); + display_error(app_state->window, + LLTrans::getString("UpdaterFailDownloadTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); + gdk_threads_leave(); + throw 0; + } + + // initialize curl and start downloading the package + llinfos << "Downloading package: " << app_state->url << llendl; + + curl = curl_easy_init(); + if (curl == NULL) + { + llerrs << "Failed to initialize libcurl" << llendl; + + gdk_threads_enter(); + display_error(app_state->window, + LLTrans::getString("UpdaterFailDownloadTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); + gdk_threads_leave(); + throw 0; + } + + curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str()); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, + &download_progress_cb); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state); + + result = curl_easy_perform(curl); + fclose(package_file); + curl_easy_cleanup(curl); + + if (result) + { + llerrs << "Failed to download update: " + << app_state->url + << llendl; + + gdk_threads_enter(); + display_error(app_state->window, + LLTrans::getString("UpdaterFailDownloadTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); + gdk_threads_leave(); + + throw 0; + } + } + + // now pulse the progres bar back and forth while the package is + // being unpacked + gdk_threads_enter(); + std::string installing_msg = LLTrans::getString("UpdaterNowInstalling"); + gtk_progress_bar_set_text( + GTK_PROGRESS_BAR(app_state->progress_bar), + installing_msg.c_str()); + app_state->activity_mode = TRUE; + gdk_threads_leave(); + + // *TODO: if the destination is not writable, terminate this + // thread and show file chooser? + if (!install_package(app_state->file.c_str(), app_state->dest_dir)) + { + llwarns << "Failed to install package to destination: " + << app_state->dest_dir + << llendl; + + gdk_threads_enter(); + display_error(app_state->window, + LLTrans::getString("UpdaterFailInstallTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); + //"Failed to update " + app_state->app_name, + gdk_threads_leave(); + throw 0; + } + + // try to spawn the new viewer + if (!spawn_viewer(app_state)) + { + llwarns << "Viewer was not installed properly in : " + << app_state->dest_dir + << llendl; + + gdk_threads_enter(); + display_error(app_state->window, + LLTrans::getString("UpdaterFailStartTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); + gdk_threads_leave(); + throw 0; + } + } + catch (...) + { + app_state->failure = TRUE; + } + + gdk_threads_enter(); + updater_app_quit(app_state); + gdk_threads_leave(); + + return NULL; +} + + +gboolean less_anal_gspawnsync(gchar **argv, + gchar **stderr_output, + gint *child_exit_status, + GError **spawn_error) +{ + // store current SIGCHLD handler if there is one, replace with default + // handler to make glib happy + struct sigaction sigchld_backup; + struct sigaction sigchld_appease_glib; + sigchld_appease_glib.sa_handler = SIG_DFL; + sigemptyset(&sigchld_appease_glib.sa_mask); + sigchld_appease_glib.sa_flags = 0; + sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); + + gboolean rtn = g_spawn_sync(NULL, + argv, + NULL, + (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL), + NULL, + NULL, + NULL, + stderr_output, + child_exit_status, + spawn_error); + + // restore SIGCHLD handler + sigaction(SIGCHLD, &sigchld_backup, NULL); + + return rtn; +} + + +// perform a rename, or perform a (prompted) root rename if that fails +int +rename_with_sudo_fallback(const std::string& filename, const std::string& newname) +{ + int rtncode = ::rename(filename.c_str(), newname.c_str()); + lldebugs << "rename result is: " << rtncode << " / " << errno << llendl; + if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno)) + { + llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl; + // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack + char *sudo_cmd = NULL; + sudo_cmd = g_find_program_in_path("gksudo"); + if (!sudo_cmd) + { + sudo_cmd = g_find_program_in_path("kdesu"); + } + if (sudo_cmd) + { + char *mv_cmd = NULL; + mv_cmd = g_find_program_in_path("mv"); + if (mv_cmd) + { + char *src_string_copy = g_strdup(filename.c_str()); + char *dst_string_copy = g_strdup(newname.c_str()); + char* argv[] = + { + sudo_cmd, + mv_cmd, + src_string_copy, + dst_string_copy, + NULL + }; + + gchar *stderr_output = NULL; + gint child_exit_status = 0; + GError *spawn_error = NULL; + if (!less_anal_gspawnsync(argv, &stderr_output, + &child_exit_status, &spawn_error)) + { + llwarns << "Failed to spawn child process: " + << spawn_error->message + << llendl; + } + else if (child_exit_status) + { + llwarns << "mv command failed: " + << (stderr_output ? stderr_output : "(no reason given)") + << llendl; + } + else + { + // everything looks good, clear the error code + rtncode = 0; + } + + g_free(src_string_copy); + g_free(dst_string_copy); + if (spawn_error) g_error_free(spawn_error); + } + } + } + return rtncode; +} + +gboolean install_package(std::string package_file, std::string destination) +{ + char *tar_cmd = NULL; + std::ostringstream command; + + // Find the absolute path to the 'tar' command. + tar_cmd = g_find_program_in_path("tar"); + if (!tar_cmd) + { + llerrs << "`tar' was not found in $PATH" << llendl; + return FALSE; + } + llinfos << "Found tar command: " << tar_cmd << llendl; + + // Unpack the tarball in a temporary place first, then move it to + // its final destination + std::string tmp_dest_dir = gDirUtilp->getTempFilename(); + if (LLFile::mkdir(tmp_dest_dir, 0744)) + { + llerrs << "Failed to create directory: " + << destination + << llendl; + + return FALSE; + } + + char *package_file_string_copy = g_strdup(package_file.c_str()); + char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str()); + gchar *argv[8] = { + tar_cmd, + const_cast<gchar*>("--strip"), const_cast<gchar*>("1"), + const_cast<gchar*>("-xjf"), + package_file_string_copy, + const_cast<gchar*>("-C"), tmp_dest_dir_string_copy, + NULL, + }; + + llinfos << "Untarring package: " << package_file << llendl; + + // store current SIGCHLD handler if there is one, replace with default + // handler to make glib happy + struct sigaction sigchld_backup; + struct sigaction sigchld_appease_glib; + sigchld_appease_glib.sa_handler = SIG_DFL; + sigemptyset(&sigchld_appease_glib.sa_mask); + sigchld_appease_glib.sa_flags = 0; + sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); + + gchar *stderr_output = NULL; + gint child_exit_status = 0; + GError *untar_error = NULL; + if (!less_anal_gspawnsync(argv, &stderr_output, + &child_exit_status, &untar_error)) + { + llwarns << "Failed to spawn child process: " + << untar_error->message + << llendl; + return FALSE; + } + + if (child_exit_status) + { + llwarns << "Untar command failed: " + << (stderr_output ? stderr_output : "(no reason given)") + << llendl; + return FALSE; + } + + g_free(tar_cmd); + g_free(package_file_string_copy); + g_free(tmp_dest_dir_string_copy); + g_free(stderr_output); + if (untar_error) g_error_free(untar_error); + + // move the existing package out of the way if it exists + if (gDirUtilp->fileExists(destination)) + { + std::string backup_dir = destination + ".backup"; + int oldcounter = 1; + while (gDirUtilp->fileExists(backup_dir)) + { + // find a foo.backup.N folder name that isn't taken yet + backup_dir = destination + ".backup." + llformat("%d", oldcounter); + ++oldcounter; + } + + if (rename_with_sudo_fallback(destination, backup_dir)) + { + llwarns << "Failed to move directory: '" + << destination << "' -> '" << backup_dir + << llendl; + return FALSE; + } + } + + // The package has been unpacked in a staging directory, now we just + // need to move it to its destination. + if (rename_with_sudo_fallback(tmp_dest_dir, destination)) + { + llwarns << "Failed to move installation to the destination: " + << destination + << llendl; + return FALSE; + } + + // \0/ Success! + return TRUE; +} + +gboolean progress_update_timeout(gpointer data) +{ + UpdaterAppState *app_state; + + llassert(data != NULL); + + app_state = (UpdaterAppState *) data; + + gdk_threads_enter(); + if (app_state->activity_mode) + { + gtk_progress_bar_pulse + (GTK_PROGRESS_BAR(app_state->progress_bar)); + } + else + { + gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar), + app_state->progress_value); + } + gdk_threads_leave(); + + return TRUE; +} + +gboolean update_progress_text_timeout(gpointer data) +{ + UpdaterAppState *app_state; + + llassert(data != NULL); + app_state = (UpdaterAppState *) data; + + if (app_state->activity_mode == TRUE) + { + // We no longer need this timeout, it will be removed. + return FALSE; + } + + if (!app_state->progress_value) + { + return TRUE; + } + + std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value); + + gdk_threads_enter(); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), + progress_text.c_str()); + gdk_threads_leave(); + + return TRUE; +} + +int download_progress_cb(gpointer data, + double t, + double d, + double utotal, + double ulnow) +{ + UpdaterAppState *app_state; + + llassert(data != NULL); + app_state = (UpdaterAppState *) data; + + if (t <= 0.0) + { + app_state->progress_value = 0; + } + else + { + app_state->progress_value = d * 100.0 / t; + } + return 0; +} + +BOOL spawn_viewer(UpdaterAppState *app_state) +{ + llassert(app_state != NULL); + + std::string cmd = app_state->dest_dir + "/secondlife"; + GError *error = NULL; + + // We want to spawn the Viewer on the same display as the updater app + gboolean success = gdk_spawn_command_line_on_screen + (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error); + + if (!success) + { + llwarns << "Failed to launch viewer: " << error->message + << llendl; + } + + if (error) g_error_free(error); + + return success; +} + +void show_usage_and_exit() +{ + std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE" + << "[--image-dir PATH]" + << std::endl; + exit(1); +} + +void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) +{ + int i; + + for (i = 1; i < argc; i++) + { + if ((!strcmp(argv[i], "--url")) && (++i < argc)) + { + app_state->url = argv[i]; + } + else if ((!strcmp(argv[i], "--file")) && (++i < argc)) + { + app_state->file = argv[i]; + } + else if ((!strcmp(argv[i], "--name")) && (++i < argc)) + { + app_state->app_name = argv[i]; + } + else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) + { + app_state->image_dir = argv[i]; + app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg"); + } + else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) + { + app_state->dest_dir = argv[i]; + } + else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc)) + { + app_state->strings_dirs = argv[i]; + } + else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc)) + { + app_state->strings_file = argv[i]; + } + else + { + // show usage, an invalid option was given. + show_usage_and_exit(); + } + } + + if (app_state->app_name.empty() + || (app_state->url.empty() && app_state->file.empty()) + || app_state->dest_dir.empty()) + { + show_usage_and_exit(); + } + + app_state->progress_value = 0.0; + app_state->activity_mode = FALSE; + app_state->failure = FALSE; + + translate_init(app_state->strings_dirs, app_state->strings_file); +} + +int main(int argc, char **argv) +{ + UpdaterAppState* app_state = new UpdaterAppState; + + parse_args_and_init(argc, argv, app_state); + + // Initialize logger, and rename old log file + gDirUtilp->initAppDirs("SecondLife"); + LLError::initForApplication + (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + std::string old_log_file = gDirUtilp->getExpandedFilename + (LL_PATH_LOGS, "updater.log.old"); + std::string log_file = + gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); + LLFile::rename(log_file, old_log_file); + LLError::logToFile(log_file); + + // initialize gthreads and gtk+ + if (!g_thread_supported()) + { + g_thread_init(NULL); + gdk_threads_init(); + } + + gtk_init(&argc, &argv); + + // create UI + updater_app_ui_init(app_state); + + //llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl; + + // create download thread + g_thread_create(GThreadFunc(worker_thread_cb), app_state, FALSE, NULL); + + gdk_threads_enter(); + gtk_main(); + gdk_threads_leave(); + + // Delete the file only if created from url download. + if(!app_state->url.empty() && !app_state->file.empty()) + { + if (gDirUtilp->fileExists(app_state->file)) + { + LLFile::remove(app_state->file); + } + } + + bool success = !app_state->failure; + delete app_state->image_dir_iter; + delete app_state; + return success ? 0 : 1; +} + +/***************************************************************************** +* Dummy LLTrans implementation (IQA-490) +*****************************************************************************/ +static LLTrans sStaticStrings; + +// lookup +std::string LLTrans::_getString(const std::string& key) const +{ + MessageMap::const_iterator found = mMessages.find(key); + if (found != mMessages.end()) + { + return found->second; + } + LL_WARNS("linux_updater") << "No message for key '" << key + << "' -- add to LLTrans::LLTrans() in linux_updater.cpp" + << LL_ENDL; + return key; +} + +// static lookup +std::string LLTrans::getString(const std::string& key) +{ + return sLLTransInstance._getString(key); +} + +// initialization +LLTrans::LLTrans() +{ + typedef std::pair<const char*, const char*> Pair; + static const Pair data[] = + { + Pair("UpdaterFailDownloadTitle", + "Failed to download update"), + Pair("UpdaterFailInstallTitle", + "Failed to install update"), + Pair("UpdaterFailStartTitle", + "Failed to start viewer"), + Pair("UpdaterFailUpdateDescriptive", + "An error occurred while updating Second Life. " + "Please download the latest version from www.secondlife.com."), + Pair("UpdaterNowInstalling", + "Installing Second Life..."), + Pair("UpdaterNowUpdating", + "Now updating Second Life..."), + Pair("UpdaterProgressBarText", + "Downloading update"), + Pair("UpdaterProgressBarTextWithEllipses", + "Downloading update..."), + Pair("UpdaterUpdatingDescriptive", + "Your Second Life Viewer is being updated to the latest release. " + "This may take some time, so please be patient."), + Pair("UpdaterWindowTitle", + "Second Life Update") + }; + + BOOST_FOREACH(Pair pair, data) + { + mMessages[pair.first] = pair.second; + } +} diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt new file mode 100644 index 0000000000..0dbd58b7cd --- /dev/null +++ b/indra/llappearance/CMakeLists.txt @@ -0,0 +1,118 @@ +# -*- cmake -*- + +project(llappearance) + +include(00-Common) +include(LLCommon) +include(LLCharacter) +include(LLImage) +include(LLInventory) +include(LLMath) +include(LLMessage) +include(LLRender) +include(LLVFS) +include(LLWindow) +include(LLXML) +include(Linking) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLCHARACTER_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLINVENTORY_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ) + +set(llappearance_SOURCE_FILES + llavatarappearance.cpp + llavatarjoint.cpp + llavatarjointmesh.cpp + lldriverparam.cpp + lllocaltextureobject.cpp + llpolyskeletaldistortion.cpp + llpolymesh.cpp + llpolymorph.cpp + lltexglobalcolor.cpp + lltexlayer.cpp + lltexlayerparams.cpp + lltexturemanagerbridge.cpp + llwearable.cpp + llwearabledata.cpp + llwearabletype.cpp + llviewervisualparam.cpp + llavatarappearancedefines.cpp + ) + +set(llappearance_HEADER_FILES + CMakeLists.txt + + llavatarappearance.h + llavatarjoint.h + llavatarjointmesh.h + lldriverparam.h + lljointpickname.h + lllocaltextureobject.h + llpolyskeletaldistortion.h + llpolymesh.h + llpolymorph.h + lltexglobalcolor.h + lltexlayer.h + lltexlayerparams.h + lltexturemanagerbridge.h + llwearable.h + llwearabledata.h + llwearabletype.h + llviewervisualparam.h + llavatarappearancedefines.h + ) + +set_source_files_properties(${llappearance_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llappearance_SOURCE_FILES ${llappearance_HEADER_FILES}) + +add_library (llappearance ${llappearance_SOURCE_FILES}) + +target_link_libraries(llappearance + ${LLCHARACTER_LIBRARIES} + ${LLINVENTORY_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLRENDER_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ) + +if (BUILD_HEADLESS) + add_library (llappearanceheadless ${llappearance_SOURCE_FILES}) + + target_link_libraries(llappearanceheadless + ${LLCHARACTER_LIBRARIES} + ${LLINVENTORY_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLRENDERHEADLESS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ) +endif (BUILD_HEADLESS) + +#add unit tests +#if (LL_TESTS) +# INCLUDE(LLAddBuildTest) +# SET(llappearance_TEST_SOURCE_FILES +# # no real unit tests yet! +# ) +# LL_ADD_PROJECT_UNIT_TESTS(llappearance "${llappearance_TEST_SOURCE_FILES}") + + #set(TEST_DEBUG on) +# set(test_libs llappearance ${LLCOMMON_LIBRARIES}) +#endif (LL_TESTS) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp new file mode 100644 index 0000000000..3bb759d458 --- /dev/null +++ b/indra/llappearance/llavatarappearance.cpp @@ -0,0 +1,1953 @@ +/** + * @File llavatarappearance.cpp + * @brief Implementation of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" +#include "imageids.h" +#include "lldir.h" +#include "lldeleteutils.h" +#include "llpolymorph.h" +#include "llpolymesh.h" +#include "llpolyskeletaldistortion.h" +#include "llstl.h" +#include "lltexglobalcolor.h" +#include "llwearabledata.h" + + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include <boost/lexical_cast.hpp> + +using namespace LLAvatarAppearanceDefines; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const std::string AVATAR_DEFAULT_CHAR = "avatar"; +const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); + +/********************************************************************************* + ** ** + ** Begin private LLAvatarAppearance Support classes + ** + **/ + +//------------------------------------------------------------------------ +// LLAvatarBoneInfo +// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. +//------------------------------------------------------------------------ +class LLAvatarBoneInfo +{ + friend class LLAvatarAppearance; + friend class LLAvatarSkeletonInfo; +public: + LLAvatarBoneInfo() : mIsJoint(FALSE) {} + ~LLAvatarBoneInfo() + { + std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + +private: + std::string mName; + BOOL mIsJoint; + LLVector3 mPos; + LLVector3 mRot; + LLVector3 mScale; + LLVector3 mPivot; + typedef std::vector<LLAvatarBoneInfo*> child_list_t; + child_list_t mChildList; +}; + +//------------------------------------------------------------------------ +// LLAvatarSkeletonInfo +// Overall avatar skeleton +//------------------------------------------------------------------------ +class LLAvatarSkeletonInfo +{ + friend class LLAvatarAppearance; +public: + LLAvatarSkeletonInfo() : + mNumBones(0), mNumCollisionVolumes(0) {} + ~LLAvatarSkeletonInfo() + { + std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + S32 getNumBones() const { return mNumBones; } + S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + +private: + S32 mNumBones; + S32 mNumCollisionVolumes; + typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLAvatarXmlInfo +//----------------------------------------------------------------------------- + +LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo() + : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) +{ +} + +LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() +{ + std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); + deleteAndClear(mTexSkinColorInfo); + deleteAndClear(mTexHairColorInfo); + deleteAndClear(mTexEyeColorInfo); + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); + std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); +} + + +/** + ** + ** End LLAvatarAppearance Support classes + ** ** + *********************************************************************************/ + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +LLXmlTree LLAvatarAppearance::sXMLTree; +LLXmlTree LLAvatarAppearance::sSkeletonXMLTree; +LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL; +LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL; + + +LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : + LLCharacter(), + mIsDummy(FALSE), + mTexSkinColor( NULL ), + mTexHairColor( NULL ), + mTexEyeColor( NULL ), + mPelvisToFoot(0.f), + mHeadOffset(), + mRoot(NULL), + mWearableData(wearable_data) +{ + llassert_always(mWearableData); + mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) + { + mBakedTextureDatas[i].mLastTextureID = IMG_DEFAULT_AVATAR; + mBakedTextureDatas[i].mTexLayerSet = NULL; + mBakedTextureDatas[i].mIsLoaded = false; + mBakedTextureDatas[i].mIsUsed = false; + mBakedTextureDatas[i].mMaskTexName = 0; + mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); + } + + mIsBuilt = FALSE; + + mNumCollisionVolumes = 0; + mCollisionVolumes = NULL; +} + +// virtual +void LLAvatarAppearance::initInstance() +{ + //------------------------------------------------------------------------- + // initialize joint, mesh and shape members + //------------------------------------------------------------------------- + mRoot = createAvatarJoint(); + mRoot->setName( "mRoot" ); + + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + ++iter) + { + const EMeshIndex mesh_index = iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; + LLAvatarJoint* joint = createAvatarJoint(); + joint->setName(mesh_dict->mName); + joint->setMeshID(mesh_index); + mMeshLOD.push_back(joint); + + /* mHairLOD.setName("mHairLOD"); + mHairMesh0.setName("mHairMesh0"); + mHairMesh0.setMeshID(MESH_ID_HAIR); + mHairMesh1.setName("mHairMesh1"); */ + for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) + { + LLAvatarJointMesh* mesh = createAvatarJointMesh(); + std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod); + // We pre-pended an m - need to capitalize first character for camelCase + mesh_name[1] = toupper(mesh_name[1]); + mesh->setName(mesh_name); + mesh->setMeshID(mesh_index); + mesh->setPickName(mesh_dict->mPickName); + mesh->setIsTransparent(FALSE); + switch((int)mesh_index) + { + case MESH_ID_HAIR: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_SKIRT: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_EYEBALL_LEFT: + case MESH_ID_EYEBALL_RIGHT: + mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); + break; + } + + joint->mMeshParts.push_back(mesh); + } + } + + //------------------------------------------------------------------------- + // associate baked textures with meshes + //------------------------------------------------------------------------- + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + ++iter) + { + const EMeshIndex mesh_index = iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; + const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; + // Skip it if there's no associated baked texture. + if (baked_texture_index == BAKED_NUM_INDICES) continue; + + for (avatar_joint_mesh_list_t::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); + iter != mMeshLOD[mesh_index]->mMeshParts.end(); + ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + mBakedTextureDatas[(int)baked_texture_index].mJointMeshes.push_back(mesh); + } + } + + buildCharacter(); + +} + +// virtual +LLAvatarAppearance::~LLAvatarAppearance() +{ + deleteAndClear(mTexSkinColor); + deleteAndClear(mTexHairColor); + deleteAndClear(mTexEyeColor); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); + mBakedTextureDatas[i].mJointMeshes.clear(); + + for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); + iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) + { + LLMaskedMorph* masked_morph = (*iter2); + delete masked_morph; + } + } + + if (mRoot) mRoot->removeAllChildren(); + mJointMap.clear(); + + clearSkeleton(); + deleteAndClearArray(mCollisionVolumes); + + deleteAndClear(mTexSkinColor); + deleteAndClear(mTexHairColor); + deleteAndClear(mTexEyeColor); + + std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer()); + mPolyMeshes.clear(); + + for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); + ++jointIter) + { + LLAvatarJoint* joint = *jointIter; + std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); + joint->mMeshParts.clear(); + } + std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); + mMeshLOD.clear(); +} + +//static +void LLAvatarAppearance::initClass() +{ + std::string xmlFile; + + xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; + BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); + if (!success) + { + llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl; + } + + // now sanity check xml file + LLXmlTreeNode* root = sXMLTree.getRoot(); + if (!root) + { + llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; + return; + } + + //------------------------------------------------------------------------- + // <linden_avatar version="1.0"> (root) + //------------------------------------------------------------------------- + if( !root->hasName( "linden_avatar" ) ) + { + llerrs << "Invalid avatar file header: " << xmlFile << llendl; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + { + llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl; + } + + S32 wearable_def_version = 1; + static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); + root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); + LLWearable::setCurrentDefinitionVersion( wearable_def_version ); + + std::string mesh_file_name; + + LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); + if (!skeleton_node) + { + llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl; + return; + } + + std::string skeleton_file_name; + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) + { + llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl; + } + + std::string skeleton_path; + skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); + if (!parseSkeletonFile(skeleton_path)) + { + llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; + } + + // Process XML data + + // avatar_skeleton.xml + if (sAvatarSkeletonInfo) + { //this can happen if a login attempt failed + delete sAvatarSkeletonInfo; + } + sAvatarSkeletonInfo = new LLAvatarSkeletonInfo; + if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) + { + llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; + } + // parse avatar_lad.xml + if (sAvatarXmlInfo) + { //this can happen if a login attempt failed + deleteAndClear(sAvatarXmlInfo); + } + sAvatarXmlInfo = new LLAvatarXmlInfo; + if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlColorNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } +} + +void LLAvatarAppearance::cleanupClass() +{ + deleteAndClear(sAvatarXmlInfo); + // *TODO: What about sAvatarSkeletonInfo ??? + sSkeletonXMLTree.cleanup(); + sXMLTree.cleanup(); +} + +using namespace LLAvatarAppearanceDefines; + +//------------------------------------------------------------------------ +// The viewer can only suggest a good size for the agent, +// the simulator will keep it inside a reasonable range. +void LLAvatarAppearance::computeBodySize() +{ + LLVector3 pelvis_scale = mPelvisp->getScale(); + + // some of the joints have not been cached + LLVector3 skull = mSkullp->getPosition(); + //LLVector3 skull_scale = mSkullp->getScale(); + + LLVector3 neck = mNeckp->getPosition(); + LLVector3 neck_scale = mNeckp->getScale(); + + LLVector3 chest = mChestp->getPosition(); + LLVector3 chest_scale = mChestp->getScale(); + + // the rest of the joints have been cached + LLVector3 head = mHeadp->getPosition(); + LLVector3 head_scale = mHeadp->getScale(); + + LLVector3 torso = mTorsop->getPosition(); + LLVector3 torso_scale = mTorsop->getScale(); + + LLVector3 hip = mHipLeftp->getPosition(); + LLVector3 hip_scale = mHipLeftp->getScale(); + + LLVector3 knee = mKneeLeftp->getPosition(); + LLVector3 knee_scale = mKneeLeftp->getScale(); + + LLVector3 ankle = mAnkleLeftp->getPosition(); + LLVector3 ankle_scale = mAnkleLeftp->getScale(); + + LLVector3 foot = mFootLeftp->getPosition(); + + F32 old_offset = mAvatarOffset.mV[VZ]; + + mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER); + + mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - + knee.mV[VZ] * hip_scale.mV[VZ] - + ankle.mV[VZ] * knee_scale.mV[VZ] - + foot.mV[VZ] * ankle_scale.mV[VZ]; + + LLVector3 new_body_size; + new_body_size.mV[VZ] = mPelvisToFoot + + // the sqrt(2) correction below is an approximate + // correction to get to the top of the head + F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + + head.mV[VZ] * neck_scale.mV[VZ] + + neck.mV[VZ] * chest_scale.mV[VZ] + + chest.mV[VZ] * torso_scale.mV[VZ] + + torso.mV[VZ] * pelvis_scale.mV[VZ]; + + // TODO -- measure the real depth and width + new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; + new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + + mAvatarOffset.mV[VX] = 0.0f; + mAvatarOffset.mV[VY] = 0.0f; + + // Certain configurations of avatars can force the overall height (with offset) to go negative. + // Enforce a constraint to make sure we don't go below 0.1 meters. + // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground + if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f) + { + mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail. + + llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f); + + if (mWearableData && isSelf()) + { + LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0); + if (shape) + { + shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false); + } + } + } + + if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ]) + { + mBodySize = new_body_size; + bodySizeChanged(); + } +} + +//----------------------------------------------------------------------------- +// parseSkeletonFile() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename) +{ + //------------------------------------------------------------------------- + // parse the file + //------------------------------------------------------------------------- + BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); + + if (!parsesuccess) + { + llerrs << "Can't parse skeleton file: " << filename << llendl; + return FALSE; + } + + // now sanity check xml file + LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); + if (!root) + { + llerrs << "No root node found in avatar skeleton file: " << filename << llendl; + return FALSE; + } + + if( !root->hasName( "linden_skeleton" ) ) + { + llerrs << "Invalid avatar skeleton file header: " << filename << llendl; + return FALSE; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + { + llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; + return FALSE; + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// setupBone() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) +{ + LLJoint* joint = NULL; + + if (info->mIsJoint) + { + joint = getCharacterJoint(joint_num); + if (!joint) + { + llwarns << "Too many bones" << llendl; + return FALSE; + } + joint->setName( info->mName ); + } + else // collision volume + { + if (volume_num >= (S32)mNumCollisionVolumes) + { + llwarns << "Too many bones" << llendl; + return FALSE; + } + joint = (&mCollisionVolumes[volume_num]); + joint->setName( info->mName ); + } + + // add to parent + if (parent) + { + parent->addChild( joint ); + } + + joint->setPosition(info->mPos); + joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], + info->mRot.mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info->mScale); + + joint->setDefaultFromCurrentXform(); + + if (info->mIsJoint) + { + joint->setSkinOffset( info->mPivot ); + joint_num++; + } + else // collision volume + { + volume_num++; + } + + // setup children + LLAvatarBoneInfo::child_list_t::const_iterator iter; + for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) + { + LLAvatarBoneInfo *child_info = *iter; + if (!setupBone(child_info, joint, volume_num, joint_num)) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// allocateCharacterJoints() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) +{ + clearSkeleton(); + + for(S32 joint_num = 0; joint_num < (S32)num; joint_num++) + { + mSkeleton.push_back(createAvatarJoint(joint_num)); + } + + return TRUE; +} + + +//----------------------------------------------------------------------------- +// buildSkeleton() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) +{ + //------------------------------------------------------------------------- + // allocate joints + //------------------------------------------------------------------------- + if (!allocateCharacterJoints(info->mNumBones)) + { + llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; + return FALSE; + } + + //------------------------------------------------------------------------- + // allocate volumes + //------------------------------------------------------------------------- + if (info->mNumCollisionVolumes) + { + if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) + { + llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; + return FALSE; + } + } + + S32 current_joint_num = 0; + S32 current_volume_num = 0; + LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; + for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + { + LLAvatarBoneInfo *info = *iter; + if (!setupBone(info, NULL, current_volume_num, current_joint_num)) + { + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// clearSkeleton() +//----------------------------------------------------------------------------- +void LLAvatarAppearance::clearSkeleton() +{ + std::for_each(mSkeleton.begin(), mSkeleton.end(), DeletePointer()); + mSkeleton.clear(); +} + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::buildCharacter() +// Deferred initialization and rebuild of the avatar. +//----------------------------------------------------------------------------- +void LLAvatarAppearance::buildCharacter() +{ + //------------------------------------------------------------------------- + // remove all references to our existing skeleton + // so we can rebuild it + //------------------------------------------------------------------------- + flushAllMotions(); + + //------------------------------------------------------------------------- + // remove all of mRoot's children + //------------------------------------------------------------------------- + mRoot->removeAllChildren(); + mJointMap.clear(); + mIsBuilt = FALSE; + + //------------------------------------------------------------------------- + // clear mesh data + //------------------------------------------------------------------------- + for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); ++jointIter) + { + LLAvatarJoint* joint = *jointIter; + for (avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); + meshIter != joint->mMeshParts.end(); ++meshIter) + { + LLAvatarJointMesh * mesh = *meshIter; + mesh->setMesh(NULL); + } + } + + //------------------------------------------------------------------------- + // (re)load our skeleton and meshes + //------------------------------------------------------------------------- + LLTimer timer; + + BOOL status = loadAvatar(); + stop_glerror(); + +// gPrintMessagesThisFrame = TRUE; + lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; + + if (!status) + { + if (isSelf()) + { + llerrs << "Unable to load user's avatar" << llendl; + } + else + { + llwarns << "Unable to load other's avatar" << llendl; + } + return; + } + + //------------------------------------------------------------------------- + // initialize "well known" joint pointers + //------------------------------------------------------------------------- + mPelvisp = mRoot->findJoint("mPelvis"); + mTorsop = mRoot->findJoint("mTorso"); + mChestp = mRoot->findJoint("mChest"); + mNeckp = mRoot->findJoint("mNeck"); + mHeadp = mRoot->findJoint("mHead"); + mSkullp = mRoot->findJoint("mSkull"); + mHipLeftp = mRoot->findJoint("mHipLeft"); + mHipRightp = mRoot->findJoint("mHipRight"); + mKneeLeftp = mRoot->findJoint("mKneeLeft"); + mKneeRightp = mRoot->findJoint("mKneeRight"); + mAnkleLeftp = mRoot->findJoint("mAnkleLeft"); + mAnkleRightp = mRoot->findJoint("mAnkleRight"); + mFootLeftp = mRoot->findJoint("mFootLeft"); + mFootRightp = mRoot->findJoint("mFootRight"); + mWristLeftp = mRoot->findJoint("mWristLeft"); + mWristRightp = mRoot->findJoint("mWristRight"); + mEyeLeftp = mRoot->findJoint("mEyeLeft"); + mEyeRightp = mRoot->findJoint("mEyeRight"); + + //------------------------------------------------------------------------- + // Make sure "well known" pointers exist + //------------------------------------------------------------------------- + if (!(mPelvisp && + mTorsop && + mChestp && + mNeckp && + mHeadp && + mSkullp && + mHipLeftp && + mHipRightp && + mKneeLeftp && + mKneeRightp && + mAnkleLeftp && + mAnkleRightp && + mFootLeftp && + mFootRightp && + mWristLeftp && + mWristRightp && + mEyeLeftp && + mEyeRightp)) + { + llerrs << "Failed to create avatar." << llendl; + return; + } + + //------------------------------------------------------------------------- + // initialize the pelvis + //------------------------------------------------------------------------- + mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); + + mIsBuilt = TRUE; + stop_glerror(); + +} + +BOOL LLAvatarAppearance::loadAvatar() +{ +// LLFastTimer t(FTM_LOAD_AVATAR); + + // avatar_skeleton.xml + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + llwarns << "avatar file: buildSkeleton() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : <skeleton> + if( !loadSkeletonNode() ) + { + llwarns << "avatar file: loadNodeSkeleton() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : <mesh> + if( !loadMeshNodes() ) + { + llwarns << "avatar file: loadNodeMesh() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : <global_color> + if( sAvatarXmlInfo->mTexSkinColorInfo ) + { + mTexSkinColor = new LLTexGlobalColor( this ); + if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) + { + llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << "<global_color> name=\"skin_color\" not found" << llendl; + return FALSE; + } + if( sAvatarXmlInfo->mTexHairColorInfo ) + { + mTexHairColor = new LLTexGlobalColor( this ); + if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) + { + llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << "<global_color> name=\"hair_color\" not found" << llendl; + return FALSE; + } + if( sAvatarXmlInfo->mTexEyeColorInfo ) + { + mTexEyeColor = new LLTexGlobalColor( this ); + if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) + { + llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << "<global_color> name=\"eye_color\" not found" << llendl; + return FALSE; + } + + // avatar_lad.xml : <layer_set> + if (sAvatarXmlInfo->mLayerInfoList.empty()) + { + llwarns << "avatar file: missing <layer_set> node" << llendl; + return FALSE; + } + + if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) + { + llwarns << "avatar file: missing <morph_masks> node" << llendl; + return FALSE; + } + + // avatar_lad.xml : <morph_masks> + for (LLAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin(); + iter != sAvatarXmlInfo->mMorphMaskInfoList.end(); + ++iter) + { + LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter; + + EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); + if (baked != BAKED_NUM_INDICES) + { + LLVisualParam* morph_param; + const std::string *name = &info->mName; + morph_param = getVisualParam(name->c_str()); + if (morph_param) + { + BOOL invert = info->mInvert; + addMaskedMorph(baked, morph_param, invert, info->mLayer); + } + } + + } + + loadLayersets(); + + // avatar_lad.xml : <driver_parameters> + for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); + ++iter) + { + LLDriverParamInfo *info = *iter; + LLDriverParam* driver_param = new LLDriverParam( this ); + if (driver_param->setInfo(info)) + { + addVisualParam( driver_param ); + driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; + if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) + { + llwarns << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << llendl; + continue; + } + } + else + { + delete driver_param; + llwarns << "avatar file: driver_param->parseData() failed" << llendl; + return FALSE; + } + } + + + return TRUE; +} + +//----------------------------------------------------------------------------- +// loadSkeletonNode(): loads <skeleton> node from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadSkeletonNode () +{ + mRoot->addChild( mSkeleton[0] ); + + // make meshes children before calling parent version of the function + for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); + ++iter) + { + LLAvatarJoint *joint = *iter; + joint->mUpdateXform = FALSE; + joint->setMeshesToChildren(); + } + + mRoot->addChild(mMeshLOD[MESH_ID_HEAD]); + mRoot->addChild(mMeshLOD[MESH_ID_EYELASH]); + mRoot->addChild(mMeshLOD[MESH_ID_UPPER_BODY]); + mRoot->addChild(mMeshLOD[MESH_ID_LOWER_BODY]); + mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]); + mRoot->addChild(mMeshLOD[MESH_ID_HEAD]); + + LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull"); + if (skull) + { + skull->addChild(mMeshLOD[MESH_ID_HAIR] ); + } + + LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft"); + if (eyeL) + { + eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); + } + + LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight"); + if (eyeR) + { + eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); + } + + // SKELETAL DISTORTIONS + { + LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; + LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); + if (!param->setInfo(info)) + { + delete param; + return FALSE; + } + else + { + addVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + } + } + + + return TRUE; +} + +//----------------------------------------------------------------------------- +// loadMeshNodes(): loads <mesh> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadMeshNodes() +{ + for (LLAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); + meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); + ++meshinfo_iter) + { + const LLAvatarXmlInfo::LLAvatarMeshInfo *info = *meshinfo_iter; + const std::string &type = info->mType; + S32 lod = info->mLOD; + + LLAvatarJointMesh* mesh = NULL; + U8 mesh_id = 0; + BOOL found_mesh_id = FALSE; + + /* if (type == "hairMesh") + switch(lod) + case 0: + mesh = &mHairMesh0; */ + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + ++mesh_iter) + { + const EMeshIndex mesh_index = mesh_iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second; + if (type.compare(mesh_dict->mName) == 0) + { + mesh_id = mesh_index; + found_mesh_id = TRUE; + break; + } + } + + if (found_mesh_id) + { + if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) + { + mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; + } + else + { + llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; + return FALSE; + } + } + else + { + llwarns << "Ignoring unrecognized mesh type: " << type << llendl; + return FALSE; + } + + // llinfos << "Parsing mesh data for " << type << "..." << llendl; + + // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. + // Do not touch!!! + mesh->setColor( LLColor4::white ); + + LLPolyMesh *poly_mesh = NULL; + + if (!info->mReferenceMeshName.empty()) + { + polymesh_map_t::const_iterator polymesh_iter = mPolyMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mPolyMeshes.end()) + { + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); + poly_mesh->setAvatar(this); + } + else + { + // This should never happen + LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; + } + } + else + { + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); + poly_mesh->setAvatar(this); + } + + if( !poly_mesh ) + { + llwarns << "Failed to load mesh of type " << type << llendl; + return FALSE; + } + + // Multimap insert + mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); + + mesh->setMesh( poly_mesh ); + mesh->setLOD( info->mMinPixelArea ); + + for (LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); + xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); + ++xmlinfo_iter) + { + const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); + LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); + if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair->first)) + { + delete param; + return FALSE; + } + else + { + if (info_pair->second) + { + addSharedVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + else + { + addVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + } + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// loadLayerSets() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadLayersets() +{ + BOOL success = TRUE; + for (LLAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin(); + layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); + ++layerset_iter) + { + LLTexLayerSetInfo *layerset_info = *layerset_iter; + if (isSelf()) + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSet* layer_set = createTexLayerSet(); + + if (!layer_set->setInfo(layerset_info)) + { + stop_glerror(); + delete layer_set; + llwarns << "avatar file: layer_set->setInfo() failed" << llendl; + return FALSE; + } + + // scan baked textures and associate the layerset with the appropriate one + EBakedTextureIndex baked_index = BAKED_NUM_INDICES; + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + baked_index = baked_iter->first; + // ensure both structures are aware of each other + mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; + layer_set->setBakedTexIndex(baked_index); + break; + } + } + // if no baked texture was found, warn and cleanup + if (baked_index == BAKED_NUM_INDICES) + { + llwarns << "<layer_set> has invalid body_region attribute" << llendl; + delete layer_set; + return FALSE; + } + + // scan morph masks and let any affected layers know they have an associated morph + for (LLAvatarAppearance::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); + morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); + ++morph_iter) + { + LLMaskedMorph *morph = *morph_iter; + LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); + if (layer) + { + layer->setHasMorph(TRUE); + } + else + { + llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl; + success = FALSE; + } + } + } + else // !isSelf() + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSetInfo *layerset_info = *layerset_iter; + layerset_info->createVisualParams(this); + } + } + return success; +} + +//----------------------------------------------------------------------------- +// getCharacterJoint() +//----------------------------------------------------------------------------- +LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num ) +{ + if ((S32)num >= mSkeleton.size() + || (S32)num < 0) + { + return NULL; + } + return mSkeleton[num]; +} + + +//----------------------------------------------------------------------------- +// getVolumePos() +//----------------------------------------------------------------------------- +LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_offset) +{ + if (joint_index > mNumCollisionVolumes) + { + return LLVector3::zero; + } + + return mCollisionVolumes[joint_index].getVolumePos(volume_offset); +} + +//----------------------------------------------------------------------------- +// findCollisionVolume() +//----------------------------------------------------------------------------- +LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id) +{ + if ((S32)volume_id > mNumCollisionVolumes) + { + return NULL; + } + + return &mCollisionVolumes[volume_id]; +} + +//----------------------------------------------------------------------------- +// findCollisionVolume() +//----------------------------------------------------------------------------- +S32 LLAvatarAppearance::getCollisionVolumeID(std::string &name) +{ + for (S32 i = 0; i < mNumCollisionVolumes; i++) + { + if (mCollisionVolumes[i].getName() == name) + { + return i; + } + } + + return -1; +} + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::getHeadMesh() +//----------------------------------------------------------------------------- +LLPolyMesh* LLAvatarAppearance::getHeadMesh() +{ + return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::getUpperBodyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh* LLAvatarAppearance::getUpperBodyMesh() +{ + return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); +} + + + +// virtual +BOOL LLAvatarAppearance::isValid() const +{ + // This should only be called on ourself. + if (!isSelf()) + { + llerrs << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << llendl; + } + return TRUE; +} + + +// adds a morph mask to the appropriate baked texture structure +void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer) +{ + if (index < BAKED_NUM_INDICES) + { + LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); + mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); + } +} + + +//static +BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) +{ + switch( te ) + { + case TEX_UPPER_SHIRT: + param_name[0] = 803; //"shirt_red"; + param_name[1] = 804; //"shirt_green"; + param_name[2] = 805; //"shirt_blue"; + break; + + case TEX_LOWER_PANTS: + param_name[0] = 806; //"pants_red"; + param_name[1] = 807; //"pants_green"; + param_name[2] = 808; //"pants_blue"; + break; + + case TEX_LOWER_SHOES: + param_name[0] = 812; //"shoes_red"; + param_name[1] = 813; //"shoes_green"; + param_name[2] = 817; //"shoes_blue"; + break; + + case TEX_LOWER_SOCKS: + param_name[0] = 818; //"socks_red"; + param_name[1] = 819; //"socks_green"; + param_name[2] = 820; //"socks_blue"; + break; + + case TEX_UPPER_JACKET: + case TEX_LOWER_JACKET: + param_name[0] = 834; //"jacket_red"; + param_name[1] = 835; //"jacket_green"; + param_name[2] = 836; //"jacket_blue"; + break; + + case TEX_UPPER_GLOVES: + param_name[0] = 827; //"gloves_red"; + param_name[1] = 829; //"gloves_green"; + param_name[2] = 830; //"gloves_blue"; + break; + + case TEX_UPPER_UNDERSHIRT: + param_name[0] = 821; //"undershirt_red"; + param_name[1] = 822; //"undershirt_green"; + param_name[2] = 823; //"undershirt_blue"; + break; + + case TEX_LOWER_UNDERPANTS: + param_name[0] = 824; //"underpants_red"; + param_name[1] = 825; //"underpants_green"; + param_name[2] = 826; //"underpants_blue"; + break; + + case TEX_SKIRT: + param_name[0] = 921; //"skirt_red"; + param_name[1] = 922; //"skirt_green"; + param_name[2] = 923; //"skirt_blue"; + break; + + case TEX_HEAD_TATTOO: + case TEX_LOWER_TATTOO: + case TEX_UPPER_TATTOO: + param_name[0] = 1071; //"tattoo_red"; + param_name[1] = 1072; //"tattoo_green"; + param_name[2] = 1073; //"tattoo_blue"; + break; + + default: + llassert(0); + return FALSE; + } + + return TRUE; +} + +void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) +{ + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake ); + setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake ); + setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake ); + } +} + +LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te ) +{ + LLColor4 color; + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + color.mV[VX] = getVisualParamWeight( param_name[0] ); + color.mV[VY] = getVisualParamWeight( param_name[1] ); + color.mV[VZ] = getVisualParamWeight( param_name[2] ); + } + return color; +} + +// static +LLColor4 LLAvatarAppearance::getDummyColor() +{ + return DUMMY_COLOR; +} + +LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) const +{ + if (color_name=="skin_color" && mTexSkinColor) + { + return mTexSkinColor->getColor(); + } + else if(color_name=="hair_color" && mTexHairColor) + { + return mTexHairColor->getColor(); + } + if(color_name=="eye_color" && mTexEyeColor) + { + return mTexEyeColor->getColor(); + } + else + { +// return LLColor4( .5f, .5f, .5f, .5f ); + return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color + } +} + +// Unlike most wearable functions, this works for both self and other. +// virtual +BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const +{ + return mWearableData->getWearableCount(type) > 0; +} + +LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + return mBakedTextureDatas[baked_index].mTexLayerSet; +} + +//----------------------------------------------------------------------------- +// allocateCollisionVolumes() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) +{ + deleteAndClearArray(mCollisionVolumes); + mNumCollisionVolumes = 0; + + mCollisionVolumes = new LLAvatarJointCollisionVolume[num]; + if (!mCollisionVolumes) + { + return FALSE; + } + + mNumCollisionVolumes = num; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarBoneInfo::parseXml() +//----------------------------------------------------------------------------- +BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +{ + if (node->hasName("bone")) + { + mIsJoint = TRUE; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + llwarns << "Bone without name" << llendl; + return FALSE; + } + } + else if (node->hasName("collision_volume")) + { + mIsJoint = FALSE; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + mName = "Collision Volume"; + } + } + else + { + llwarns << "Invalid node " << node->getName() << llendl; + return FALSE; + } + + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + if (!node->getFastAttributeVector3(pos_string, mPos)) + { + llwarns << "Bone without position" << llendl; + return FALSE; + } + + static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); + if (!node->getFastAttributeVector3(rot_string, mRot)) + { + llwarns << "Bone without rotation" << llendl; + return FALSE; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!node->getFastAttributeVector3(scale_string, mScale)) + { + llwarns << "Bone without scale" << llendl; + return FALSE; + } + + if (mIsJoint) + { + static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); + if (!node->getFastAttributeVector3(pivot_string, mPivot)) + { + llwarns << "Bone without pivot" << llendl; + return FALSE; + } + } + + // parse children + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo; + if (!child_info->parseXml(child)) + { + delete child_info; + return FALSE; + } + mChildList.push_back(child_info); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarSkeletonInfo::parseXml() +//----------------------------------------------------------------------------- +BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +{ + static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); + if (!node->getFastAttributeS32(num_bones_string, mNumBones)) + { + llwarns << "Couldn't find number of bones." << llendl; + return FALSE; + } + + static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); + node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); + + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *info = new LLAvatarBoneInfo; + if (!info->parseXml(child)) + { + delete info; + llwarns << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } + mBoneInfoList.push_back(info); + } + return TRUE; +} + + +//----------------------------------------------------------------------------- +// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +{ + LLXmlTreeNode* node = root->getChildByName( "skeleton" ); + if( !node ) + { + llwarns << "avatar file: missing <skeleton>" << llendl; + return FALSE; + } + + LLXmlTreeNode* child; + + // SKELETON DISTORTIONS + for (child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_skeleton")) + { + if (child->getChildByName("param_morph")) + { + llwarns << "Can't specify morph param in skeleton definition." << llendl; + } + else + { + llwarns << "Unknown param type." << llendl; + } + continue; + } + + LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + + mSkeletalDistortionInfoList.push_back(info); + } + + // ATTACHMENT POINTS + for (child = node->getChildByName( "attachment_point" ); + child; + child = node->getNextNamedChild()) + { + LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!child->getFastAttributeString(name_string, info->mName)) + { + llwarns << "No name supplied for attachment point." << llendl; + delete info; + continue; + } + + static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); + if (!child->getFastAttributeString(joint_string, info->mJointName)) + { + llwarns << "No bone declared in attachment point " << info->mName << llendl; + delete info; + continue; + } + + static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); + if (child->getFastAttributeVector3(position_string, info->mPosition)) + { + info->mHasPosition = TRUE; + } + + static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); + if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) + { + info->mHasRotation = TRUE; + } + static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); + if (child->getFastAttributeS32(group_string, info->mGroup)) + { + if (info->mGroup == -1) + info->mGroup = -1111; // -1 = none parsed, < -1 = bad value + } + + static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); + if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) + { + llwarns << "No id supplied for attachment point " << info->mName << llendl; + delete info; + continue; + } + + static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); + child->getFastAttributeS32(slot_string, info->mPieMenuSlice); + + static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); + child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); + + static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); + child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); + + mAttachmentInfoList.push_back(info); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlMeshNodes(): parses <mesh> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); + node; + node = root->getNextNamedChild()) + { + LLAvatarMeshInfo *info = new LLAvatarMeshInfo; + + // attribute: type + static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); + if( !node->getFastAttributeString( type_string, info->mType ) ) + { + llwarns << "Avatar file: <mesh> is missing type attribute. Ignoring element. " << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); + if (!node->getFastAttributeS32( lod_string, info->mLOD )) + { + llwarns << "Avatar file: <mesh> is missing lod attribute. Ignoring element. " << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) + { + llwarns << "Avatar file: <mesh> is missing file_name attribute. Ignoring: " << info->mType << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); + node->getFastAttributeString( reference_string, info->mReferenceMeshName ); + + // attribute: min_pixel_area + static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); + static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); + if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) + { + F32 min_pixel_area = 0.1f; + if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) + { + // this is square root of pixel area (sensible to use linear space in defining lods) + min_pixel_area = min_pixel_area * min_pixel_area; + } + info->mMinPixelArea = min_pixel_area; + } + + // Parse visual params for this node only if we haven't already + for (LLXmlTreeNode* child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_morph")) + { + if (child->getChildByName("param_skeleton")) + { + llwarns << "Can't specify skeleton param in a mesh definition." << llendl; + } + else + { + llwarns << "Unknown param type." << llendl; + } + continue; + } + + LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); + if (!morphinfo->parseXml(child)) + { + delete morphinfo; + delete info; + return -1; + } + BOOL shared = FALSE; + static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); + child->getFastAttributeBOOL(shared_string, shared); + + info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); + } + + mMeshInfoList.push_back(info); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlColorNodes(): parses <global_color> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); + color_node; + color_node = root->getNextNamedChild()) + { + std::string global_color_name; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (color_node->getFastAttributeString( name_string, global_color_name ) ) + { + if( global_color_name == "skin_color" ) + { + if (mTexSkinColorInfo) + { + llwarns << "avatar file: multiple instances of skin_color" << llendl; + return FALSE; + } + mTexSkinColorInfo = new LLTexGlobalColorInfo; + if( !mTexSkinColorInfo->parseXml( color_node ) ) + { + deleteAndClear(mTexSkinColorInfo); + llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl; + return FALSE; + } + } + else if( global_color_name == "hair_color" ) + { + if (mTexHairColorInfo) + { + llwarns << "avatar file: multiple instances of hair_color" << llendl; + return FALSE; + } + mTexHairColorInfo = new LLTexGlobalColorInfo; + if( !mTexHairColorInfo->parseXml( color_node ) ) + { + deleteAndClear(mTexHairColorInfo); + llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl; + return FALSE; + } + } + else if( global_color_name == "eye_color" ) + { + if (mTexEyeColorInfo) + { + llwarns << "avatar file: multiple instances of eye_color" << llendl; + return FALSE; + } + mTexEyeColorInfo = new LLTexGlobalColorInfo; + if( !mTexEyeColorInfo->parseXml( color_node ) ) + { + llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl; + return FALSE; + } + } + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlLayerNodes(): parses <layer_set> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); + layer_node; + layer_node = root->getNextNamedChild()) + { + LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); + if( layer_info->parseXml( layer_node ) ) + { + mLayerInfoList.push_back(layer_info); + } + else + { + delete layer_info; + llwarns << "avatar file: layer_set->parseXml() failed" << llendl; + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); + if( driver ) + { + for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); + grand_child; + grand_child = driver->getNextNamedChild()) + { + if( grand_child->getChildByName( "param_driver" ) ) + { + LLDriverParamInfo* driver_info = new LLDriverParamInfo(); + if( driver_info->parseXml( grand_child ) ) + { + mDriverInfoList.push_back(driver_info); + } + else + { + delete driver_info; + llwarns << "avatar file: driver_param->parseXml() failed" << llendl; + return FALSE; + } + } + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); + if( !masks ) + { + return FALSE; + } + + for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); + grand_child; + grand_child = masks->getNextNamedChild()) + { + LLAvatarMorphInfo* info = new LLAvatarMorphInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); + if (!grand_child->getFastAttributeString(name_string, info->mName)) + { + llwarns << "No name supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); + if (!grand_child->getFastAttributeString(region_string, info->mRegion)) + { + llwarns << "No region supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); + if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) + { + llwarns << "No layer supplied for morph mask." << llendl; + delete info; + continue; + } + + // optional parameter. don't throw a warning if not present. + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + grand_child->getFastAttributeBOOL(invert_string, info->mInvert); + + mMorphMaskInfoList.push_back(info); + } + + return TRUE; +} + +//virtual +LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer) : + mMorphTarget(morph_target), + mInvert(invert), + mLayer(layer) +{ + LLPolyMorphTarget *target = dynamic_cast<LLPolyMorphTarget*>(morph_target); + if (target) + { + target->addPendingMorphMask(); + } +} + + + diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h new file mode 100644 index 0000000000..bce2540258 --- /dev/null +++ b/indra/llappearance/llavatarappearance.h @@ -0,0 +1,448 @@ +/** + * @file llavatarappearance.h + * @brief Declaration of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_AVATAR_APPEARANCE_H +#define LL_AVATAR_APPEARANCE_H + +#include "llcharacter.h" +#include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" +#include "lldriverparam.h" +#include "lltexlayer.h" +#include "llviewervisualparam.h" +#include "llxmltree.h" + +class LLTexLayerSet; +class LLTexGlobalColor; +class LLTexGlobalColorInfo; +class LLWearableData; +class LLAvatarBoneInfo; +class LLAvatarSkeletonInfo; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLAvatarAppearance +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLAvatarAppearance : public LLCharacter +{ + LOG_CLASS(LLAvatarAppearance); + +protected: + struct LLAvatarXmlInfo; + +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ +private: + // Hide default constructor. + LLAvatarAppearance() {} + +public: + LLAvatarAppearance(LLWearableData* wearable_data); + virtual ~LLAvatarAppearance(); + + static void initClass(); // initializes static members + static void cleanupClass(); // Cleanup data that's only init'd once per class. + virtual void initInstance(); // Called after construction to initialize the instance. + virtual BOOL loadSkeletonNode(); + BOOL loadMeshNodes(); + BOOL loadLayersets(); + + +/** Initialization + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** INHERITED + **/ + + //-------------------------------------------------------------------- + // LLCharacter interface and related + //-------------------------------------------------------------------- +public: + /*virtual*/ LLJoint* getCharacterJoint(U32 num); + + /*virtual*/ const char* getAnimationPrefix() { return "avatar"; } + /*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); + /*virtual*/ LLJoint* findCollisionVolume(U32 volume_id); + /*virtual*/ S32 getCollisionVolumeID(std::string &name); + /*virtual*/ LLPolyMesh* getHeadMesh(); + /*virtual*/ LLPolyMesh* getUpperBodyMesh(); + +/** Inherited + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** STATE + **/ +public: + virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + virtual BOOL isValid() const; + virtual BOOL isUsingServerBakes() const = 0; + virtual BOOL isUsingLocalAppearance() const = 0; + virtual BOOL isEditingAppearance() const = 0; + + bool isBuilt() const { return mIsBuilt; } + + +/** State + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SKELETON + **/ + +protected: + virtual LLAvatarJoint* createAvatarJoint() = 0; + virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0; + virtual LLAvatarJointMesh* createAvatarJointMesh() = 0; +public: + F32 getPelvisToFoot() const { return mPelvisToFoot; } + /*virtual*/ LLJoint* getRootJoint() { return mRoot; } + + LLVector3 mHeadOffset; // current head position + LLAvatarJoint *mRoot; + + typedef std::map<std::string, LLJoint*> joint_map_t; + joint_map_t mJointMap; + + void computeBodySize(); + + +protected: + static BOOL parseSkeletonFile(const std::string& filename); + virtual void buildCharacter(); + virtual BOOL loadAvatar(); + virtual void bodySizeChanged() = 0; + + BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL allocateCharacterJoints(U32 num); + BOOL buildSkeleton(const LLAvatarSkeletonInfo *info); +protected: + void clearSkeleton(); + BOOL mIsBuilt; // state of deferred character building + typedef std::vector<LLAvatarJoint*> avatar_joint_list_t; + avatar_joint_list_t mSkeleton; + + //-------------------------------------------------------------------- + // Pelvis height adjustment members. + //-------------------------------------------------------------------- +public: + LLVector3 mBodySize; + LLVector3 mAvatarOffset; +protected: + F32 mPelvisToFoot; + + //-------------------------------------------------------------------- + // Cached pointers to well known joints + //-------------------------------------------------------------------- +public: + LLJoint* mPelvisp; + LLJoint* mTorsop; + LLJoint* mChestp; + LLJoint* mNeckp; + LLJoint* mHeadp; + LLJoint* mSkullp; + LLJoint* mEyeLeftp; + LLJoint* mEyeRightp; + LLJoint* mHipLeftp; + LLJoint* mHipRightp; + LLJoint* mKneeLeftp; + LLJoint* mKneeRightp; + LLJoint* mAnkleLeftp; + LLJoint* mAnkleRightp; + LLJoint* mFootLeftp; + LLJoint* mFootRightp; + LLJoint* mWristLeftp; + LLJoint* mWristRightp; + + //-------------------------------------------------------------------- + // XML parse tree + //-------------------------------------------------------------------- +protected: + static LLXmlTree sXMLTree; // avatar config file + static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + + static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLAvatarXmlInfo* sAvatarXmlInfo; + + +/** Skeleton + ** ** + *******************************************************************************/ + + +/******************************************************************************** + ** ** + ** RENDERING + **/ +public: + BOOL mIsDummy; // for special views + + //-------------------------------------------------------------------- + // Morph masks + //-------------------------------------------------------------------- +public: + void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer); + virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; + +/** Rendering + ** ** + *******************************************************************************/ + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0; + +/******************************************************************************** + ** ** + ** MESHES + **/ + +public: + virtual void updateMeshTextures() = 0; + virtual void dirtyMesh() = 0; // Dirty the avatar mesh +protected: + virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority + +protected: + typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t; + polymesh_map_t mPolyMeshes; + avatar_joint_list_t mMeshLOD; + +/** Meshes + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** APPEARANCE + **/ + + //-------------------------------------------------------------------- + // Clothing colors (convenience functions to access visual parameters) + //-------------------------------------------------------------------- +public: + void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); + LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); + static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + LLColor4 getGlobalColor(const std::string& color_name ) const; + virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0; +protected: + LLTexGlobalColor* mTexSkinColor; + LLTexGlobalColor* mTexHairColor; + LLTexGlobalColor* mTexEyeColor; + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + static LLColor4 getDummyColor(); +/** Appearance + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** WEARABLES + **/ + +public: + LLWearableData* getWearableData() { return mWearableData; } + const LLWearableData* getWearableData() const { return mWearableData; } + virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; + +private: + LLWearableData* mWearableData; + +/******************************************************************************** + ** ** + ** BAKED TEXTURES + **/ +public: + LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + +protected: + virtual LLTexLayerSet* createTexLayerSet() = 0; + +protected: + class LLMaskedMorph; + typedef std::deque<LLMaskedMorph *> morph_list_t; + struct BakedTextureData + { + LLUUID mLastTextureID; + LLTexLayerSet* mTexLayerSet; // Only exists for self + bool mIsLoaded; + bool mIsUsed; + LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; + U32 mMaskTexName; + // Stores pointers to the joint meshes that this baked texture deals with + avatar_joint_mesh_list_t mJointMeshes; + morph_list_t mMaskedMorphs; + }; + typedef std::vector<BakedTextureData> bakedtexturedata_vec_t; + bakedtexturedata_vec_t mBakedTextureDatas; + +/******************************************************************************** + ** ** + ** PHYSICS + **/ + + //-------------------------------------------------------------------- + // Collision volumes + //-------------------------------------------------------------------- +public: + S32 mNumCollisionVolumes; + LLAvatarJointCollisionVolume* mCollisionVolumes; +protected: + BOOL allocateCollisionVolumes(U32 num); + +/** Physics + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SUPPORT CLASSES + **/ + + struct LLAvatarXmlInfo + { + LLAvatarXmlInfo(); + ~LLAvatarXmlInfo(); + + BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); + BOOL parseXmlMeshNodes(LLXmlTreeNode* root); + BOOL parseXmlColorNodes(LLXmlTreeNode* root); + BOOL parseXmlLayerNodes(LLXmlTreeNode* root); + BOOL parseXmlDriverNodes(LLXmlTreeNode* root); + BOOL parseXmlMorphNodes(LLXmlTreeNode* root); + + struct LLAvatarMeshInfo + { + typedef std::pair<LLViewerVisualParamInfo*,BOOL> morph_info_pair_t; // LLPolyMorphTargetInfo stored here + typedef std::vector<morph_info_pair_t> morph_info_list_t; + + LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} + ~LLAvatarMeshInfo() + { + morph_info_list_t::iterator iter; + for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) + { + delete iter->first; + } + mPolyMorphTargetInfoList.clear(); + } + + std::string mType; + S32 mLOD; + std::string mMeshFileName; + std::string mReferenceMeshName; + F32 mMinPixelArea; + morph_info_list_t mPolyMorphTargetInfoList; + }; + typedef std::vector<LLAvatarMeshInfo*> mesh_info_list_t; + mesh_info_list_t mMeshInfoList; + + typedef std::vector<LLViewerVisualParamInfo*> skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here + skeletal_distortion_info_list_t mSkeletalDistortionInfoList; + + struct LLAvatarAttachmentInfo + { + LLAvatarAttachmentInfo() + : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), + mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} + std::string mName; + std::string mJointName; + LLVector3 mPosition; + LLVector3 mRotationEuler; + S32 mGroup; + S32 mAttachmentID; + S32 mPieMenuSlice; + BOOL mVisibleFirstPerson; + BOOL mIsHUDAttachment; + BOOL mHasPosition; + BOOL mHasRotation; + }; + typedef std::vector<LLAvatarAttachmentInfo*> attachment_info_list_t; + attachment_info_list_t mAttachmentInfoList; + + LLTexGlobalColorInfo *mTexSkinColorInfo; + LLTexGlobalColorInfo *mTexHairColorInfo; + LLTexGlobalColorInfo *mTexEyeColorInfo; + + typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t; + layer_info_list_t mLayerInfoList; + + typedef std::vector<LLDriverParamInfo*> driver_info_list_t; + driver_info_list_t mDriverInfoList; + + struct LLAvatarMorphInfo + { + LLAvatarMorphInfo() + : mInvert(FALSE) {} + std::string mName; + std::string mRegion; + std::string mLayer; + BOOL mInvert; + }; + + typedef std::vector<LLAvatarMorphInfo*> morph_info_list_t; + morph_info_list_t mMorphMaskInfoList; + }; + + + class LLMaskedMorph + { + public: + LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer); + + LLVisualParam *mMorphTarget; + BOOL mInvert; + std::string mLayer; + }; +/** Support Classes + ** ** + *******************************************************************************/ +}; + +#endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/newview/llvoavatardefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 1ed4e3b61c..f1c78946a1 100755..100644 --- a/indra/newview/llvoavatardefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -1,6 +1,6 @@ /** - * @file llvoavatar.cpp - * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject + * @file llavatarappearancedefines.cpp + * @brief Implementation of LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,21 +24,20 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" -#include "llvoavatardefines.h" -#include "llviewercontrol.h" // gSavedSettings +#include "linden_common.h" +#include "llavatarappearancedefines.h" -const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; -const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; -const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 512; +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 512; +const S32 LLAvatarAppearanceDefines::IMPOSTOR_PERIOD = 2; -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; /********************************************************************************* * Edit this function to add/remove/change textures and mesh definitions for avatars. */ -LLVOAvatarDictionary::Textures::Textures() +LLAvatarAppearanceDictionary::Textures::Textures() { addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); @@ -66,15 +65,15 @@ LLVOAvatarDictionary::Textures::Textures() addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD)); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER)); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER)); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES)); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR)); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT)); + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); } -LLVOAvatarDictionary::BakedTextures::BakedTextures() +LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() { // Baked textures addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, @@ -110,36 +109,36 @@ LLVOAvatarDictionary::BakedTextures::BakedTextures() 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); } -LLVOAvatarDictionary::Meshes::Meshes() +LLAvatarAppearanceDictionary::MeshEntries::MeshEntries() { - // Meshes - addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4)); - addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5)); - addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0)); // no baked mesh associated currently - addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1)); - addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2)); - addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3)); - addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3)); - addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5)); + // MeshEntries + addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); + addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); + addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently + addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); + addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); + addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); + addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); + addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); } /* * *********************************************************************************/ -LLVOAvatarDictionary::LLVOAvatarDictionary() +LLAvatarAppearanceDictionary::LLAvatarAppearanceDictionary() { createAssociations(); } //virtual -LLVOAvatarDictionary::~LLVOAvatarDictionary() +LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary() { } // Baked textures are composites of textures; for each such composited texture, // map it to the baked texture. -void LLVOAvatarDictionary::createAssociations() +void LLAvatarAppearanceDictionary::createAssociations() { for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) { @@ -160,7 +159,7 @@ void LLVOAvatarDictionary::createAssociations() } -LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name, +LLAvatarAppearanceDictionary::TextureEntry::TextureEntry(const std::string &name, bool is_local_texture, EBakedTextureIndex baked_texture_index, const std::string &default_image_name, @@ -175,17 +174,17 @@ LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name, { } -LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, +LLAvatarAppearanceDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, const std::string &name, U8 level, - LLViewerJoint::PickName pick) : + LLJointPickName pick) : LLDictionaryEntry(name), mBakedID(baked_index), mLOD(level), mPickName(pick) { } -LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, +LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, const std::string &name, const std::string &hash_name, U32 num_local_textures, @@ -216,18 +215,18 @@ LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, } // static -ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) +ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) { - return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; + return LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; } -//static -EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) +// static +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) { U8 index = 0; while (index < BAKED_NUM_INDICES) { - const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); if (be && be->mName.compare(name) == 0) { // baked texture found @@ -239,23 +238,30 @@ EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) return BAKED_NUM_INDICES; } -//static -const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index) +// static +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) { - const TextureEntry *texture_dict = getInstance()->getTexture(index); - const std::string &default_image_name = texture_dict->mDefaultImageName; - if (default_image_name == "") - { - return IMG_DEFAULT_AVATAR; - } - else + U8 index = 0; + while (index < BAKED_NUM_INDICES) { - return LLUUID(gSavedSettings.getString(default_image_name)); + const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + if (be) + { + const TextureEntry *te = LLAvatarAppearanceDictionary::getInstance()->getTexture(be->mTextureIndex); + if (te && te->mDefaultImageName.compare(name) == 0) + { + // baked texture found + return (EBakedTextureIndex) index; + } + } + index++; } + // baked texture could not be found + return BAKED_NUM_INDICES; } // static -LLWearableType::EType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index ) +LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) { return getInstance()->getTexture(index)->mWearableType; } diff --git a/indra/newview/llvoavatardefines.h b/indra/llappearance/llavatarappearancedefines.h index 35bb37463a..8a1d2c4707 100755..100644 --- a/indra/newview/llvoavatardefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -1,6 +1,6 @@ /** - * @file llvoavatar.h - * @brief Declaration of LLVOAvatar class which is a derivation fo + * @file llavatarappearancedefines.h + * @brief Various LLAvatarAppearance related definitions * LLViewerObject * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ @@ -25,26 +25,30 @@ * $/LicenseInfo$ */ -#ifndef LLVOAVATAR_DEFINES_H -#define LLVOAVATAR_DEFINES_H +#ifndef LL_AVATARAPPEARANCE_DEFINES_H +#define LL_AVATARAPPEARANCE_DEFINES_H #include <vector> -#include "llwearable.h" -#include "llviewerjoint.h" +#include "lljointpickname.h" #include "lldictionary.h" +#include "llwearabletype.h" +#include "lluuid.h" -namespace LLVOAvatarDefines +namespace LLAvatarAppearanceDefines { extern const S32 SCRATCH_TEX_WIDTH; extern const S32 SCRATCH_TEX_HEIGHT; extern const S32 IMPOSTOR_PERIOD; +static const U32 AVATAR_HOVER = 11001; + //-------------------------------------------------------------------- // Enums //-------------------------------------------------------------------- enum ETextureIndex { + TEX_INVALID = -1, TEX_HEAD_BODYPAINT = 0, TEX_UPPER_SHIRT, TEX_LOWER_PANTS, @@ -111,21 +115,21 @@ typedef std::vector<EMeshIndex> mesh_vec_t; typedef std::vector<LLWearableType::EType> wearables_vec_t; //------------------------------------------------------------------------ -// LLVOAvatarDictionary +// LLAvatarAppearanceDictionary // // Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. // information that is common to all avatars. // // This holds const data - it is initialized once and the contents never change after that. //------------------------------------------------------------------------ -class LLVOAvatarDictionary : public LLSingleton<LLVOAvatarDictionary> +class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictionary> { //-------------------------------------------------------------------- // Constructors and Destructors //-------------------------------------------------------------------- public: - LLVOAvatarDictionary(); - virtual ~LLVOAvatarDictionary(); + LLAvatarAppearanceDictionary(); + virtual ~LLAvatarAppearanceDictionary(); private: void createAssociations(); @@ -166,20 +170,20 @@ public: MeshEntry(EBakedTextureIndex baked_index, const std::string &name, // names of mesh types as they are used in avatar_lad.xml U8 level, - LLViewerJoint::PickName pick); + LLJointPickName pick); // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml // Otherwise meshes will be unable to be found, or levels of detail will be ignored const U8 mLOD; const EBakedTextureIndex mBakedID; - const LLViewerJoint::PickName mPickName; + const LLJointPickName mPickName; }; - struct Meshes : public LLDictionary<EMeshIndex, MeshEntry> + struct MeshEntries : public LLDictionary<EMeshIndex, MeshEntry> { - Meshes(); - } mMeshes; - const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } - const Meshes& getMeshes() const { return mMeshes; } + MeshEntries(); + } mMeshEntries; + const MeshEntry* getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); } + const MeshEntries& getMeshEntries() const { return mMeshEntries; } //-------------------------------------------------------------------- // Baked Textures @@ -215,14 +219,13 @@ public: // find a baked texture index based on its name static EBakedTextureIndex findBakedByRegionName(std::string name); - - static const LLUUID getDefaultTextureImageID(ETextureIndex index); + static EBakedTextureIndex findBakedByImageName(std::string name); // Given a texture entry, determine which wearable type owns it. static LLWearableType::EType getTEWearableType(ETextureIndex index); -}; // End LLVOAvatarDictionary +}; // End LLAvatarAppearanceDictionary -} // End namespace LLVOAvatarDefines +} // End namespace LLAvatarAppearanceDefines -#endif //LL_VO_AVATARDEFINES_H +#endif //LL_AVATARAPPEARANCE_DEFINES_H diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp new file mode 100644 index 0000000000..6ab341af64 --- /dev/null +++ b/indra/llappearance/llavatarjoint.cpp @@ -0,0 +1,326 @@ +/** + * @file llavatarjoint.cpp + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llavatarjoint.h" + +#include "llgl.h" +#include "llrender.h" +#include "llmath.h" +#include "llglheaders.h" +#include "llavatarappearance.h" + +const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f; + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +BOOL LLAvatarJoint::sDisableLOD = FALSE; + +//----------------------------------------------------------------------------- +// LLAvatarJoint() +// Class Constructors +//----------------------------------------------------------------------------- +LLAvatarJoint::LLAvatarJoint() : + LLJoint() +{ + init(); +} + +LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) : + LLJoint(name, parent) +{ + init(); +} + +LLAvatarJoint::LLAvatarJoint(S32 joint_num) : + LLJoint(joint_num) +{ + init(); +} + + +void LLAvatarJoint::init() +{ + mValid = FALSE; + mComponents = SC_JOINT | SC_BONE | SC_AXES; + mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD; + mPickName = PN_DEFAULT; + mVisible = TRUE; + mMeshID = 0; + mIsTransparent = FALSE; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJoint() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJoint::~LLAvatarJoint() +{ +} + + +//-------------------------------------------------------------------- +// setValid() +//-------------------------------------------------------------------- +void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) +{ + //---------------------------------------------------------------- + // set visibility for this joint + //---------------------------------------------------------------- + mValid = valid; + + //---------------------------------------------------------------- + // set visibility for children + //---------------------------------------------------------------- + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + joint->setValid(valid, TRUE); + } + } + +} + +//-------------------------------------------------------------------- +// setSkeletonComponents() +//-------------------------------------------------------------------- +void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive ) +{ + mComponents = comp; + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + joint->setSkeletonComponents(comp, recursive); + } + } +} + +void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive) +{ + mVisible = visible; + + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + joint->setVisible(visible, recursive); + } + } +} + +void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + joint->updateFaceSizes(num_vertices, num_indices, pixel_area); + } +} + +void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + joint->updateFaceData(face, pixel_area, damp_wind, terse_update); + } +} + +void LLAvatarJoint::updateJointGeometry() +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + joint->updateJointGeometry(); + } +} + + +BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate) +{ + BOOL lod_changed = FALSE; + BOOL found_lod = FALSE; + + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + F32 jointLOD = joint->getLOD(); + + if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) + { + // we've already found a joint to enable, so enable the rest as alternatives + lod_changed |= joint->updateLOD(pixel_area, TRUE); + } + else + { + if (pixel_area >= jointLOD || sDisableLOD) + { + lod_changed |= joint->updateLOD(pixel_area, TRUE); + found_lod = TRUE; + } + else + { + lod_changed |= joint->updateLOD(pixel_area, FALSE); + } + } + } + return lod_changed; +} + +void LLAvatarJoint::dump() +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); + joint->dump(); + } +} + + +void LLAvatarJoint::setMeshesToChildren() +{ + removeAllChildren(); + for (avatar_joint_mesh_list_t::iterator iter = mMeshParts.begin(); + iter != mMeshParts.end(); iter++) + { + addChild((*iter)); + } +} +//----------------------------------------------------------------------------- +// LLAvatarJointCollisionVolume() +//----------------------------------------------------------------------------- + +LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() +{ + mUpdateXform = FALSE; +} + +/*virtual*/ +U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) +{ + llerrs << "Cannot call render() on LLAvatarJointCollisionVolume" << llendl; + return 0; +} + +LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) +{ + mUpdateXform = TRUE; + + LLVector3 result = offset; + result.scaleVec(getScale()); + result.rotVec(getWorldRotation()); + result += getWorldPosition(); + + return result; +} + +void LLAvatarJointCollisionVolume::renderCollision() +{ + updateWorldMatrix(); + + gGL.pushMatrix(); + gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); + + gGL.diffuseColor3f( 0.f, 0.f, 1.f ); + + gGL.begin(LLRender::LINES); + + LLVector3 v[] = + { + LLVector3(1,0,0), + LLVector3(-1,0,0), + LLVector3(0,1,0), + LLVector3(0,-1,0), + + LLVector3(0,0,-1), + LLVector3(0,0,1), + }; + + //sides + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[3].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[3].mV); + + + //top + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[4].mV); + + + //bottom + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[5].mV); + + gGL.end(); + + gGL.popMatrix(); +} + + +// End diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h new file mode 100644 index 0000000000..fec91503c7 --- /dev/null +++ b/indra/llappearance/llavatarjoint.h @@ -0,0 +1,140 @@ +/** + * @file llavatarjoint.h + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINT_H +#define LL_LLAVATARJOINT_H + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "lljoint.h" +#include "lljointpickname.h" + +class LLFace; +class LLAvatarJointMesh; + +extern const F32 DEFAULT_AVATAR_JOINT_LOD; + +//----------------------------------------------------------------------------- +// class LLViewerJoint +//----------------------------------------------------------------------------- +class LLAvatarJoint : + public LLJoint +{ +public: + LLAvatarJoint(); + LLAvatarJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* + LLAvatarJoint(const std::string &name, LLJoint *parent = NULL); + virtual ~LLAvatarJoint(); + + // Gets the validity of this joint + BOOL getValid() { return mValid; } + + // Sets the validity of this joint + virtual void setValid( BOOL valid, BOOL recursive=FALSE ); + + // Returns true if this object is transparent. + // This is used to determine in which order to draw objects. + virtual BOOL isTransparent() { return mIsTransparent; } + + // Returns true if this object should inherit scale modifiers from its immediate parent + virtual BOOL inheritScale() { return FALSE; } + + enum Components + { + SC_BONE = 1, + SC_JOINT = 2, + SC_AXES = 4 + }; + + // Selects which skeleton components to draw + void setSkeletonComponents( U32 comp, BOOL recursive = TRUE ); + + // Returns which skeleton components are enables for drawing + U32 getSkeletonComponents() { return mComponents; } + + // Sets the level of detail for this node as a minimum + // pixel area threshold. If the current pixel area for this + // object is less than the specified threshold, the node is + // not traversed. In addition, if a value is specified (not + // default of 0.0), and the pixel area is larger than the + // specified minimum, the node is rendered, but no other siblings + // of this node under the same parent will be. + F32 getLOD() { return mMinPixelArea; } + void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } + + void setPickName(LLJointPickName name) { mPickName = name; } + LLJointPickName getPickName() { return mPickName; } + + void setVisible( BOOL visible, BOOL recursive ); + + // Takes meshes in mMeshParts and sets each one as a child joint + void setMeshesToChildren(); + + // LLViewerJoint interface + virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) = 0; + virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); + virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); + virtual BOOL updateLOD(F32 pixel_area, BOOL activate); + virtual void updateJointGeometry(); + virtual void dump(); + + +public: + static BOOL sDisableLOD; + avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh* + void setMeshID( S32 id ) {mMeshID = id;} + +protected: + void init(); + + BOOL mValid; + BOOL mIsTransparent; + U32 mComponents; + F32 mMinPixelArea; + LLJointPickName mPickName; + BOOL mVisible; + S32 mMeshID; +}; + +class LLAvatarJointCollisionVolume : public LLAvatarJoint +{ +public: + LLAvatarJointCollisionVolume(); + virtual ~LLAvatarJointCollisionVolume() {}; + + /*virtual*/ BOOL inheritScale() { return TRUE; } + /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); + + void renderCollision(); + + LLVector3 getVolumePos(LLVector3 &offset); +}; + +#endif // LL_LLAVATARJOINT_H + + diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp new file mode 100644 index 0000000000..4a5cff1dc3 --- /dev/null +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -0,0 +1,375 @@ +/** + * @file LLAvatarJointMesh.cpp + * @brief Implementation of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" +#include "imageids.h" +#include "llfasttimer.h" +#include "llrender.h" + +#include "llavatarjointmesh.h" +#include "llavatarappearance.h" +//#include "llapr.h" +//#include "llbox.h" +//#include "lldrawable.h" +//#include "lldrawpoolavatar.h" +//#include "lldrawpoolbump.h" +//#include "lldynamictexture.h" +//#include "llface.h" +//#include "llgldbg.h" +//#include "llglheaders.h" +#include "lltexlayer.h" +//#include "llviewercamera.h" +//#include "llviewercontrol.h" +//#include "llviewertexturelist.h" +//#include "llsky.h" +//#include "pipeline.h" +//#include "llviewershadermgr.h" +#include "llmath.h" +#include "v4math.h" +#include "m3math.h" +#include "m4math.h" +#include "llmatrix4a.h" + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::LLSkinJoint +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::LLSkinJoint() +{ + mJoint = NULL; +} + +//----------------------------------------------------------------------------- +// ~LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::~LLSkinJoint() +{ + mJoint = NULL; +} + + +//----------------------------------------------------------------------------- +// LLSkinJoint::setupSkinJoint() +//----------------------------------------------------------------------------- +BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) +{ + // find the named joint + mJoint = joint; + if ( !mJoint ) + { + llinfos << "Can't find joint" << llendl; + } + + // compute the inverse root skin matrix + mRootToJointSkinOffset.clearVec(); + + LLVector3 rootSkinOffset; + while (joint) + { + rootSkinOffset += joint->getSkinOffset(); + joint = (LLAvatarJoint*)joint->getParent(); + } + + mRootToJointSkinOffset = -rootSkinOffset; + mRootToParentJointSkinOffset = mRootToJointSkinOffset; + mRootToParentJointSkinOffset += mJoint->getSkinOffset(); + + return TRUE; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +BOOL LLAvatarJointMesh::sPipelineRender = FALSE; +EAvatarRenderPass LLAvatarJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; +U32 LLAvatarJointMesh::sClothingMaskImageName = 0; +LLColor4 LLAvatarJointMesh::sClothingInnerColor; + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh() +//----------------------------------------------------------------------------- +LLAvatarJointMesh::LLAvatarJointMesh() + : + mTexture( NULL ), + mLayerSet( NULL ), + mTestImageName( 0 ), + mFaceIndexCount(0) +{ + + mColor[0] = 1.0f; + mColor[1] = 1.0f; + mColor[2] = 1.0f; + mColor[3] = 1.0f; + mShiny = 0.0f; + mCullBackFaces = TRUE; + + mMesh = NULL; + + mNumSkinJoints = 0; + mSkinJoints = NULL; + + mFace = NULL; + + mMeshID = 0; + mUpdateXform = FALSE; + + mValid = FALSE; + + mIsTransparent = FALSE; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJointMesh() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJointMesh::~LLAvatarJointMesh() +{ + mMesh = NULL; + mTexture = NULL; + freeSkinData(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::allocateSkinData() +//----------------------------------------------------------------------------- +BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) +{ + mSkinJoints = new LLSkinJoint[ numSkinJoints ]; + mNumSkinJoints = numSkinJoints; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::freeSkinData() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::freeSkinData() +{ + mNumSkinJoints = 0; + delete [] mSkinJoints; + mSkinJoints = NULL; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) +{ + *red = mColor[0]; + *green = mColor[1]; + *blue = mColor[2]; + *alpha = mColor[3]; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) +{ + mColor[0] = red; + mColor[1] = green; + mColor[2] = blue; + mColor[3] = alpha; +} + +void LLAvatarJointMesh::setColor( const LLColor4& color ) +{ + mColor = color; +} + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getTexture() +//-------------------------------------------------------------------- +//LLViewerTexture *LLAvatarJointMesh::getTexture() +//{ +// return mTexture; +//} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setTexture() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) +{ + mTexture = texture; + + // texture and dynamic_texture are mutually exclusive + if( texture ) + { + mLayerSet = NULL; + //texture->bindTexture(0); + //texture->setClamp(TRUE, TRUE); + } +} + + +BOOL LLAvatarJointMesh::hasGLTexture() const +{ + return mTexture.notNull() && mTexture->hasGLTexture(); +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setLayerSet() +// Sets the shape texture (takes precedence over normal texture) +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) +{ + mLayerSet = layer_set; + + // texture and dynamic_texture are mutually exclusive + if( layer_set ) + { + mTexture = NULL; + } +} + +BOOL LLAvatarJointMesh::hasComposite() const +{ + return (mLayerSet && mLayerSet->hasComposite()); +} + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getMesh() +//-------------------------------------------------------------------- +LLPolyMesh *LLAvatarJointMesh::getMesh() +{ + return mMesh; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::setMesh() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) +{ + // set the mesh pointer + mMesh = mesh; + + // release any existing skin joints + freeSkinData(); + + if ( mMesh == NULL ) + { + return; + } + + // acquire the transform from the mesh object + setPosition( mMesh->getPosition() ); + setRotation( mMesh->getRotation() ); + setScale( mMesh->getScale() ); + + // create skin joints if necessary + if ( mMesh->hasWeights() && !mMesh->isLOD()) + { + U32 numJointNames = mMesh->getNumJointNames(); + + allocateSkinData( numJointNames ); + std::string *jointNames = mMesh->getJointNames(); + + U32 jn; + for (jn = 0; jn < numJointNames; jn++) + { + //llinfos << "Setting up joint " << jointNames[jn] << llendl; + LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) ); + mSkinJoints[jn].setupSkinJoint( joint ); + } + } + + // setup joint array + if (!mMesh->isLOD()) + { + setupJoint((LLAvatarJoint*)getRoot()); + } + +// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl; +} + +//----------------------------------------------------------------------------- +// setupJoint() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) +{ +// llinfos << "Mesh: " << getName() << llendl; + +// S32 joint_count = 0; + U32 sj; + for (sj=0; sj<mNumSkinJoints; sj++) + { + LLSkinJoint &js = mSkinJoints[sj]; + + if (js.mJoint != current_joint) + { + continue; + } + + // we've found a skinjoint for this joint.. + + // is the last joint in the array our parent? + if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) + { + // ...then just add ourselves + LLAvatarJoint* jointp = js.mJoint; + mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); +// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl; +// joint_count++; + } + // otherwise add our parent and ourselves + else + { + mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); +// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl; +// joint_count++; + mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); +// llinfos << "joint " << joint_count << current_joint->getName() << llendl; +// joint_count++; + } + } + + // depth-first traversal + for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); + iter != current_joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); + setupJoint(child_joint); + } +} + + +// End diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h new file mode 100644 index 0000000000..6486932cdf --- /dev/null +++ b/indra/llappearance/llavatarjointmesh.h @@ -0,0 +1,145 @@ +/** + * @file llavatarjointmesh.h + * @brief Declaration of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINTMESH_H +#define LL_LLAVATARJOINTMESH_H + +#include "llavatarjoint.h" +#include "llgltexture.h" +#include "llpolymesh.h" +#include "v4color.h" + +class LLDrawable; +class LLFace; +class LLCharacter; +class LLTexLayerSet; + +typedef enum e_avatar_render_pass +{ + AVATAR_RENDER_PASS_SINGLE, + AVATAR_RENDER_PASS_CLOTHING_INNER, + AVATAR_RENDER_PASS_CLOTHING_OUTER +} EAvatarRenderPass; + +class LLSkinJoint +{ +public: + LLSkinJoint(); + ~LLSkinJoint(); + BOOL setupSkinJoint( LLAvatarJoint *joint); + + LLAvatarJoint *mJoint; + LLVector3 mRootToJointSkinOffset; + LLVector3 mRootToParentJointSkinOffset; +}; + +//----------------------------------------------------------------------------- +// class LLViewerJointMesh +//----------------------------------------------------------------------------- +class LLAvatarJointMesh : public virtual LLAvatarJoint +{ +protected: + LLColor4 mColor; // color value +// LLColor4 mSpecular; // specular color (always white for now) + F32 mShiny; // shiny value + LLPointer<LLGLTexture> mTexture; // ptr to a global texture + LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar + U32 mTestImageName; // handle to a temporary texture for previewing uploads + LLPolyMesh* mMesh; // ptr to a global polymesh + BOOL mCullBackFaces; // true by default + LLFace* mFace; // ptr to a face w/ AGP copy of mesh + + U32 mFaceIndexCount; + + U32 mNumSkinJoints; + LLSkinJoint* mSkinJoints; + S32 mMeshID; + +public: + static BOOL sPipelineRender; + //RN: this is here for testing purposes + static U32 sClothingMaskImageName; + static EAvatarRenderPass sRenderPass; + static LLColor4 sClothingInnerColor; + +public: + // Constructor + LLAvatarJointMesh(); + + // Destructor + virtual ~LLAvatarJointMesh(); + + // Gets the shape color + void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); + + // Sets the shape color + void setColor( F32 red, F32 green, F32 blue, F32 alpha ); + void setColor( const LLColor4& color ); + + // Sets the shininess + void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; + + // Sets the shape texture + void setTexture( LLGLTexture *texture ); + + BOOL hasGLTexture() const; + + void setTestTexture( U32 name ) { mTestImageName = name; } + + // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) + void setLayerSet( LLTexLayerSet* layer_set ); + + BOOL hasComposite() const; + + // Gets the poly mesh + LLPolyMesh *getMesh(); + + // Sets the poly mesh + void setMesh( LLPolyMesh *mesh ); + + // Sets up joint matrix data for rendering + void setupJoint(LLAvatarJoint* current_joint); + + // Render time method to upload batches of joint matrices + void uploadJointMatrices(); + + // Sets ID for picking + void setMeshID( S32 id ) {mMeshID = id;} + + // Gets ID for picking + S32 getMeshID() { return mMeshID; } + + void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } + +private: + // Allocate skin data + BOOL allocateSkinData( U32 numSkinJoints ); + + // Free skin data + void freeSkinData(); +}; + +#endif // LL_LLAVATARJOINTMESH_H diff --git a/indra/newview/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index 885cae1737..1f7e8b8652 100755..100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -24,22 +24,20 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "lldriverparam.h" -#include "llfasttimer.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "llagent.h" +#include "llavatarappearance.h" #include "llwearable.h" -#include "llagentwearables.h" +#include "llwearabledata.h" //----------------------------------------------------------------------------- // LLDriverParamInfo //----------------------------------------------------------------------------- -LLDriverParamInfo::LLDriverParamInfo() +LLDriverParamInfo::LLDriverParamInfo() : + mDriverParam(NULL) { } @@ -112,12 +110,14 @@ void LLDriverParamInfo::toStream(std::ostream &out) out << std::endl; - if(isAgentAvatarValid()) + if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() && + mDriverParam->getAvatarAppearance()->isValid()) { for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) { LLDrivenEntryInfo driven = *iter; - LLViewerVisualParam *param = (LLViewerVisualParam*)gAgentAvatarp->getVisualParam(driven.mDrivenID); + LLViewerVisualParam *param = + (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID); if (param) { param->getInfo()->toStream(out); @@ -139,7 +139,9 @@ void LLDriverParamInfo::toStream(std::ostream &out) } else { - llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl; + llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " + << mDriverParam->getAvatarAppearance() + << " for driver parameter " << getID() << llendl; } out << std::endl; } @@ -150,19 +152,16 @@ void LLDriverParamInfo::toStream(std::ostream &out) // LLDriverParam //----------------------------------------------------------------------------- -LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : +LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) : mCurrentDistortionParam( NULL ), - mAvatarp(avatarp), - mWearablep(NULL) -{ - mDefaultVec.clear(); -} - -LLDriverParam::LLDriverParam(LLWearable *wearablep) : - mCurrentDistortionParam( NULL ), - mAvatarp(NULL), - mWearablep(wearablep) + mAvatarAppearance(appearance), + mWearablep(wearable) { + llassert(mAvatarAppearance); + if (mWearablep) + { + llassert(mAvatarAppearance->isSelf()); + } mDefaultVec.clear(); } @@ -177,67 +176,25 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) return FALSE; mInfo = info; mID = info->mID; + info->mDriverParam = this; setWeight(getDefaultWeight(), FALSE ); return TRUE; } -void LLDriverParam::setWearable(LLWearable *wearablep) -{ - if (wearablep) - { - mWearablep = wearablep; - mAvatarp = NULL; - } -} - -void LLDriverParam::setAvatar(LLVOAvatar *avatarp) -{ - if (avatarp) - { - mWearablep = NULL; - mAvatarp = avatarp; - } -} - /*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const { - LLDriverParam *new_param; - if (wearable) - { - new_param = new LLDriverParam(wearable); - } - else - { - if (mWearablep) - { - new_param = new LLDriverParam(mWearablep); - } - else - { - new_param = new LLDriverParam(mAvatarp); - } - } + llassert(wearable); + LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable); + // FIXME DRANO this clobbers mWearablep, which means any code + // currently using mWearablep is wrong, or at least untested. *new_param = *this; + //new_param->mWearablep = wearable; +// new_param->mDriven.clear(); // clear driven list to avoid overwriting avatar driven params from wearables. return new_param; } -#if 0 // obsolete -BOOL LLDriverParam::parseData(LLXmlTreeNode* node) -{ - LLDriverParamInfo* info = new LLDriverParamInfo; - - info->parseXml(node); - if (!setInfo(info)) - { - delete info; - return FALSE; - } - return TRUE; -} -#endif - void LLDriverParam::setWeight(F32 weight, BOOL upload_bake) { F32 min_weight = getMinWeight(); @@ -456,6 +413,20 @@ const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly return v; }; +S32 LLDriverParam::getDrivenParamsCount() const +{ + return mDriven.size(); +} + +const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const +{ + if (0 > index || index >= mDriven.size()) + { + return NULL; + } + return mDriven[index].mParam; +} + //----------------------------------------------------------------------------- // setAnimationTarget() //----------------------------------------------------------------------------- @@ -511,6 +482,7 @@ BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross if (!found) { LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id); + if (param) param->setParamLocation(this->getParamLocation()); bool push = param && (!only_cross_params || param->getCrossWearable()); if (push) { @@ -555,7 +527,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) // Thus this wearable needs to get updates from the driver wearable. // The call to setVisualParamWeight seems redundant, but is necessary // as the number of driven wearables has changed since the last update. -Nyx - LLWearable *wearable = gAgentWearables.getTopWearable(driver_type); + LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type); if (wearable) { wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false); @@ -623,13 +595,22 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) { - if(isAgentAvatarValid() && - mWearablep && - driven->mParam->getCrossWearable() && - mWearablep->isOnTop()) + bool use_self = false; + if(mWearablep && + mAvatarAppearance->isValid() && + driven->mParam->getCrossWearable()) + { + LLWearable* wearable = dynamic_cast<LLWearable*> (mWearablep); + if (mAvatarAppearance->getWearableData()->isOnTop(wearable)) + { + use_self = true; + } + } + + if (use_self) { // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values - gAgentAvatarp->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); + mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); } else { diff --git a/indra/newview/lldriverparam.h b/indra/llappearance/lldriverparam.h index 216cf003e1..040c9cf5be 100755..100644 --- a/indra/newview/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -30,8 +30,8 @@ #include "llviewervisualparam.h" #include "llwearabletype.h" -class LLPhysicsMotion; -class LLVOAvatar; +class LLAvatarAppearance; +class LLDriverParam; class LLWearable; //----------------------------------------------------------------------------- @@ -71,6 +71,7 @@ public: protected: typedef std::deque<LLDrivenEntryInfo> entry_info_list_t; entry_info_list_t mDrivenInfoList; + LLDriverParam* mDriverParam; // backpointer }; //----------------------------------------------------------------------------- @@ -78,10 +79,11 @@ protected: LL_ALIGN_PREFIX(16) class LLDriverParam : public LLViewerVisualParam { - friend class LLPhysicsMotion; // physics motion needs to access driven params directly. +private: + // Hide the default constructor. Force construction with LLAvatarAppearance. + LLDriverParam() {} public: - LLDriverParam(LLVOAvatar *avatarp); - LLDriverParam(LLWearable *wearablep); + LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable = NULL); ~LLDriverParam(); void* operator new(size_t size) @@ -99,14 +101,14 @@ public: // This sets mInfo and calls initialization functions BOOL setInfo(LLDriverParamInfo *info); - void setWearable(LLWearable *wearablep); - void setAvatar(LLVOAvatar *avatarp); + LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } + const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + void updateCrossDrivenParams(LLWearableType::EType driven_type); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake ); @@ -122,6 +124,9 @@ public: /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + S32 getDrivenParamsCount() const; + const LLViewerVisualParam* getDrivenParam(S32 index) const; + protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); @@ -132,7 +137,7 @@ protected: entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; // Backlink only; don't make this an LLPointer. - LLVOAvatar* mAvatarp; + LLAvatarAppearance* mAvatarAppearance; LLWearable* mWearablep; } LL_ALIGN_POSTFIX(16); diff --git a/indra/llappearance/lljointpickname.h b/indra/llappearance/lljointpickname.h new file mode 100644 index 0000000000..1d41a761fc --- /dev/null +++ b/indra/llappearance/lljointpickname.h @@ -0,0 +1,49 @@ +/** + * @file lljointpickname.h + * @brief Defines OpenGL seleciton stack names + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#ifndef LL_LLJOINTPICKNAME_H +#define LL_LLJOINTPICKNAME_H + +class LLAvatarJointMesh; + +// Sets the OpenGL selection stack name that is pushed and popped +// with this joint state. The default value indicates that no name +// should be pushed/popped. +enum LLJointPickName +{ + PN_DEFAULT = -1, + PN_0 = 0, + PN_1 = 1, + PN_2 = 2, + PN_3 = 3, + PN_4 = 4, + PN_5 = 5 +}; + +typedef std::vector<LLAvatarJointMesh*> avatar_joint_mesh_list_t; + +#endif // LL_LLJOINTPICKNAME_H diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index 07ec0fab95..7e36a06797 100755..100644 --- a/indra/newview/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -23,13 +23,14 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "lllocaltextureobject.h" +#include "llimage.h" +#include "llrender.h" #include "lltexlayer.h" -#include "llviewertexture.h" -#include "lltextureentry.h" +#include "llgltexture.h" #include "lluuid.h" #include "llwearable.h" @@ -41,7 +42,7 @@ LLLocalTextureObject::LLLocalTextureObject() : mImage = NULL; } -LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id) : +LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) : mIsBakedReady(FALSE), mDiscard(MAX_DISCARD_LEVEL+1) { @@ -77,7 +78,7 @@ LLLocalTextureObject::~LLLocalTextureObject() { } -LLViewerFetchedTexture* LLLocalTextureObject::getImage() const +LLGLTexture* LLLocalTextureObject::getImage() const { return mImage; } @@ -126,7 +127,7 @@ BOOL LLLocalTextureObject::getBakedReady() const return mIsBakedReady; } -void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image) +void LLLocalTextureObject::setImage(LLGLTexture* new_image) { mImage = new_image; } diff --git a/indra/newview/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index b9bfc5472f..9b9f41fd19 100755..100644 --- a/indra/newview/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -29,11 +29,10 @@ #include <boost/shared_ptr.hpp> -#include "llviewertexture.h" +#include "llpointer.h" +#include "llgltexture.h" -class LLUUID; class LLTexLayer; -class LLTextureEntry; class LLTexLayerTemplate; class LLWearable; @@ -44,11 +43,11 @@ class LLLocalTextureObject { public: LLLocalTextureObject(); - LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id); + LLLocalTextureObject(LLGLTexture* image, const LLUUID& id); LLLocalTextureObject(const LLLocalTextureObject& lto); ~LLLocalTextureObject(); - LLViewerFetchedTexture* getImage() const; + LLGLTexture* getImage() const; LLTexLayer* getTexLayer(U32 index) const; LLTexLayer* getTexLayer(const std::string &name); U32 getNumTexLayers() const; @@ -56,7 +55,7 @@ public: S32 getDiscard() const; BOOL getBakedReady() const; - void setImage(LLViewerFetchedTexture* new_image); + void setImage(LLGLTexture* new_image); BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index); BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); @@ -70,7 +69,7 @@ protected: private: - LLPointer<LLViewerFetchedTexture> mImage; + LLPointer<LLGLTexture> mImage; // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer // using shared pointers here only for smart assignment & cleanup // do NOT create new shared pointers to these objects, or keep pointers to them around diff --git a/indra/newview/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 5f5258bbce..a01457246e 100755..100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -27,25 +27,24 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" - +#include "linden_common.h" +#include "llpolymesh.h" #include "llfasttimer.h" #include "llmemory.h" -#include "llviewercontrol.h" +//#include "llviewercontrol.h" #include "llxmltree.h" -#include "llvoavatar.h" +#include "llavatarappearance.h" #include "llwearable.h" #include "lldir.h" #include "llvolume.h" #include "llendianswizzle.h" -#include "llpolymesh.h" #define HEADER_ASCII "Linden Mesh 1.0" #define HEADER_BINARY "Linden Binary Mesh 1.0" -extern LLControlGroup gSavedSettings; // read only +//extern LLControlGroup gSavedSettings; // read only LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, const std::string &name); @@ -241,7 +240,7 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) mBaseNormals[i].clear(); mBaseBinormals[i].clear(); mTexCoords[i].clear(); - mWeights[i] = 0.f; + mWeights[i] = 0.f; } mNumVertices = numVertices; return TRUE; @@ -1046,250 +1045,4 @@ F32* LLPolyMesh::getWritableWeights() const return mSharedData->mWeights; } -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortionInfo() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() -{ -} - -BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; - - LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); - - if (NULL == skeletalParam) - { - llwarns << "Failed to getChildByName(\"param_skeleton\")" - << llendl; - return FALSE; - } - - for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) - { - if (bone->hasName("bone")) - { - std::string name; - LLVector3 scale; - LLVector3 pos; - BOOL haspos = FALSE; - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!bone->getFastAttributeString(name_string, name)) - { - llwarns << "No bone name specified for skeletal param." << llendl; - continue; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!bone->getFastAttributeVector3(scale_string, scale)) - { - llwarns << "No scale specified for bone " << name << "." << llendl; - continue; - } - - // optional offset deformation (translation) - static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); - if (bone->getFastAttributeVector3(offset_string, pos)) - { - haspos = TRUE; - } - mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); - } - else - { - llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl; - continue; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp) -{ - mAvatar = avatarp; - mDefaultVec.splat(0.001f); -} - -//----------------------------------------------------------------------------- -// ~LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::~LLPolySkeletalDistortion() -{ -} - -BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight(), FALSE ); - - LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; - for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) - { - LLPolySkeletalBoneInfo *bone_info = &(*iter); - LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); - if (!joint) - { - llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl; - continue; - } - - if (mJointScales.find(joint) != mJointScales.end()) - { - llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl; - } - - // store it - mJointScales[joint] = bone_info->mScaleDeformation; - - // apply to children that need to inherit it - for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); - iter != joint->mChildren.end(); ++iter) - { - LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); - if (child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info->mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } - } - - if (bone_info->mHasPositionDeformation) - { - if (mJointOffsets.find(joint) != mJointOffsets.end()) - { - llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl; - } - mJointOffsets[joint] = bone_info->mPositionDeformation; - } - } - return TRUE; -} - -/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const -{ - LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar); - *new_param = *this; - return new_param; -} - -//----------------------------------------------------------------------------- -// apply() -//----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); - -void LLPolySkeletalDistortion::apply( ESex avatar_sex ) -{ - LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); - - F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); - - LLJoint* joint; - joint_vec_map_t::iterator iter; - - for (iter = mJointScales.begin(); - iter != mJointScales.end(); - iter++) - { - joint = iter->first; - LLVector3 newScale = joint->getScale(); - LLVector3 scaleDelta = iter->second; - newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); - joint->setScale(newScale); - } - - for (iter = mJointOffsets.begin(); - iter != mJointOffsets.end(); - iter++) - { - joint = iter->first; - LLVector3 newPosition = joint->getPosition(); - LLVector3 positionDelta = iter->second; - newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); - joint->setPosition(newPosition); - } - - if (mLastWeight != mCurWeight && !mIsAnimating) - { - mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); - } - mLastWeight = mCurWeight; -} - - -LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, - const LLVector3 &direction, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - LLVector4a dir; - dir.load3(direction.mV); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = dir; - cloned_morph_data->mNormals[v].clear(); - cloned_morph_data->mBinormals[v].clear(); - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, - F32 scale, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - - LLVector4a sc; - sc.splat(scale); - - LLVector4a nsc; - nsc.set(scale, -scale, scale, scale); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); - } - else - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); - } - } - return cloned_morph_data; -} - // End diff --git a/indra/newview/llpolymesh.h b/indra/llappearance/llpolymesh.h index 28da230541..ef1dfb1adb 100755..100644 --- a/indra/newview/llpolymesh.h +++ b/indra/llappearance/llpolymesh.h @@ -24,8 +24,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLPOLYMESH_H -#define LL_LLPOLYMESH_H +#ifndef LL_LLPOLYMESHINTERFACE_H +#define LL_LLPOLYMESHINTERFACE_H #include <string> #include <map> @@ -39,7 +39,7 @@ //#include "lldarray.h" class LLSkinJoint; -class LLVOAvatar; +class LLAvatarAppearance; class LLWearable; //#define USE_STRIPS // Use tri-strips for rendering. @@ -319,8 +319,8 @@ public: BOOL isLOD() { return mSharedData && mSharedData->isLOD(); } - void setAvatar(LLVOAvatar* avatarp) { mAvatarp = avatarp; } - LLVOAvatar* getAvatar() { return mAvatarp; } + void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; } + LLAvatarAppearance* getAvatar() { return mAvatarp; } LLDynamicArray<LLJointRenderData*> mJointRenderData; @@ -362,90 +362,8 @@ protected: static LLPolyMeshSharedDataTable sGlobalSharedMeshList; // Backlink only; don't make this an LLPointer. - LLVOAvatar* mAvatarp; + LLAvatarAppearance* mAvatarp; }; -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformationInfo -// Shared information for LLPolySkeletalDeformations -//----------------------------------------------------------------------------- -struct LLPolySkeletalBoneInfo -{ - LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos) - : mBoneName(name), - mScaleDeformation(scale), - mPositionDeformation(pos), - mHasPositionDeformation(haspos) {} - std::string mBoneName; - LLVector3 mScaleDeformation; - LLVector3 mPositionDeformation; - BOOL mHasPositionDeformation; -}; - -class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo -{ - friend class LLPolySkeletalDistortion; -public: - LLPolySkeletalDistortionInfo(); - /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; - - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - -protected: - typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformation -// A set of joint scale data for deforming the avatar mesh -//----------------------------------------------------------------------------- - -LL_ALIGN_PREFIX(16) -class LLPolySkeletalDistortion : public LLViewerVisualParam -{ -public: - LLPolySkeletalDistortion(LLVOAvatar *avatarp); - ~LLPolySkeletalDistortion(); - - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - - // Special: These functions are overridden by child classes - LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLPolySkeletalDistortionInfo *info); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex sex ); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } - /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; - -protected: - LL_ALIGN_16(LLVector4a mDefaultVec); - - typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; - joint_vec_map_t mJointScales; - joint_vec_map_t mJointOffsets; - // Backlink only; don't make this an LLPointer. - LLVOAvatar *mAvatar; -} LL_ALIGN_POSTFIX(16); - -#endif // LL_LLPOLYMESH_H +#endif // LL_LLPOLYMESHINTERFACE_H diff --git a/indra/newview/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 495fdc348c..8a17819083 100755..100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -27,13 +27,14 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" #include "llpolymorph.h" -#include "llvoavatar.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" #include "llwearable.h" #include "llxmltree.h" #include "llendianswizzle.h" +#include "llpolymesh.h" //#include "../tools/imdebug/imdebug.h" @@ -343,7 +344,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) mID = info->mID; setWeight(getDefaultWeight(), FALSE ); - LLVOAvatar* avatarp = mMesh->getAvatar(); + LLAvatarAppearance* avatarp = mMesh->getAvatar(); LLPolyMorphTargetInfo::volume_info_list_t::iterator iter; for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++) { diff --git a/indra/newview/llpolymorph.h b/indra/llappearance/llpolymorph.h index 24940c52e0..ee380ae7c3 100755..100644 --- a/indra/newview/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -32,10 +32,10 @@ #include "llviewervisualparam.h" +class LLAvatarJointCollisionVolume; class LLPolyMeshSharedData; -class LLVOAvatar; class LLVector2; -class LLViewerJointCollisionVolume; +class LLAvatarJointCollisionVolume; class LLWearable; //----------------------------------------------------------------------------- @@ -119,10 +119,10 @@ struct LLPolyVolumeMorphInfo struct LLPolyVolumeMorph { - LLPolyVolumeMorph(LLViewerJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) + LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) : mVolume(volume), mScale(scale), mPos(pos) {}; - LLViewerJointCollisionVolume* mVolume; + LLAvatarJointCollisionVolume* mVolume; LLVector3 mScale; LLVector3 mPos; }; diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp new file mode 100644 index 0000000000..4ba16691c2 --- /dev/null +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -0,0 +1,293 @@ +/** + * @file llpolyskeletaldistortion.cpp + * @brief Implementation of LLPolySkeletalDistortion classes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llpreprocessor.h" +#include "llerrorlegacy.h" +//#include "llcommon.h" +//#include "llmemory.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llpolymorph.h" +//#include "llviewercontrol.h" +//#include "llxmltree.h" +//#include "llvoavatar.h" +#include "llwearable.h" +//#include "lldir.h" +//#include "llvolume.h" +//#include "llendianswizzle.h" + +#include "llpolyskeletaldistortion.h" + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortionInfo() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() +{ +} + +BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return FALSE; + + LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); + + if (NULL == skeletalParam) + { + llwarns << "Failed to getChildByName(\"param_skeleton\")" + << llendl; + return FALSE; + } + + for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) + { + if (bone->hasName("bone")) + { + std::string name; + LLVector3 scale; + LLVector3 pos; + BOOL haspos = FALSE; + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!bone->getFastAttributeString(name_string, name)) + { + llwarns << "No bone name specified for skeletal param." << llendl; + continue; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!bone->getFastAttributeVector3(scale_string, scale)) + { + llwarns << "No scale specified for bone " << name << "." << llendl; + continue; + } + + // optional offset deformation (translation) + static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); + if (bone->getFastAttributeVector3(offset_string, pos)) + { + haspos = TRUE; + } + mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); + } + else + { + llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl; + continue; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp) +{ + mAvatar = avatarp; + mDefaultVec.splat(0.001f); +} + +//----------------------------------------------------------------------------- +// ~LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::~LLPolySkeletalDistortion() +{ +} + +BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return FALSE; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight(), FALSE ); + + LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; + for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) + { + LLPolySkeletalBoneInfo *bone_info = &(*iter); + LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); + if (!joint) + { + llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl; + continue; + } + + if (mJointScales.find(joint) != mJointScales.end()) + { + llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl; + } + + // store it + mJointScales[joint] = bone_info->mScaleDeformation; + + // apply to children that need to inherit it + for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); + if (child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info->mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } + } + + if (bone_info->mHasPositionDeformation) + { + if (mJointOffsets.find(joint) != mJointOffsets.end()) + { + llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl; + } + mJointOffsets[joint] = bone_info->mPositionDeformation; + } + } + return TRUE; +} + +/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const +{ + LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar); + *new_param = *this; + return new_param; +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); + +void LLPolySkeletalDistortion::apply( ESex avatar_sex ) +{ + LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); + + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); + + LLJoint* joint; + joint_vec_map_t::iterator iter; + + for (iter = mJointScales.begin(); + iter != mJointScales.end(); + iter++) + { + joint = iter->first; + LLVector3 newScale = joint->getScale(); + LLVector3 scaleDelta = iter->second; + newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); + joint->setScale(newScale); + } + + for (iter = mJointOffsets.begin(); + iter != mJointOffsets.end(); + iter++) + { + joint = iter->first; + LLVector3 newPosition = joint->getPosition(); + LLVector3 positionDelta = iter->second; + newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); + joint->setPosition(newPosition); + } + + if (mLastWeight != mCurWeight && !mIsAnimating) + { + mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); + } + mLastWeight = mCurWeight; +} + + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = src_data->mCoords[v]; + cloned_morph_data->mNormals[v] = src_data->mNormals[v]; + cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } + } + return cloned_morph_data; +} + +// End diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h new file mode 100644 index 0000000000..774bc7dfa2 --- /dev/null +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -0,0 +1,131 @@ +/** + * @file llpolyskeletaldistortion.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYSKELETALDISTORTION_H +#define LL_LLPOLYSKELETALDISTORTION_H + +#include "llcommon.h" + +#include <string> +#include <map> +#include "llstl.h" + +#include "v3math.h" +#include "v2math.h" +#include "llquaternion.h" +//#include "llpolymorph.h" +#include "lljoint.h" +#include "llviewervisualparam.h" +//#include "lldarray.h" + +//class LLSkinJoint; +class LLAvatarAppearance; + +//#define USE_STRIPS // Use tri-strips for rendering. + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformationInfo +// Shared information for LLPolySkeletalDeformations +//----------------------------------------------------------------------------- +struct LLPolySkeletalBoneInfo +{ + LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos) + : mBoneName(name), + mScaleDeformation(scale), + mPositionDeformation(pos), + mHasPositionDeformation(haspos) {} + std::string mBoneName; + LLVector3 mScaleDeformation; + LLVector3 mPositionDeformation; + BOOL mHasPositionDeformation; +}; + +LL_ALIGN_PREFIX(16) +class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo +{ + friend class LLPolySkeletalDistortion; +public: + + LLPolySkeletalDistortionInfo(); + /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + +protected: + typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformation +// A set of joint scale data for deforming the avatar mesh +//----------------------------------------------------------------------------- +class LLPolySkeletalDistortion : public LLViewerVisualParam +{ +public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLPolySkeletalDistortion(LLAvatarAppearance *avatarp); + ~LLPolySkeletalDistortion(); + + // Special: These functions are overridden by child classes + LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLPolySkeletalDistortionInfo *info); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex sex ); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 0.1f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ F32 getMaxDistortion() { return 0.1f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + +protected: + LL_ALIGN_16(LLVector4a mDefaultVec); + typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; + joint_vec_map_t mJointScales; + joint_vec_map_t mJointOffsets; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance *mAvatar; +} LL_ALIGN_POSTFIX(16); + +#endif // LL_LLPOLYSKELETALDISTORTION_H + diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index ebe5ccd6c0..f38b982104 100755..100644 --- a/indra/newview/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -24,20 +24,20 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" -#include "llagent.h" +#include "linden_common.h" +#include "llavatarappearance.h" #include "lltexlayer.h" -#include "llvoavatar.h" -#include "llwearable.h" #include "lltexglobalcolor.h" +class LLWearable; + //----------------------------------------------------------------------------- // LLTexGlobalColor //----------------------------------------------------------------------------- -LLTexGlobalColor::LLTexGlobalColor(LLVOAvatar* avatar) +LLTexGlobalColor::LLTexGlobalColor(LLAvatarAppearance* appearance) : - mAvatar(avatar), + mAvatarAppearance(appearance), mInfo(NULL) { } @@ -91,7 +91,7 @@ const std::string& LLTexGlobalColor::getName() const // LLTexParamGlobalColor //----------------------------------------------------------------------------- LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) : - LLTexLayerParamColor(tex_global_color->getAvatar()), + LLTexLayerParamColor(tex_global_color->getAvatarAppearance()), mTexGlobalColor(tex_global_color) { } @@ -105,7 +105,7 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake) { - mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake); + mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake); } //----------------------------------------------------------------------------- diff --git a/indra/newview/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h index ae04798445..2867479876 100755..100644 --- a/indra/newview/lltexglobalcolor.h +++ b/indra/llappearance/lltexglobalcolor.h @@ -1,6 +1,6 @@ /** * @file lltexglobalcolor.h - * @brief This is global texture color info used by llvoavatar. + * @brief This is global texture color info used by llavatarappearance. * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code @@ -30,31 +30,31 @@ #include "lltexlayer.h" #include "lltexlayerparams.h" -class LLVOAvatar; +class LLAvatarAppearance; class LLWearable; class LLTexGlobalColorInfo; class LLTexGlobalColor { public: - LLTexGlobalColor( LLVOAvatar* avatar ); + LLTexGlobalColor( LLAvatarAppearance* appearance ); ~LLTexGlobalColor(); LLTexGlobalColorInfo* getInfo() const { return mInfo; } // This sets mInfo and calls initialization functions BOOL setInfo(LLTexGlobalColorInfo *info); - LLVOAvatar* getAvatar() const { return mAvatar; } + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } LLColor4 getColor() const; const std::string& getName() const; private: param_color_list_t mParamGlobalColorList; - LLVOAvatar* mAvatar; // just backlink, don't LLPointer + LLAvatarAppearance* mAvatarAppearance; // just backlink, don't LLPointer LLTexGlobalColorInfo *mInfo; }; -// Used by llvoavatar to determine skin/eye/hair color. +// Used by llavatarappearance to determine skin/eye/hair color. class LLTexGlobalColorInfo { friend class LLTexGlobalColor; diff --git a/indra/newview/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index ad09af6594..f951a982e5 100755..100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -24,36 +24,29 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "lltexlayer.h" -#include "llagent.h" +#include "llavatarappearance.h" +#include "llcrc.h" +#include "imageids.h" #include "llimagej2c.h" #include "llimagetga.h" -#include "llnotificationsutil.h" +#include "lldir.h" #include "llvfile.h" #include "llvfs.h" -#include "llviewerstats.h" -#include "llviewerregion.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "pipeline.h" -#include "llassetuploadresponders.h" #include "lltexlayerparams.h" -#include "llui.h" -#include "llagentwearables.h" +#include "lltexturemanagerbridge.h" +#include "../llui/llui.h" #include "llwearable.h" -#include "llviewercontrol.h" -#include "llviewershadermgr.h" +#include "llwearabledata.h" +#include "llvertexbuffer.h" #include "llviewervisualparam.h" //#include "../tools/imdebug/imdebug.h" -using namespace LLVOAvatarDefines; - -static const S32 BAKE_UPLOAD_ATTEMPTS = 7; -static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt +using namespace LLAvatarAppearanceDefines; // runway consolidate extern std::string self_av_string(); @@ -68,7 +61,7 @@ public: ~LLTexLayerInfo(); BOOL parseXml(LLXmlTreeNode* node); - BOOL createVisualParams(LLVOAvatar *avatar); + BOOL createVisualParams(LLAvatarAppearance *appearance); BOOL isUserSettable() { return mLocalTexture != -1; } S32 getLocalTexture() const { return mLocalTexture; } BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } @@ -96,125 +89,17 @@ private: }; //----------------------------------------------------------------------------- -// LLBakedUploadData() -//----------------------------------------------------------------------------- -LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, - LLTexLayerSet* layerset, - const LLUUID& id, - bool highest_res) : - mAvatar(avatar), - mTexLayerSet(layerset), - mID(id), - mStartTime(LLFrameTimer::getTotalTime()), // Record starting time - mIsHighestRes(highest_res) -{ -} - -//----------------------------------------------------------------------------- // LLTexLayerSetBuffer -// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. //----------------------------------------------------------------------------- -// static -S32 LLTexLayerSetBuffer::sGLByteCount = 0; - -LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, - S32 width, S32 height) : - // ORDER_LAST => must render these after the hints are created. - LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), - mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates - mNeedsUpload(FALSE), - mNumLowresUploads(0), - mUploadFailCount(0), - mNeedsUpdate(TRUE), - mNumLowresUpdates(0), +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) : mTexLayerSet(owner) { - LLTexLayerSetBuffer::sGLByteCount += getSize(); - mNeedsUploadTimer.start(); - mNeedsUpdateTimer.start(); } LLTexLayerSetBuffer::~LLTexLayerSetBuffer() { - LLTexLayerSetBuffer::sGLByteCount -= getSize(); - destroyGLTexture(); - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. - } -} - -//virtual -S8 LLTexLayerSetBuffer::getType() const -{ - return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ; -} - -//virtual -void LLTexLayerSetBuffer::restoreGLTexture() -{ - LLViewerDynamicTexture::restoreGLTexture() ; -} - -//virtual -void LLTexLayerSetBuffer::destroyGLTexture() -{ - LLViewerDynamicTexture::destroyGLTexture() ; -} - -// static -void LLTexLayerSetBuffer::dumpTotalByteCount() -{ - llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; -} - -void LLTexLayerSetBuffer::requestUpdate() -{ - restartUpdateTimer(); - mNeedsUpdate = TRUE; - mNumLowresUpdates = 0; - // If we're in the middle of uploading a baked texture, we don't care about it any more. - // When it's downloaded, ignore it. - mUploadID.setNull(); -} - -void LLTexLayerSetBuffer::requestUpload() -{ - conditionalRestartUploadTimer(); - mNeedsUpload = TRUE; - mNumLowresUploads = 0; - mUploadPending = TRUE; -} - -void LLTexLayerSetBuffer::conditionalRestartUploadTimer() -{ - // If we requested a new upload but haven't even uploaded - // a low res version of our last upload request, then - // keep the timer ticking instead of resetting it. - if (mNeedsUpload && (mNumLowresUploads == 0)) - { - mNeedsUploadTimer.unpause(); - } - else - { - mNeedsUploadTimer.reset(); - mNeedsUploadTimer.start(); - } -} - -void LLTexLayerSetBuffer::restartUpdateTimer() -{ - mNeedsUpdateTimer.reset(); - mNeedsUpdateTimer.start(); -} - -void LLTexLayerSetBuffer::cancelUpload() -{ - mNeedsUpload = FALSE; - mUploadPending = FALSE; - mNeedsUploadTimer.pause(); - mUploadRetryTimer.reset(); } void LLTexLayerSetBuffer::pushProjection() const @@ -222,7 +107,7 @@ void LLTexLayerSetBuffer::pushProjection() const gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); + gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); @@ -238,64 +123,24 @@ void LLTexLayerSetBuffer::popProjection() const gGL.popMatrix(); } -BOOL LLTexLayerSetBuffer::needsRender() -{ - llassert(mTexLayerSet->getAvatar() == gAgentAvatarp); - if (!isAgentAvatarValid()) return FALSE; - - const BOOL upload_now = mNeedsUpload && isReadyToUpload(); - const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); - - // Don't render if we don't want to (or aren't ready to) upload or update. - if (!(update_now || upload_now)) - { - return FALSE; - } - - // Don't render if we're animating our appearance. - if (gAgentAvatarp->getIsAppearanceAnimating()) - { - return FALSE; - } - - // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. - if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && - !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) - { - cancelUpload(); - return FALSE; - } - - // Render if we have at least minimal level of detail for each local texture. - return mTexLayerSet->isLocalTextureDataAvailable(); -} - -void LLTexLayerSetBuffer::preRender(BOOL clear_depth) +// virtual +void LLTexLayerSetBuffer::preRenderTexLayerSet() { // Set up an ortho projection pushProjection(); - - // keep depth buffer, we don't need to clear it - LLViewerDynamicTexture::preRender(FALSE); } -void LLTexLayerSetBuffer::postRender(BOOL success) +// virtual +void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) { popProjection(); - - LLViewerDynamicTexture::postRender(success); } -BOOL LLTexLayerSetBuffer::render() +BOOL LLTexLayerSetBuffer::renderTexLayerSet() { // Default color mask for tex layer render gGL.setColorMask(true, true); - // do we need to upload, and do we have sufficient data to create an uploadable composite? - // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero? - const BOOL upload_now = mNeedsUpload && isReadyToUpload(); - const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); - BOOL success = TRUE; bool use_shaders = LLGLSLShader::sNoFixedFunction; @@ -305,42 +150,20 @@ BOOL LLTexLayerSetBuffer::render() gAlphaMaskProgram.bind(); gAlphaMaskProgram.setMinimumAlpha(0.004f); } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.00f); + } LLVertexBuffer::unbind(); // Composite the color data LLGLSUIDefault gls_ui; - success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); + success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), + getCompositeWidth(), getCompositeHeight() ); gGL.flush(); - if(upload_now) - { - if (!success) - { - llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl; - mUploadPending = FALSE; - } - else - { - if (mTexLayerSet->isVisible()) - { - mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. - doUpload(); - } - else - { - mUploadPending = FALSE; - mNeedsUpload = FALSE; - mNeedsUploadTimer.pause(); - mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE); - } - } - } - - if (update_now) - { - doUpdate(); - } + midRenderTexLayerSet(success); if (use_shaders) { @@ -353,374 +176,11 @@ BOOL LLTexLayerSetBuffer::render() gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); - // we have valid texture data now - mGLTexturep->setGLTextureCreated(true); - return success; } -BOOL LLTexLayerSetBuffer::isInitialized(void) const -{ - return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); -} - -BOOL LLTexLayerSetBuffer::uploadPending() const -{ - return mUploadPending; -} - -BOOL LLTexLayerSetBuffer::uploadNeeded() const -{ - return mNeedsUpload; -} - -BOOL LLTexLayerSetBuffer::uploadInProgress() const -{ - return !mUploadID.isNull(); -} - -BOOL LLTexLayerSetBuffer::isReadyToUpload() const -{ - if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. - - BOOL ready = FALSE; - if (mTexLayerSet->isLocalTextureDataFinal()) - { - // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) - if (mUploadFailCount == 0) - { - ready = TRUE; - } - else - { - ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1)); - } - } - else - { - // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure - // we aren't doing uploads too frequently. - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); - if (texture_timeout != 0) - { - // The timeout period increases exponentially between every lowres upload in order to prevent - // spamming the server with frequent uploads. - const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); - - // If we hit our timeout and have textures available at even lower resolution, then upload. - const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); - ready = has_lower_lod && is_upload_textures_timeout; - } - } - - return ready; -} - -BOOL LLTexLayerSetBuffer::isReadyToUpdate() const -{ - // If we requested an update and have the final LOD ready, then update. - if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; - - // If we haven't done an update yet, then just do one now regardless of state of textures. - if (mNumLowresUpdates == 0) return TRUE; - - // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small - // since render unnecessarily doesn't cost much. - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout"); - if (texture_timeout != 0) - { - // If we hit our timeout and have textures available at even lower resolution, then update. - const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); - if (has_lower_lod && is_update_textures_timeout) return TRUE; - } - - return FALSE; -} - -BOOL LLTexLayerSetBuffer::requestUpdateImmediate() -{ - mNeedsUpdate = TRUE; - BOOL result = FALSE; - - if (needsRender()) - { - preRender(FALSE); - result = render(); - postRender(result); - } - - return result; -} - -// Create the baked texture, send it out to the server, then wait for it to come -// back so we can switch to using it. -void LLTexLayerSetBuffer::doUpload() -{ - llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); - - // Don't need caches since we're baked now. (note: we won't *really* be baked - // until this image is sent to the server and the Avatar Appearance message is received.) - mTexLayerSet->deleteCaches(); - - // Get the COLOR information from our texture - U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; - glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); - stop_glerror(); - - // Get the MASK information from our texture - LLGLSUIDefault gls_ui; - LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); - U8* baked_mask_data = baked_mask_image->getData(); - mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); - - - // Create the baked image from our color and mask information - const S32 baked_image_components = 5; // red green blue [bump] clothing - LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); - U8* baked_image_data = baked_image->getData(); - S32 i = 0; - for (S32 u=0; u < mFullWidth; u++) - { - for (S32 v=0; v < mFullHeight; v++) - { - baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. - baked_image_data[5*i + 4] = baked_mask_data[i]; - i++; - } - } - - LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; - const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) - if (compressedImage->encode(baked_image, comment_text)) - { - LLTransactionID tid; - tid.generate(); - const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), - gVFS, asset_id, LLAssetType::AT_TEXTURE)) - { - // Read back the file and validate. - BOOL valid = FALSE; - LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; - S32 file_size = 0; - - //data buffer MUST be allocated using LLImageBase - LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE); - file_size = file.getSize(); - U8* data = integrity_test->allocateData(file_size); - file.read(data, file_size); - - if (data) - { - valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' - } - else - { - integrity_test->setLastError("Unable to read entire file"); - } - - if (valid) - { - const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - // Baked_upload_data is owned by the responder and deleted after the request completes. - LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, - this->mTexLayerSet, - asset_id, - highest_lod); - // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. - mUploadID = asset_id; - - // Upload the image - const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); - if(!url.empty() - && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method - && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. - { - LLSD body = LLSD::emptyMap(); - // The responder will call LLTexLayerSetBuffer::onTextureUploadComplete() - LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); - llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; - } - else - { - gAssetStorage->storeAssetData(tid, - LLAssetType::AT_TEXTURE, - LLTexLayerSetBuffer::onTextureUploadComplete, - baked_upload_data, - TRUE, // temp_file - TRUE, // is_priority - TRUE); // store_local - llinfos << "Baked texture upload via Asset Store." << llendl; - } - - if (highest_lod) - { - // Sending the final LOD for the baked texture. All done, pause - // the upload timer so we know how long it took. - mNeedsUpload = FALSE; - mNeedsUploadTimer.pause(); - } - else - { - // Sending a lower level LOD for the baked texture. Restart the upload timer. - mNumLowresUploads++; - mNeedsUploadTimer.unpause(); - mNeedsUploadTimer.reset(); - } - - // Print out notification that we uploaded this texture. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); - args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); - args["RESOLUTION"] = lod_str; - LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; - } - } - else - { - // The read back and validate operation failed. Remove the uploaded file. - mUploadPending = FALSE; - LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); - file.remove(); - llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl; - } - } - } - else - { - // The VFS write file operation failed. - mUploadPending = FALSE; - llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl; - } - - delete [] baked_color_data; -} - -// Mostly bookkeeping; don't need to actually "do" anything since -// render() will actually do the update. -void LLTexLayerSetBuffer::doUpdate() -{ - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - if (highest_lod) - { - mNeedsUpdate = FALSE; - } - else - { - mNumLowresUpdates++; - } - - restartUpdateTimer(); - - // need to swtich to using this layerset if this is the first update - // after getting the lowest LOD - mTexLayerSet->getAvatar()->updateMeshTextures(); - - // Print out notification that we uploaded this texture. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); - args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); - args["RESOLUTION"] = lod_str; - LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; - } -} - -// static -void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, - void* userdata, - S32 result, - LLExtStat ext_status) // StoreAssetData callback (not fixed) -{ - LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; - - if (isAgentAvatarValid() && - !gAgentAvatarp->isDead() && - (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures. - (baked_upload_data->mTexLayerSet->hasComposite())) - { - LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); - S32 failures = layerset_buffer->mUploadFailCount; - layerset_buffer->mUploadFailCount = 0; - - if (layerset_buffer->mUploadID.isNull()) - { - // The upload got canceled, we should be in the - // process of baking a new texture so request an - // upload with the new data - - // BAP: does this really belong in this callback, as - // opposed to where the cancellation takes place? - // suspect this does nothing. - layerset_buffer->requestUpload(); - } - else if (baked_upload_data->mID == layerset_buffer->mUploadID) - { - // This is the upload we're currently waiting for. - layerset_buffer->mUploadID.setNull(); - const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName()); - const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res "; - if (result >= 0) - { - layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later - LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); - // Update baked texture info with the new UUID - U64 now = LLFrameTimer::getTotalTime(); // Record starting time - llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; - gAgentAvatarp->setNewBakedTexture(baked_te, uuid); - } - else - { - ++failures; - S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes - llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl; - if (failures < max_attempts) - { - layerset_buffer->mUploadFailCount = failures; - layerset_buffer->mUploadRetryTimer.start(); - layerset_buffer->requestUpload(); - } - } - } - else - { - llinfos << "Received baked texture out of date, ignored." << llendl; - } - - gAgentAvatarp->dirtyMesh(); - } - else - { - // Baked texture failed to upload (in which case since we - // didn't set the new baked texture, it means that they'll try - // and rebake it at some point in the future (after login?)), - // or this response to upload is out of date, in which case a - // current response should be on the way or already processed. - llwarns << "Baked upload failed" << llendl; - } - - delete baked_upload_data; -} - //----------------------------------------------------------------------------- -// LLTexLayerSet +// LLTexLayerSetInfo // An ordered set of texture layers that get composited into a single texture. //----------------------------------------------------------------------------- @@ -790,7 +250,7 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) } // creates visual params without generating layersets or layers -void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar) +void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) { //layer_info_list_t mLayerInfoList; for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin(); @@ -798,7 +258,7 @@ void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar) layer_iter++) { LLTexLayerInfo *layer_info = *layer_iter; - layer_info->createVisualParams(avatar); + layer_info->createVisualParams(appearance); } } @@ -809,16 +269,15 @@ void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar) BOOL LLTexLayerSet::sHasCaches = FALSE; -LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) : - mComposite( NULL ), - mAvatar( avatar ), - mUpdatesEnabled( FALSE ), +LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : + mAvatarAppearance( appearance ), mIsVisible( TRUE ), - mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD), + mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD), mInfo( NULL ) { } +// virtual LLTexLayerSet::~LLTexLayerSet() { deleteCaches(); @@ -844,13 +303,13 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) LLTexLayerInterface *layer = NULL; if ( (*iter)->isUserSettable() ) { - layer = new LLTexLayerTemplate( this ); + layer = new LLTexLayerTemplate( this, getAvatarAppearance() ); } else { layer = new LLTexLayer(this); } - // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar + // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance if (!layer->setInfo(*iter, NULL)) { mInfo = NULL; @@ -910,21 +369,6 @@ void LLTexLayerSet::deleteCaches() } } -// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. -BOOL LLTexLayerSet::isLocalTextureDataAvailable() const -{ - if (!mAvatar->isSelf()) return FALSE; - return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataAvailable(this); -} - - -// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. -BOOL LLTexLayerSet::isLocalTextureDataFinal() const -{ - if (!mAvatar->isSelf()) return FALSE; - return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataFinal(this); -} - BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { @@ -1025,43 +469,31 @@ const std::string LLTexLayerSet::getBodyRegionName() const return mInfo->mBodyRegion; } -void LLTexLayerSet::requestUpdate() -{ - if( mUpdatesEnabled ) - { - createComposite(); - mComposite->requestUpdate(); - } -} - -void LLTexLayerSet::requestUpload() -{ - createComposite(); - mComposite->requestUpload(); -} -void LLTexLayerSet::cancelUpload() +// virtual +void LLTexLayerSet::asLLSD(LLSD& sd) const { - if(mComposite) + sd["visible"] = LLSD::Boolean(isVisible()); + LLSD layer_list_sd; + layer_list_t::const_iterator layer_iter = mLayerList.begin(); + layer_list_t::const_iterator layer_end = mLayerList.end(); + for(; layer_iter != layer_end; ++layer_iter); { - mComposite->cancelUpload(); + LLSD layer_sd; + //LLTexLayerInterface* layer = (*layer_iter); + //if (layer) + //{ + // layer->asLLSD(layer_sd); + //} + layer_list_sd.append(layer_sd); } + LLSD mask_list_sd; + LLSD info_sd; + sd["layers"] = layer_list_sd; + sd["masks"] = mask_list_sd; + sd["info"] = info_sd; } -void LLTexLayerSet::createComposite() -{ - if(!mComposite) - { - S32 width = mInfo->mWidth; - S32 height = mInfo->mHeight; - // Composite other avatars at reduced resolution - if( !mAvatar->isSelf() ) - { - llerrs << "composites should not be created for non-self avatars!" << llendl; - } - mComposite = new LLTexLayerSetBuffer( this, width, height ); - } -} void LLTexLayerSet::destroyComposite() { @@ -1071,18 +503,6 @@ void LLTexLayerSet::destroyComposite() } } -void LLTexLayerSet::setUpdatesEnabled( BOOL b ) -{ - mUpdatesEnabled = b; -} - - -void LLTexLayerSet::updateComposite() -{ - createComposite(); - mComposite->requestUpdateImmediate(); -} - LLTexLayerSetBuffer* LLTexLayerSet::getComposite() { if (!mComposite) @@ -1097,22 +517,26 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const return mComposite; } -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) +static LLFastTimer::DeclareTimer FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height) { + LLFastTimer t(FTM_GATHER_MORPH_MASK_ALPHA); memset(data, 255, width * height); for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); + layer->gatherAlphaMasks(data, origin_x, origin_y, width, height); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); + renderAlphaMaskTextures(origin_x, origin_y, width, height, true); } +static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { + LLFastTimer t(FTM_RENDER_ALPHA_MASK_TEXTURES); const LLTexLayerSetInfo *info = getInfo(); bool use_shaders = LLGLSLShader::sNoFixedFunction; @@ -1125,7 +549,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gGL.flush(); { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); if( tex ) { LLGLSUIDefault gls_ui; @@ -1182,7 +606,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) { - mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); + mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); } BOOL LLTexLayerSet::isMorphValid() const @@ -1297,11 +721,11 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) /* if ("upper_shirt" == local_texture_name) mLocalTexture = TEX_UPPER_SHIRT; */ mLocalTexture = TEX_NUM_INDICES; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); iter++) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (local_texture_name == texture_dict->mName) { mLocalTexture = iter->first; @@ -1368,7 +792,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) return TRUE; } -BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) +BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) { BOOL success = TRUE; for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin(); @@ -1376,7 +800,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) color_info_iter++) { LLTexLayerParamColorInfo * color_info = *color_info_iter; - LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar); + LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); if (!param_color->setInfo(color_info, TRUE)) { llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl; @@ -1390,7 +814,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) alpha_info_iter++) { LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; - LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar); + LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); if (!param_alpha->setInfo(alpha_info, TRUE)) { llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl; @@ -1498,6 +922,59 @@ const std::string& LLTexLayerInterface::getName() const return mInfo->mName; } +ETextureIndex LLTexLayerInterface::getLocalTextureIndex() const +{ + return (ETextureIndex) mInfo->mLocalTexture; +} + +LLWearableType::EType LLTexLayerInterface::getWearableType() const +{ + ETextureIndex te = getLocalTextureIndex(); + if (TEX_INVALID == te) + { + LLWearableType::EType type = LLWearableType::WT_INVALID; + param_color_list_t::const_iterator color_iter = mParamColorList.begin(); + param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); + + for (; color_iter != mParamColorList.end(); color_iter++) + { + LLTexLayerParamColor* param = *color_iter; + if (param) + { + LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); + if (new_type != LLWearableType::WT_INVALID && new_type != type) + { + if (type != LLWearableType::WT_INVALID) + { + return LLWearableType::WT_INVALID; + } + type = new_type; + } + } + } + + for (; alpha_iter != mParamAlphaList.end(); alpha_iter++) + { + LLTexLayerParamAlpha* param = *alpha_iter; + if (param) + { + LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); + if (new_type != LLWearableType::WT_INVALID && new_type != type) + { + if (type != LLWearableType::WT_INVALID) + { + return LLWearableType::WT_INVALID; + } + type = new_type; + } + } + } + + return type; + } + return LLAvatarAppearanceDictionary::getTEWearableType(te); +} + LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const { return mInfo->mRenderPass; @@ -1586,6 +1063,12 @@ LLTexLayer::~LLTexLayer() } +void LLTexLayer::asLLSD(LLSD& sd) const +{ + // *TODO: Finish + sd["id"] = getUUID(); +} + //----------------------------------------------------------------------------- // setInfo //----------------------------------------------------------------------------- @@ -1637,17 +1120,21 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { LLGLEnable color_mat(GL_COLOR_MATERIAL); - gPipeline.disableLights(); + // *TODO: Is this correct? + //gPipeline.disableLights(); + stop_glerror(); + glDisable(GL_LIGHTING); + stop_glerror(); bool use_shaders = LLGLSLShader::sNoFixedFunction; LLColor4 net_color; BOOL color_specified = findNetColor(&net_color); - if (mTexLayerSet->getAvatar()->mIsDummy) + if (mTexLayerSet->getAvatarAppearance()->mIsDummy) { color_specified = true; - net_color = LLVOAvatar::getDummyColor(); + net_color = LLAvatarAppearance::getDummyColor(); } BOOL success = TRUE; @@ -1687,7 +1174,8 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) } }//*/ - renderMorphMasks(x, y, width, height, net_color); + const bool force_render = true; + renderMorphMasks(x, y, width, height, net_color, force_render); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1704,7 +1192,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) { { - LLViewerTexture* tex = NULL; + LLGLTexture* tex = NULL; if (mLocalTextureObject && mLocalTextureObject->getImage()) { tex = mLocalTextureObject->getImage(); @@ -1717,15 +1205,18 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl; } -// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) +// if( mTexLayerSet->getAvatarAppearance()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) { if( tex ) { bool no_alpha_test = getInfo()->mWriteAllChannels; LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0); - if (use_shaders && no_alpha_test) + if (no_alpha_test) { - gAlphaMaskProgram.setMinimumAlpha(0.f); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } } LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); @@ -1737,11 +1228,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) gGL.getTexUnit(0)->setTextureAddressMode(old_mode); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (use_shaders && no_alpha_test) + if (no_alpha_test) { - gAlphaMaskProgram.setMinimumAlpha(0.004f); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } } - } } // else @@ -1754,7 +1247,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) if( !getInfo()->mStaticImageFileName.empty() ) { { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { gGL.getTexUnit(0)->bind(tex, TRUE); @@ -1776,8 +1269,9 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) LLGLDisable no_alpha(GL_ALPHA_TEST); if (use_shaders) { - gAlphaMaskProgram.setMinimumAlpha(0.f); + gAlphaMaskProgram.setMinimumAlpha(0.000f); } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv( net_color.mV ); gl_rect_2d_simple( width, height ); @@ -1834,7 +1328,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const { if( !getGlobalColor().empty() ) { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) ); } else if (getInfo()->mFixedColor.mV[VW]) { @@ -1851,7 +1345,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const if( !getGlobalColor().empty() ) { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) ); + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) ); return TRUE; } @@ -1876,7 +1370,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) if( !getInfo()->mStaticImageFileName.empty() ) { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); if( tex ) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1901,7 +1395,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) { - LLViewerTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if (tex) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1929,8 +1423,15 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) addAlphaMask(data, originX, originY, width, height); } -BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) +static LLFastTimer::DeclareTimer FTM_RENDER_MORPH_MASKS("renderMorphMasks"); +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) { + if (!force_render && !hasMorph()) + { + lldebugs << "skipping renderMorphMasks for " << getUUID() << llendl; + return; + } + LLFastTimer t(FTM_RENDER_MORPH_MASKS); BOOL success = TRUE; llassert( !mParamAlphaList.empty() ); @@ -1966,6 +1467,11 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { LLTexLayerParamAlpha* param = *iter; success &= param->render( x, y, width, height ); + if (!success && !force_render) + { + lldebugs << "Failed to render param " << param->getID() << " ; skipping morph mask." << llendl; + return; + } } // Approximates a min() function @@ -1975,7 +1481,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - LLViewerTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if( tex && (tex->getComponents() == 4) ) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1991,25 +1497,29 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } } - if( !getInfo()->mStaticImageFileName.empty() ) + if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask ) { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { - if( (tex->getComponents() == 4) || - ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) + if( (tex->getComponents() == 4) || (tex->getComponents() == 1) ) { LLGLSNoAlphaTest gls_no_alpha_test; gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } + else + { + llwarns << "Skipping rendering of " << getInfo()->mStaticImageFileName + << "; expected 1 or 4 components." << llendl; + } } } // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if (layer_color.mV[VW] != 1.f) + if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) { LLGLDisable no_alpha(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2044,7 +1554,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC if (!alpha_data) { // clear out a slot if we have filled our cache - S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1; + S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry @@ -2057,17 +1567,17 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); } - getTexLayerSet()->getAvatar()->dirtyMesh(); + getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); mMorphMasksValid = TRUE; getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); } - - return success; } +static LLFastTimer::DeclareTimer FTM_ADD_ALPHA_MASK("addAlphaMask"); void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { + LLFastTimer t(FTM_ADD_ALPHA_MASK); S32 size = width * height; const U8* alphaData = getAlphaData(); if (!alphaData && hasAlphaParams()) @@ -2076,7 +1586,8 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 findNetColor( &net_color ); // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); - renderMorphMasks(originX, originY, width, height, net_color); + const bool force_render = false; + renderMorphMasks(originX, originY, width, height, net_color, force_render); alphaData = getAlphaData(); } if (alphaData) @@ -2085,7 +1596,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 { U8 curAlpha = data[i]; U16 resultAlpha = curAlpha; - resultAlpha *= (alphaData[i] + 1); + resultAlpha *= ( ((U16)alphaData[i]) + 1); resultAlpha = resultAlpha >> 8; data[i] = (U8)resultAlpha; } @@ -2110,7 +1621,7 @@ LLUUID LLTexLayer::getUUID() const LLUUID uuid; if( getInfo()->mLocalTexture != -1 ) { - LLViewerTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if (tex) { uuid = mLocalTextureObject->getID(); @@ -2118,7 +1629,7 @@ LLUUID LLTexLayer::getUUID() const } if( !getInfo()->mStaticImageFileName.empty() ) { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { uuid = tex->getID(); @@ -2141,13 +1652,15 @@ LLUUID LLTexLayer::getUUID() const // * a texture entry index (TE) // * (optional) one or more alpha parameters (weighted alpha textures) //----------------------------------------------------------------------------- -LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) : - LLTexLayerInterface(layer_set) +LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set, LLAvatarAppearance* const appearance) : + LLTexLayerInterface(layer_set), + mAvatarAppearance( appearance ) { } LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : - LLTexLayerInterface(layer) + LLTexLayerInterface(layer), + mAvatarAppearance(layer.getAvatarAppearance()) { } @@ -2168,18 +1681,17 @@ U32 LLTexLayerTemplate::updateWearableCache() const { mWearableCache.clear(); - S32 te = mInfo->mLocalTexture; - if (te == -1) + LLWearableType::EType wearable_type = getWearableType(); + if (LLWearableType::WT_INVALID == wearable_type) { //this isn't a cloneable layer return 0; } - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te); - U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + U32 num_wearables = getAvatarAppearance()->getWearableData()->getWearableCount(wearable_type); U32 added = 0; for (U32 i = 0; i < num_wearables; i++) { - LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i); + LLWearable* wearable = getAvatarAppearance()->getWearableData()->getWearable(wearable_type, i); if (!wearable) { continue; @@ -2234,7 +1746,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const } if (layer) { - wearable->writeToAvatar(); + wearable->writeToAvatar(mAvatarAppearance); layer->setLTO(lto); success &= layer->render(x,y,width,height); } @@ -2341,7 +1853,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) return NULL; } -void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable) +void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable) { // initialize all texlayers with this texture type for this LTO for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) @@ -2408,8 +1920,10 @@ void LLTexLayerStaticImageList::deleteCachedImages() // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. +static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TGA("getImageTGA"); LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) { + LLFastTimer t(FTM_LOAD_STATIC_TGA); const char *namekey = mImageNames.addString(file_name); image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); if( iter != mStaticImageListTGA.end() ) @@ -2436,9 +1950,11 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) +static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TEXTURE("getTexture"); +LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) { - LLPointer<LLViewerTexture> tex; + LLFastTimer t(FTM_LOAD_STATIC_TEXTURE); + LLPointer<LLGLTexture> tex; const char *namekey = mImageNames.addString(file_name); texture_map_t::const_iterator iter = mStaticImageList.find(namekey); @@ -2448,17 +1964,24 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n } else { - tex = LLViewerTextureManager::getLocalTexture( FALSE ); + llassert(gTextureManagerBridgep); + tex = gTextureManagerBridgep->getLocalTexture( FALSE ); LLPointer<LLImageRaw> image_raw = new LLImageRaw; if( loadImageRaw( file_name, image_raw ) ) { if( (image_raw->getComponents() == 1) && is_mask ) { - // Note: these are static, unchanging images so it's ok to assume - // that once an image is a mask it's always a mask. - tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); + // Convert grayscale alpha masks from single channel into RGBA. + // Fill RGB with black to allow fixed function gl calls + // to match shader implementation. + LLPointer<LLImageRaw> alpha_image_raw = image_raw; + image_raw = new LLImageRaw(image_raw->getWidth(), + image_raw->getHeight(), + 4); + + image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); } - tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL); + tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL); gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -2477,8 +2000,10 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n // Reads a .tga file, decodes it, and puts the decoded data in image_raw. // Returns TRUE if successful. +static LLFastTimer::DeclareTimer FTM_LOAD_IMAGE_RAW("loadImageRaw"); BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) { + LLFastTimer t(FTM_LOAD_IMAGE_RAW); BOOL success = FALSE; std::string path; path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); @@ -2492,23 +2017,3 @@ BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLIma return success; } -const std::string LLTexLayerSetBuffer::dumpTextureInfo() const -{ - if (!isAgentAvatarValid()) return ""; - - const BOOL is_high_res = !mNeedsUpload; - const U32 num_low_res = mNumLowresUploads; - const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32(); - const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet); - - std::string status = "CREATING "; - if (!uploadNeeded()) status = "DONE "; - if (uploadInProgress()) status = "UPLOADING"; - - std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s", - status.c_str(), - is_high_res, num_low_res, - upload_time, - local_texture_info.c_str()); - return text; -} diff --git a/indra/newview/lltexlayer.h b/indra/llappearance/lltexlayer.h index 4f43547dae..959d6e499a 100755..100644 --- a/indra/newview/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -28,14 +28,15 @@ #define LL_LLTEXLAYER_H #include <deque> -#include "lldynamictexture.h" -#include "llvoavatardefines.h" +#include "llglslshader.h" +#include "llgltexture.h" +#include "llavatarappearancedefines.h" #include "lltexlayerparams.h" -class LLVOAvatar; -class LLVOAvatarSelf; +class LLAvatarAppearance; class LLImageTGA; class LLImageRaw; +class LLLocalTextureObject; class LLXmlTreeNode; class LLTexLayerSet; class LLTexLayerSetInfo; @@ -71,6 +72,8 @@ public: const LLTexLayerInfo* getInfo() const { return mInfo; } virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions + LLWearableType::EType getWearableType() const; + LLAvatarAppearanceDefines::ETextureIndex getLocalTextureIndex() const; const std::string& getName() const; const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } @@ -88,6 +91,8 @@ public: ERenderPass getRenderPass() const; BOOL isVisibilityMask() const; + virtual void asLLSD(LLSD& sd) const {} + protected: const std::string& getGlobalColor() const; LLViewerVisualParam* getVisualParamPtr(S32 index) const; @@ -113,7 +118,7 @@ protected: class LLTexLayerTemplate : public LLTexLayerInterface { public: - LLTexLayerTemplate(LLTexLayerSet* const layer_set); + LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); @@ -126,7 +131,9 @@ public: protected: U32 updateWearableCache() const; LLTexLayer* getLayer(U32 i) const; + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } private: + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. typedef std::vector<LLWearable*> wearable_cache_t; mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache }; @@ -153,17 +160,18 @@ public: BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render); void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); /*virtual*/ BOOL isInvisibleAlphaMask() const; void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } LLLocalTextureObject* getLTO() { return mLocalTextureObject; } + /*virtual*/ void asLLSD(LLSD& sd) const; + static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); protected: LLUUID getUUID() const; -private: typedef std::map<U32, U8*> alpha_cache_t; alpha_cache_t mAlphaCache; LLLocalTextureObject* mLocalTextureObject; @@ -179,8 +187,14 @@ class LLTexLayerSet { friend class LLTexLayerSetBuffer; public: - LLTexLayerSet(LLVOAvatarSelf* const avatar); - ~LLTexLayerSet(); + LLTexLayerSet(LLAvatarAppearance* const appearance); + virtual ~LLTexLayerSet(); + + LLTexLayerSetBuffer* getComposite(); + const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. + virtual void createComposite() = 0; + void destroyComposite(); + void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height); const LLTexLayerSetInfo* getInfo() const { return mInfo; } BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions @@ -189,45 +203,34 @@ public: void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); BOOL isBodyRegion(const std::string& region) const; - LLTexLayerSetBuffer* getComposite(); - const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. - void requestUpdate(); - void requestUpload(); - void cancelUpload(); - void updateComposite(); - BOOL isLocalTextureDataAvailable() const; - BOOL isLocalTextureDataFinal() const; - void createComposite(); - void destroyComposite(); - void setUpdatesEnabled(BOOL b); - BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } - void deleteCaches(); - void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); BOOL isMorphValid() const; + virtual void requestUpdate() = 0; void invalidateMorphMasks(); + void deleteCaches(); LLTexLayerInterface* findLayerByName(const std::string& name); - void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); + void cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable* wearable); - LLVOAvatarSelf* getAvatar() const { return mAvatar; } + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } const std::string getBodyRegionName() const; BOOL hasComposite() const { return (mComposite.notNull()); } - LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } - void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } + LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() const { return mBakedTexIndex; } + void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } BOOL isVisible() const { return mIsVisible; } static BOOL sHasCaches; -private: + virtual void asLLSD(LLSD& sd) const; + +protected: typedef std::vector<LLTexLayerInterface *> layer_list_t; layer_list_t mLayerList; layer_list_t mMaskLayerList; LLPointer<LLTexLayerSetBuffer> mComposite; - LLVOAvatarSelf* const mAvatar; // note: backlink only; don't make this an LLPointer. - BOOL mUpdatesEnabled; + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. BOOL mIsVisible; - LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; + LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex; const LLTexLayerSetInfo* mInfo; }; @@ -243,8 +246,10 @@ public: LLTexLayerSetInfo(); ~LLTexLayerSetInfo(); BOOL parseXml(LLXmlTreeNode* node); - void createVisualParams(LLVOAvatar *avatar); -private: + void createVisualParams(LLAvatarAppearance *appearance); + S32 getWidth() const { return mWidth; } + S32 getHeight() const { return mHeight; } +protected: std::string mBodyRegion; S32 mWidth; S32 mHeight; @@ -259,78 +264,27 @@ private: // // The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetBuffer : public LLViewerDynamicTexture +class LLTexLayerSetBuffer : public virtual LLRefCount { LOG_CLASS(LLTexLayerSetBuffer); public: - LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); + LLTexLayerSetBuffer(LLTexLayerSet* const owner); virtual ~LLTexLayerSetBuffer(); -public: - /*virtual*/ S8 getType() const; - BOOL isInitialized(void) const; - static void dumpTotalByteCount(); - const std::string dumpTextureInfo() const; - virtual void restoreGLTexture(); - virtual void destroyGLTexture(); protected: void pushProjection() const; void popProjection() const; -private: - LLTexLayerSet* const mTexLayerSet; - static S32 sGLByteCount; + virtual void preRenderTexLayerSet(); + virtual void midRenderTexLayerSet(BOOL success) {} + virtual void postRenderTexLayerSet(BOOL success); + virtual S32 getCompositeOriginX() const = 0; + virtual S32 getCompositeOriginY() const = 0; + virtual S32 getCompositeWidth() const = 0; + virtual S32 getCompositeHeight() const = 0; + BOOL renderTexLayerSet(); - //-------------------------------------------------------------------- - // Render - //-------------------------------------------------------------------- -public: - /*virtual*/ BOOL needsRender(); -protected: - BOOL render(S32 x, S32 y, S32 width, S32 height); - virtual void preRender(BOOL clear_depth); - virtual void postRender(BOOL success); - virtual BOOL render(); - - //-------------------------------------------------------------------- - // Uploads - //-------------------------------------------------------------------- -public: - void requestUpload(); - void cancelUpload(); - BOOL uploadNeeded() const; // We need to upload a new texture - BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result - BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point - static void onTextureUploadComplete(const LLUUID& uuid, - void* userdata, - S32 result, LLExtStat ext_status); -protected: - BOOL isReadyToUpload() const; - void doUpload(); // Does a read back and upload. - void conditionalRestartUploadTimer(); -private: - BOOL mNeedsUpload; // Whether we need to send our baked textures to the server - U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server - BOOL mUploadPending; // Whether we have received back the new baked textures - LLUUID mUploadID; // The current upload process (null if none). - LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed. - S32 mUploadFailCount; // Number of consecutive upload failures - LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure. - - //-------------------------------------------------------------------- - // Updates - //-------------------------------------------------------------------- -public: - void requestUpdate(); - BOOL requestUpdateImmediate(); -protected: - BOOL isReadyToUpdate() const; - void doUpdate(); - void restartUpdateTimer(); -private: - BOOL mNeedsUpdate; // Whether we need to locally update our baked textures - U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures - LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed. + LLTexLayerSet* const mTexLayerSet; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -342,7 +296,7 @@ class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList> public: LLTexLayerStaticImageList(); ~LLTexLayerStaticImageList(); - LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask); + LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask); LLImageTGA* getImageTGA(const std::string& file_name); void deleteCachedImages(); void dumpByteCount() const; @@ -350,7 +304,7 @@ protected: BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); private: LLStringTable mImageNames; - typedef std::map<const char*, LLPointer<LLViewerTexture> > texture_map_t; + typedef std::map<const char*, LLPointer<LLGLTexture> > texture_map_t; texture_map_t mStaticImageList; typedef std::map<const char*, LLPointer<LLImageTGA> > image_tga_map_t; image_tga_map_t mStaticImageListTGA; @@ -358,23 +312,4 @@ private: S32 mTGABytes; }; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLBakedUploadData -// -// Used by LLTexLayerSetBuffer for a callback. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -struct LLBakedUploadData -{ - LLBakedUploadData(const LLVOAvatarSelf* avatar, - LLTexLayerSet* layerset, - const LLUUID& id, - bool highest_res); - ~LLBakedUploadData() {} - const LLUUID mID; - const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer - LLTexLayerSet* mTexLayerSet; - const U64 mStartTime; // for measuring baked texture upload time - const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res -}; - #endif // LL_LLTEXLAYER_H diff --git a/indra/newview/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 8972827eff..6aae9a8cc1 100755..100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -24,27 +24,28 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "lltexlayerparams.h" -#include "llagentcamera.h" +#include "llavatarappearance.h" #include "llimagetga.h" +#include "llquantize.h" #include "lltexlayer.h" -#include "llvoavatarself.h" +#include "lltexturemanagerbridge.h" +#include "../llui/llui.h" #include "llwearable.h" -#include "llui.h" //----------------------------------------------------------------------------- // LLTexLayerParam //----------------------------------------------------------------------------- LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : mTexLayer(layer), - mAvatar(NULL) + mAvatarAppearance(NULL) { if (mTexLayer != NULL) { - mAvatar = mTexLayer->getTexLayerSet()->getAvatar(); + mAvatarAppearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); } else { @@ -52,20 +53,21 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : } } -LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) : - mTexLayer(NULL) +LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) : + mTexLayer(NULL), + mAvatarAppearance(appearance) { - mAvatar = avatar; } -BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ) -{ +BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance) +{ LLViewerVisualParam::setInfo(info); - if (add_to_avatar) + if (add_to_appearance) { - mAvatar->addVisualParam( this); + mAvatarAppearance->addVisualParam( this); + this->setParamLocation(mAvatarAppearance->isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); } return TRUE; @@ -96,7 +98,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) iter != sInstances.end(); iter++) { LLTexLayerParamAlpha* instance = *iter; - LLViewerTexture* tex = instance->mCachedProcessedTexture; + LLGLTexture* tex = instance->mCachedProcessedTexture; if (tex) { S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); @@ -120,8 +122,8 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) : sInstances.push_front(this); } -LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLVOAvatar* avatar) : - LLTexLayerParam(avatar), +LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) : + LLTexLayerParam(appearance), mCachedProcessedTexture(NULL), mNeedsCreateTexture(FALSE), mStaticImageInvalid(FALSE), @@ -173,13 +175,10 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake) { mCurWeight = new_weight; - if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + if ((mAvatarAppearance->getSex() & getSex()) && + (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. { - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) - { - upload_bake = FALSE; - } - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); mTexLayer->invalidateMorphMasks(); } } @@ -218,11 +217,11 @@ BOOL LLTexLayerParamAlpha::getSkip() const return TRUE; } - const LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar(); + const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight) { - F32 effective_weight = (avatar->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); if (is_approx_zero(effective_weight)) { return TRUE; @@ -230,7 +229,7 @@ BOOL LLTexLayerParamAlpha::getSkip() const } LLWearableType::EType type = (LLWearableType::EType)getWearableType(); - if ((type != LLWearableType::WT_INVALID) && !avatar->isWearingWearableType(type)) + if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type)) { return TRUE; } @@ -239,8 +238,10 @@ BOOL LLTexLayerParamAlpha::getSkip() const } +static LLFastTimer::DeclareTimer FTM_TEX_LAYER_PARAM_ALPHA("alpha render"); BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { + LLFastTimer t(FTM_TEX_LAYER_PARAM_ALPHA); BOOL success = TRUE; if (!mTexLayer) @@ -248,7 +249,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) return success; } - F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); BOOL weight_changed = effective_weight != mCachedEffectiveWeight; if (getSkip()) { @@ -290,12 +291,12 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) (mCachedProcessedTexture->getHeight() != image_tga_height) || (weight_changed)) { -// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; mCachedEffectiveWeight = effective_weight; if (!mCachedProcessedTexture) { - mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture(image_tga_width, image_tga_height, 1, FALSE); + llassert(gTextureManagerBridgep); + mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, FALSE); // We now have something in one of our caches LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE; @@ -308,6 +309,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) mStaticImageRaw = new LLImageRaw; mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); mNeedsCreateTexture = TRUE; + lldebugs << "Built Cached Alpha: " << info->mStaticImageFileName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << "Domain: " << info->mDomain << " Weight: " << effective_weight << llendl; } if (mCachedProcessedTexture) @@ -332,7 +334,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Don't keep the cache for other people's avatars // (It's not really a "cache" in that case, but the logic is the same) - if (!mAvatar->isSelf()) + if (!mAvatarAppearance->isSelf()) { mCachedProcessedTexture = NULL; } @@ -402,8 +404,8 @@ LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) : { } -LLTexLayerParamColor::LLTexLayerParamColor(LLVOAvatar *avatar) : - LLTexLayerParam(avatar), +LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) : + LLTexLayerParam(appearance), mAvgDistortionVec(1.f, 1.f, 1.f) { } @@ -425,7 +427,7 @@ LLColor4 LLTexLayerParamColor::getNetColor() const llassert(info->mNumColors >= 1); - F32 effective_weight = (mAvatar && (mAvatar->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); + F32 effective_weight = (mAvatarAppearance && (mAvatarAppearance->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); S32 index_last = info->mNumColors - 1; F32 scaled_weight = effective_weight * index_last; @@ -470,12 +472,12 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake) return; } - if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. { onGlobalColorChanged(upload_bake); if (mTexLayer) { - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); } } diff --git a/indra/newview/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index c812199796..b38d28d3eb 100755..100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -27,14 +27,16 @@ #ifndef LL_LLTEXLAYERPARAMS_H #define LL_LLTEXLAYERPARAMS_H +#include "llpointer.h" +#include "v4color.h" #include "llviewervisualparam.h" +class LLAvatarAppearance; class LLImageRaw; class LLImageTGA; class LLTexLayer; class LLTexLayerInterface; -class LLViewerTexture; -class LLVOAvatar; +class LLGLTexture; class LLWearable; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -45,13 +47,13 @@ class LLTexLayerParam : public LLViewerVisualParam { public: LLTexLayerParam(LLTexLayerInterface *layer); - LLTexLayerParam(LLVOAvatar *avatar); - /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ); + LLTexLayerParam(LLAvatarAppearance *appearance); + /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; protected: LLTexLayerInterface* mTexLayer; - LLVOAvatar* mAvatar; + LLAvatarAppearance* mAvatarAppearance; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -63,7 +65,7 @@ class LLTexLayerParamAlpha : public LLTexLayerParam { public: LLTexLayerParamAlpha( LLTexLayerInterface* layer ); - LLTexLayerParamAlpha( LLVOAvatar* avatar ); + LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); /*virtual*/ ~LLTexLayerParamAlpha(); void* operator new(size_t size) @@ -100,7 +102,7 @@ public: BOOL getMultiplyBlend() const; private: - LLPointer<LLViewerTexture> mCachedProcessedTexture; + LLPointer<LLGLTexture> mCachedProcessedTexture; LLPointer<LLImageTGA> mStaticImageTGA; LLPointer<LLImageRaw> mStaticImageRaw; BOOL mNeedsCreateTexture; @@ -153,7 +155,7 @@ public: }; LLTexLayerParamColor( LLTexLayerInterface* layer ); - LLTexLayerParamColor( LLVOAvatar* avatar ); + LLTexLayerParamColor( LLAvatarAppearance* appearance ); void* operator new(size_t size) { diff --git a/indra/newview/fmodwrapper.cpp b/indra/llappearance/lltexturemanagerbridge.cpp index 16f1d19a78..33f2185e4f 100755..100644 --- a/indra/newview/fmodwrapper.cpp +++ b/indra/llappearance/lltexturemanagerbridge.cpp @@ -1,8 +1,8 @@ -/** - * @file fmodwrapper.cpp - * @brief dummy source file for building a shared library to wrap libfmod.a + /** + * @file lltexturemanagerbridge.cpp + * @brief Defined a null texture manager bridge. Applications must provide their own bridge implementaton. * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -24,14 +24,9 @@ * $/LicenseInfo$ */ -extern "C" -{ - void FSOUND_Init(void); -} +#include "lltexturemanagerbridge.h" + +// Define a null texture manager bridge. Applications must provide their own bridge implementaton. +LLTextureManagerBridge* gTextureManagerBridgep = NULL; + -void* fmodwrapper(void) -{ - // When building the fmodwrapper library, the linker doesn't seem to want to bring in libfmod.a unless I explicitly - // reference at least one symbol in the library. This seemed like the simplest way. - return (void*)&FSOUND_Init; -} diff --git a/indra/llappearance/lltexturemanagerbridge.h b/indra/llappearance/lltexturemanagerbridge.h new file mode 100644 index 0000000000..4b814b522d --- /dev/null +++ b/indra/llappearance/lltexturemanagerbridge.h @@ -0,0 +1,46 @@ +/** + * @file lltexturemanagerbridge.h + * @brief Bridge to an application-specific texture manager. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_TEXTUREMANAGERBRIDGE_H +#define LL_TEXTUREMANAGERBRIDGE_H + +#include "llavatarappearancedefines.h" +#include "llpointer.h" +#include "llgltexture.h" + +// Abstract bridge interface +class LLTextureManagerBridge +{ +public: + virtual LLPointer<LLGLTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0; + virtual LLPointer<LLGLTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0; + virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0; +}; + +extern LLTextureManagerBridge* gTextureManagerBridgep; + +#endif // LL_TEXTUREMANAGERBRIDGE_H + diff --git a/indra/newview/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index f0cf9b7692..cc81bcf118 100755..100644 --- a/indra/newview/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -27,11 +27,10 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "llviewervisualparam.h" #include "llxmltree.h" -#include "llui.h" #include "llwearable.h" //----------------------------------------------------------------------------- diff --git a/indra/newview/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index 2826e6c316..2826e6c316 100755..100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp new file mode 100644 index 0000000000..d86a460511 --- /dev/null +++ b/indra/llappearance/llwearable.cpp @@ -0,0 +1,781 @@ +/** + * @file llwearable.cpp + * @brief LLWearable class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "lllocaltextureobject.h" +#include "lltexlayer.h" +#include "lltexturemanagerbridge.h" +#include "llvisualparam.h" +#include "llavatarappearancedefines.h" +#include "llwearable.h" + +using namespace LLAvatarAppearanceDefines; + +// static +S32 LLWearable::sCurrentDefinitionVersion = 1; + +// Private local functions +static std::string terse_F32_to_string(F32 f); + +// virtual +LLWearable::~LLWearable() +{ +} + +const std::string& LLWearable::getTypeLabel() const +{ + return LLWearableType::getTypeLabel(mType); +} + +const std::string& LLWearable::getTypeName() const +{ + return LLWearableType::getTypeName(mType); +} + +LLAssetType::EType LLWearable::getAssetType() const +{ + return LLWearableType::getAssetType(mType); +} + +BOOL LLWearable::exportFile(LLFILE* fp) const +{ + llofstream ofs(fp); + return exportStream(ofs); +} + +// virtual +BOOL LLWearable::exportStream( std::ostream& output_stream ) const +{ + if (!output_stream.good()) return FALSE; + + // header and version + output_stream << "LLWearable version " << mDefinitionVersion << "\n"; + // name + output_stream << mName << "\n"; + // description + output_stream << mDescription << "\n"; + + // permissions + if( !mPermissions.exportLegacyStream( output_stream ) ) + { + return FALSE; + } + + // sale info + if( !mSaleInfo.exportLegacyStream( output_stream ) ) + { + return FALSE; + } + + // wearable type + output_stream << "type " << (S32) getType() << "\n"; + + // parameters + output_stream << "parameters " << mVisualParamIndexMap.size() << "\n"; + + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + S32 param_id = iter->first; + const LLVisualParam* param = iter->second; + F32 param_weight = param->getWeight(); + output_stream << param_id << " " << terse_F32_to_string( param_weight ) << "\n"; + } + + // texture entries + output_stream << "textures " << mTEMap.size() << "\n"; + + for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + const LLUUID& image_id = iter->second->getID(); + output_stream << te << " " << image_id << "\n"; + } + return TRUE; +} + +void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) +{ + for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) avatarp->getNextVisualParam()) + { + if (param->getWearableType() == mType) + { + LLVisualParam *clone_param = param->cloneParam(this); + clone_param->setParamLocation(LOC_UNKNOWN); + clone_param->setParamLocation(LOC_WEARABLE); + addVisualParam(clone_param); + } + } + + // resync driver parameters to point to the newly cloned driven parameters + for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) + { + LLVisualParam* param = param_iter->second; + LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; + // need this line to disambiguate between versions of LLCharacter::getVisualParam() + LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; + param->resetDrivenParams(); + if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + { + if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true)) + { + llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; + continue; + } + } + } +} + +void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) +{ + LLTexLayerSet *layer_set = NULL; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + + layer_set = avatarp->getAvatarLayerSet(baked_index); + } + + if (layer_set) + { + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + } + else + { + llerrs << "could not find layerset for LTO in wearable!" << llendl; + } +} + +LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp ) +{ + llifstream ifs(fp); + return importStream(ifs, avatarp); +} + +// virtual +LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) +{ + // *NOTE: changing the type or size of this buffer will require + // changes in the fscanf() code below. + // We are using a local max buffer size here to avoid issues + // if MAX_STRING size changes. + const U32 PARSE_BUFFER_SIZE = 2048; + char buffer[PARSE_BUFFER_SIZE]; /* Flawfinder: ignore */ + char uuid_buffer[37]; /* Flawfinder: ignore */ + + // This data is being generated on the viewer. + // Impose some sane limits on parameter and texture counts. + const S32 MAX_WEARABLE_ASSET_TEXTURES = 100; + const S32 MAX_WEARABLE_ASSET_PARAMETERS = 1000; + + if(!avatarp) + { + return LLWearable::FAILURE; + } + + // read header and version + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Failed to read wearable asset input stream." << llendl; + return LLWearable::FAILURE; + } + if ( 1 != sscanf( /* Flawfinder: ignore */ + buffer, + "LLWearable version %d\n", + &mDefinitionVersion ) ) + { + return LLWearable::BAD_HEADER; + } + + // Hack to allow wearables with definition version 24 to still load. + // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 + // the extra check for version == 24 can be removed before release, once internal testers + // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that + // these wearables get re-saved with version definition 22. + if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) + { + llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; + return LLWearable::FAILURE; + } + + // name may be empty + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading name" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mName = buffer; + + // description may be empty + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading description" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mDescription = buffer; + + // permissions may have extra empty lines before the correct line + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading permissions" << llendl; + return LLWearable::FAILURE; + } + S32 perm_version = -1; + if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) || + perm_version != 0 ) + { + llwarns << "Bad Wearable asset: missing valid permissions" << llendl; + return LLWearable::FAILURE; + } + if( !mPermissions.importLegacyStream( input_stream ) ) + { + return LLWearable::FAILURE; + } + + // sale info + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading sale info" << llendl; + return LLWearable::FAILURE; + } + S32 sale_info_version = -1; + if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) || + sale_info_version != 0 ) + { + llwarns << "Bad Wearable asset: missing valid sale_info" << llendl; + return LLWearable::FAILURE; + } + // Sale info used to contain next owner perm. It is now in the + // permissions. Thus, we read that out, and fix legacy + // objects. It's possible this op would fail, but it should pick + // up the vast majority of the tasks. + BOOL has_perm_mask = FALSE; + U32 perm_mask = 0; + if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) ) + { + return LLWearable::FAILURE; + } + if(has_perm_mask) + { + // fair use fix. + if(!(perm_mask & PERM_COPY)) + { + perm_mask |= PERM_TRANSFER; + } + mPermissions.setMaskNext(perm_mask); + } + + // wearable type + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading type" << llendl; + return LLWearable::FAILURE; + } + S32 type = -1; + if ( 1 != sscanf( buffer, "type %d\n", &type ) ) + { + llwarns << "Bad Wearable asset: bad type" << llendl; + return LLWearable::FAILURE; + } + if( 0 <= type && type < LLWearableType::WT_COUNT ) + { + setType((LLWearableType::EType)type, avatarp); + } + else + { + mType = LLWearableType::WT_COUNT; + llwarns << "Bad Wearable asset: bad type #" << type << llendl; + return LLWearable::FAILURE; + } + + // parameters header + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading parameters header" << llendl; + return LLWearable::FAILURE; + } + S32 num_parameters = -1; + if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) ) + { + llwarns << "Bad Wearable asset: missing parameters block" << llendl; + return LLWearable::FAILURE; + } + if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS ) + { + llwarns << "Bad Wearable asset: too many parameters, " + << num_parameters << llendl; + return LLWearable::FAILURE; + } + if( num_parameters != mVisualParamIndexMap.size() ) + { + llwarns << "Wearable parameter mismatch. Reading in " + << num_parameters << " from file, but created " + << mVisualParamIndexMap.size() + << " from avatar parameters. type: " + << getType() << llendl; + } + + // parameters + S32 i; + for( i = 0; i < num_parameters; i++ ) + { + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading parameter #" << i << llendl; + return LLWearable::FAILURE; + } + S32 param_id = 0; + F32 param_weight = 0.f; + if ( 2 != sscanf( buffer, "%d %f\n", ¶m_id, ¶m_weight ) ) + { + llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; + return LLWearable::FAILURE; + } + mSavedVisualParamMap[param_id] = param_weight; + } + + // textures header + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading textures header" << i << llendl; + return LLWearable::FAILURE; + } + S32 num_textures = -1; + if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) ) + { + llwarns << "Bad Wearable asset: missing textures block" << llendl; + return LLWearable::FAILURE; + } + if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES ) + { + llwarns << "Bad Wearable asset: too many textures, " + << num_textures << llendl; + return LLWearable::FAILURE; + } + + // textures + for( i = 0; i < num_textures; i++ ) + { + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading textures #" << i << llendl; + return LLWearable::FAILURE; + } + S32 te = 0; + if ( 2 != sscanf( /* Flawfinder: ignore */ + buffer, + "%d %36s\n", + &te, uuid_buffer) ) + { + llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; + return LLWearable::FAILURE; + } + + if( !LLUUID::validate( uuid_buffer ) ) + { + llwarns << "Bad Wearable asset: bad texture uuid: " + << uuid_buffer << llendl; + return LLWearable::FAILURE; + } + LLUUID id = LLUUID(uuid_buffer); + LLGLTexture* image = gTextureManagerBridgep->getFetchedTexture( id ); + if( mTEMap.find(te) != mTEMap.end() ) + { + delete mTEMap[te]; + } + if( mSavedTEMap.find(te) != mSavedTEMap.end() ) + { + delete mSavedTEMap[te]; + } + + LLUUID textureid(uuid_buffer); + mTEMap[te] = new LLLocalTextureObject(image, textureid); + mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); + createLayers(te, avatarp); + } + + // copy all saved param values to working params + revertValues(); + + return LLWearable::SUCCESS; +} + +BOOL LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size) +{ + if (!input_stream.good()) + { + return FALSE; + } + + do + { + input_stream.getline(buffer, buffer_size); + } + while (input_stream.good() && buffer[0]=='\0'); + + return (buffer[0] != '\0'); +} + + +void LLWearable::setType(LLWearableType::EType type, LLAvatarAppearance *avatarp) +{ + mType = type; + createVisualParams(avatarp); +} + + +LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) +{ + te_map_t::iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const +{ + te_map_t::const_iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + const LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +std::vector<LLLocalTextureObject*> LLWearable::getLocalTextureListSeq() +{ + std::vector<LLLocalTextureObject*> result; + + for(te_map_t::const_iterator iter = mTEMap.begin(); + iter != mTEMap.end(); iter++) + { + LLLocalTextureObject* lto = iter->second; + result.push_back(lto); + } + + return result; +} + +void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) +{ + if( mTEMap.find(index) != mTEMap.end() ) + { + mTEMap.erase(index); + } + mTEMap[index] = new LLLocalTextureObject(lto); +} + +void LLWearable::revertValues() +{ + // FIXME DRANO - this triggers changes to driven params on avatar, potentially clobbering baked appearance. + + //update saved settings so wearable is no longer dirty + // non-driver params first + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && !dynamic_cast<LLDriverParam*>(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + //then driver params + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && dynamic_cast<LLDriverParam*>(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + // make sure that saved values are sane + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *param = getVisualParam(id); + if( param ) + { + mSavedVisualParamMap[id] = param->getWeight(); + } + } + + syncImages(mSavedTEMap, mTEMap); +} + +void LLWearable::saveValues() +{ + //update saved settings so wearable is no longer dirty + mSavedVisualParamMap.clear(); + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + mSavedVisualParamMap[id] = value; + } + + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + syncImages(mTEMap, mSavedTEMap); +} + +void LLWearable::syncImages(te_map_t &src, te_map_t &dst) +{ + // Deep copy of src (copies only those tes that are current, filling in defaults where needed) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src.find(te); + LLUUID image_id; + LLGLTexture *image = NULL; + LLLocalTextureObject *lto = NULL; + if(iter != src.end()) + { + // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. + lto = iter->second; + image = lto->getImage(); + image_id = lto->getID(); + } + else + { + // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. + image_id = getDefaultTextureImageID((ETextureIndex) te); + image = gTextureManagerBridgep->getFetchedTexture( image_id ); + } + + if( dst.find(te) != dst.end() ) + { + // there's already an entry in the destination map for the texture. Just update its values. + dst[te]->setImage(image); + dst[te]->setID(image_id); + } + else + { + // no entry found in the destination map, we need to create a new Local Texture Object + dst[te] = new LLLocalTextureObject(image, image_id); + } + + if( lto ) + { + // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. + dst[te]->setBakedReady(lto->getBakedReady()); + dst[te]->setDiscard(lto->getDiscard()); + } + } + } +} + +void LLWearable::destroyTextures() +{ + for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mTEMap.clear(); + for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mSavedTEMap.clear(); +} + +void LLWearable::addVisualParam(LLVisualParam *param) +{ + if( mVisualParamIndexMap[param->getID()] ) + { + delete mVisualParamIndexMap[param->getID()]; + } + param->setIsDummy(FALSE); + param->setParamLocation(LOC_WEARABLE); + mVisualParamIndexMap[param->getID()] = param; + mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); +} + + +void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + wearable_param->setWeight(value, upload_bake); + } + else + { + llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } +} + +F32 LLWearable::getVisualParamWeight(S32 param_index) const +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; + return wearable_param->getWeight(); + } + else + { + llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } + return (F32)-1.0; +} + +LLVisualParam* LLWearable::getVisualParam(S32 index) const +{ + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); + return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; +} + + +void LLWearable::getVisualParams(visual_param_vec_t &list) +{ + visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); + + // add all visual params to the passed-in vector + for( ; iter != end; ++iter ) + { + list.push_back(iter->second); + } +} + +void LLWearable::animateParams(F32 delta, BOOL upload_bake) +{ + for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + LLVisualParam *param = (LLVisualParam*) iter->second; + param->animate(delta, upload_bake); + } +} + +LLColor4 LLWearable::getClothesColor(S32 te) const +{ + LLColor4 color; + U32 param_name[3]; + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + color.mV[index] = getVisualParamWeight(param_name[index]); + } + } + return color; +} + +void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) +{ + U32 param_name[3]; + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake); + } + } +} + +void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) +{ + if (!avatarp) return; + + // Pull params + for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + { + // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the + // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. + if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) + { + S32 param_id = param->getID(); + F32 weight = getVisualParamWeight(param_id); + + avatarp->setVisualParamWeight( param_id, weight, FALSE ); + } + } +} + + +std::string terse_F32_to_string(F32 f) +{ + std::string r = llformat("%.2f", f); + S32 len = r.length(); + + // "1.20" -> "1.2" + // "24.00" -> "24." + while (len > 0 && ('0' == r[len - 1])) + { + r.erase(len-1, 1); + len--; + } + if ('.' == r[len - 1]) + { + // "24." -> "24" + r.erase(len-1, 1); + } + else if (('-' == r[0]) && ('0' == r[1])) + { + // "-0.59" -> "-.59" + r.erase(1, 1); + } + else if ('0' == r[0]) + { + // "0.59" -> ".59" + r.erase(0, 1); + } + return r; +} + diff --git a/indra/newview/llwearable.h b/indra/llappearance/llwearable.h index 3d8c53a755..6f5a1e14e8 100755..100644 --- a/indra/newview/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -27,31 +27,25 @@ #ifndef LL_LLWEARABLE_H #define LL_LLWEARABLE_H -#include "lluuid.h" -#include "llstring.h" +#include "llavatarappearancedefines.h" +#include "llextendedstatus.h" #include "llpermissions.h" #include "llsaleinfo.h" -#include "llassetstorage.h" #include "llwearabletype.h" -#include "llfile.h" #include "lllocaltextureobject.h" -class LLViewerInventoryItem; +class LLMD5; class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; +class LLAvatarAppearance; +// Abstract class. class LLWearable { - friend class LLWearableList; - //-------------------------------------------------------------------- // Constructors and destructors //-------------------------------------------------------------------- -private: - // Private constructors used by LLWearableList - LLWearable(const LLTransactionID& transactionID); - LLWearable(const LLAssetID& assetID); public: virtual ~LLWearable(); @@ -59,11 +53,8 @@ public: // Accessors //-------------------------------------------------------------------- public: - const LLUUID& getItemID() const; - const LLAssetID& getAssetID() const { return mAssetID; } - const LLTransactionID& getTransactionID() const { return mTransactionID; } - LLWearableType::EType getType() const { return mType; } - void setType(LLWearableType::EType type); + LLWearableType::EType getType() const { return mType; } + void setType(LLWearableType::EType type, LLAvatarAppearance *avatarp); const std::string& getName() const { return mName; } void setName(const std::string& name) { mName = name; } const std::string& getDescription() const { return mDescription; } @@ -77,32 +68,26 @@ public: LLAssetType::EType getAssetType() const; S32 getDefinitionVersion() const { return mDefinitionVersion; } void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; } + static S32 getCurrentDefinitionVersion() { return LLWearable::sCurrentDefinitionVersion; } public: typedef std::vector<LLVisualParam*> visual_param_vec_t; - BOOL isDirty() const; - BOOL isOldVersion() const; - - void writeToAvatar(); - void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); } - static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); + virtual void writeToAvatar(LLAvatarAppearance* avatarp); + enum EImportResult + { + FAILURE = 0, + SUCCESS, + BAD_HEADER + }; BOOL exportFile(LLFILE* file) const; - BOOL importFile(LLFILE* file); - - void setParamsToDefaults(); - void setTexturesToDefaults(); - - void saveNewAsset() const; - static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); - - void copyDataFrom(const LLWearable* src); + EImportResult importFile(LLFILE* file, LLAvatarAppearance* avatarp ); + virtual BOOL exportStream( std::ostream& output_stream ) const; + virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } - - friend std::ostream& operator<<(std::ostream &s, const LLWearable &w); - void setItemID(const LLUUID& item_id); + virtual LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const = 0; LLLocalTextureObject* getLocalTextureObject(S32 index); const LLLocalTextureObject* getLocalTextureObject(S32 index) const; @@ -110,7 +95,6 @@ public: void setLocalTextureObject(S32 index, LLLocalTextureObject <o); void addVisualParam(LLVisualParam *param); - void setVisualParams(); void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); F32 getVisualParamWeight(S32 index) const; LLVisualParam* getVisualParam(S32 index) const; @@ -120,27 +104,22 @@ public: LLColor4 getClothesColor(S32 te) const; void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); - void revertValues(); - void saveValues(); - void pullCrossWearableValues(); + virtual void revertValues(); + virtual void saveValues(); - BOOL isOnTop() const; + // Something happened that requires the wearable to be updated (e.g. worn/unworn). + virtual void setUpdated() const = 0; - // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). - void setLabelUpdated() const; + // Update the baked texture hash. + virtual void addToBakedTextureHash(LLMD5& hash) const = 0; - // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, - // not the wearable asset itself. - void refreshName(); - -private: +protected: typedef std::map<S32, LLLocalTextureObject*> te_map_t; - typedef std::map<S32, LLVisualParam *> visual_param_index_map_t; - - void createLayers(S32 te); - void createVisualParams(); void syncImages(te_map_t &src, te_map_t &dst); - void destroyTextures(); + void destroyTextures(); + void createVisualParams(LLAvatarAppearance *avatarp); + void createLayers(S32 te, LLAvatarAppearance *avatarp); + BOOL getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. @@ -148,18 +127,16 @@ private: std::string mDescription; LLPermissions mPermissions; LLSaleInfo mSaleInfo; - LLAssetID mAssetID; - LLTransactionID mTransactionID; LLWearableType::EType mType; typedef std::map<S32, F32> param_map_t; param_map_t mSavedVisualParamMap; // last saved version of visual params + typedef std::map<S32, LLVisualParam *> visual_param_index_map_t; visual_param_index_map_t mVisualParamIndexMap; te_map_t mTEMap; // maps TE to LocalTextureObject te_map_t mSavedTEMap; // last saved version of TEMap - LLUUID mItemID; // ID of the inventory item in the agent's inventory }; #endif // LL_LLWEARABLE_H diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp new file mode 100644 index 0000000000..68fdcca782 --- /dev/null +++ b/indra/llappearance/llwearabledata.cpp @@ -0,0 +1,360 @@ +/** + * @file llwearabledata.cpp + * @brief LLWearableData class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llwearabledata.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "lldriverparam.h" +#include "llmd5.h" + +LLWearableData::LLWearableData() : + mAvatarAppearance(NULL) +{ +} + +// virtual +LLWearableData::~LLWearableData() +{ +} + +using namespace LLAvatarAppearanceDefines; + +LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) +{ + LLWearable *old_wearable = getWearable(type,index); + if (!old_wearable) + { + pushWearable(type,wearable); + return; + } + + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + llwarns << "invalid type, type " << type << " index " << index << llendl; + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + llwarns << "invalid index, type " << type << " index " << index << llendl; + } + else + { + wearable_vec[index] = wearable; + old_wearable->setUpdated(); + const BOOL removed = FALSE; + wearableUpdated(wearable, removed); + } +} + +U32 LLWearableData::pushWearable(const LLWearableType::EType type, + LLWearable *wearable, + bool trigger_updated /* = true */) +{ + if (wearable == NULL) + { + // no null wearables please! + llwarns << "Null wearable sent for type " << type << llendl; + return MAX_CLOTHING_PER_TYPE; + } + if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) + { + mWearableDatas[type].push_back(wearable); + if (trigger_updated) + { + const BOOL removed = FALSE; + wearableUpdated(wearable, removed); + } + return mWearableDatas[type].size()-1; + } + return MAX_CLOTHING_PER_TYPE; +} + +// virtual +void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed) +{ + wearable->setUpdated(); + // FIXME DRANO avoid updating params via wearables when rendering server-baked appearance. +#if 0 + if (mAvatarAppearance->isUsingServerBakes() && !mAvatarAppearance->isUsingLocalAppearance()) + { + return; + } +#endif + if (!removed) + { + pullCrossWearableValues(wearable->getType()); + } +} + +void LLWearableData::popWearable(LLWearable *wearable) +{ + if (wearable == NULL) + { + // nothing to do here. move along. + return; + } + + U32 index = getWearableIndex(wearable); + const LLWearableType::EType type = wearable->getType(); + + if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type)) + { + popWearable(type, index); + } +} + +void LLWearableData::popWearable(const LLWearableType::EType type, U32 index) +{ + LLWearable *wearable = getWearable(type, index); + if (wearable) + { + mWearableDatas[type].erase(mWearableDatas[type].begin() + index); + const BOOL removed = TRUE; + wearableUpdated(wearable, removed); + } +} + +void LLWearableData::clearWearableType(const LLWearableType::EType type) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + wearable_vec.clear(); +} + +bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return false; + } + + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (0 > index_a || index_a >= wearable_vec.size()) return false; + if (0 > index_b || index_b >= wearable_vec.size()) return false; + + LLWearable* wearable = wearable_vec[index_a]; + wearable_vec[index_a] = wearable_vec[index_b]; + wearable_vec[index_b] = wearable; + return true; +} + +void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type) +{ + llassert(mAvatarAppearance); + // scan through all of the avatar's visual parameters + for (LLViewerVisualParam* param = (LLViewerVisualParam*) mAvatarAppearance->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) mAvatarAppearance->getNextVisualParam()) + { + if( param ) + { + LLDriverParam *driver_param = dynamic_cast<LLDriverParam*>(param); + if(driver_param) + { + // parameter is a driver parameter, have it update its cross-driven params + driver_param->updateCrossDrivenParams(type); + } + } + } +} + + +U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const +{ + if (wearable == NULL) + { + return MAX_CLOTHING_PER_TYPE; + } + + const LLWearableType::EType type = wearable->getType(); + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + llwarns << "tried to get wearable index with an invalid type!" << llendl; + return MAX_CLOTHING_PER_TYPE; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + for(U32 index = 0; index < wearable_vec.size(); index++) + { + if (wearable_vec[index] == wearable) + { + return index; + } + } + + return MAX_CLOTHING_PER_TYPE; +} + +BOOL LLWearableData::isOnTop(LLWearable* wearable) const +{ + if (!wearable) return FALSE; + const LLWearableType::EType type = wearable->getType(); + return ( getTopWearable(type) == wearable ); +} + +const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return 0; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + return wearable_vec.size(); +} + +U32 LLWearableData::getWearableCount(const U32 tex_index) const +{ + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); + return getWearableCount(wearable_type); +} + +LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, + BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache +{ + LLUUID hash_id; + bool hash_computed = false; + LLMD5 hash; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); + + for (U8 i=0; i < baked_dict->mWearables.size(); i++) + { + const LLWearableType::EType baked_type = baked_dict->mWearables[i]; + const U32 num_wearables = getWearableCount(baked_type); + for (U32 index = 0; index < num_wearables; ++index) + { + const LLWearable* wearable = getWearable(baked_type,index); + if (wearable) + { + wearable->addToBakedTextureHash(hash); + hash_computed = true; + } + } + } + if (hash_computed) + { + hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES); + + if (!generate_valid_hash) + { + invalidateBakedTextureHash(hash); + } + hash.finalize(); + hash.raw_digest(hash_id.mData); + } + + return hash_id; +} + + diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h new file mode 100644 index 0000000000..03bd179f25 --- /dev/null +++ b/indra/llappearance/llwearabledata.h @@ -0,0 +1,109 @@ +/** + * @file llwearabledata.h + * @brief LLWearableData class header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_WEARABLEDATA_H +#define LL_WEARABLEDATA_H + +#include "llavatarappearancedefines.h" +#include "llwearable.h" +#include "llerror.h" + +class LLAvatarAppearance; + +class LLWearableData +{ + // *TODO: Figure out why this is causing compile error. + //LOG_CLASS(LLWearableData); + + //-------------------------------------------------------------------- + // Constructors / destructors / Initializers + //-------------------------------------------------------------------- +public: + LLWearableData(); + virtual ~LLWearableData(); + + void setAvatarAppearance(LLAvatarAppearance* appearance) { mAvatarAppearance = appearance; } + +protected: + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; + LLWearable* getTopWearable(const LLWearableType::EType type); + const LLWearable* getTopWearable(const LLWearableType::EType type) const; + LLWearable* getBottomWearable(const LLWearableType::EType type); + const LLWearable* getBottomWearable(const LLWearableType::EType type) const; + U32 getWearableCount(const LLWearableType::EType type) const; + U32 getWearableCount(const U32 tex_index) const; + U32 getWearableIndex(const LLWearable *wearable) const; + + BOOL isOnTop(LLWearable* wearable) const; + + static const U32 MAX_CLOTHING_PER_TYPE = 5; + + //-------------------------------------------------------------------- + // Setters + //-------------------------------------------------------------------- +protected: + // Low-level data structure setter - public access is via setWearableItem, etc. + void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); + U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable, + bool trigger_updated = true); + virtual void wearableUpdated(LLWearable *wearable, BOOL removed); + void popWearable(LLWearable *wearable); + void popWearable(const LLWearableType::EType type, U32 index); + void clearWearableType(const LLWearableType::EType type); + bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b); + +private: + void pullCrossWearableValues(const LLWearableType::EType type); + + //-------------------------------------------------------------------- + // Server Communication + //-------------------------------------------------------------------- +public: + LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, + BOOL generate_valid_hash = TRUE); +protected: + virtual void invalidateBakedTextureHash(LLMD5& hash) const {} + + //-------------------------------------------------------------------- + // Member variables + //-------------------------------------------------------------------- +protected: + LLAvatarAppearance* mAvatarAppearance; + typedef std::vector<LLWearable*> wearableentry_vec_t; // all wearables of a certain type (EG all shirts) + typedef std::map<LLWearableType::EType, wearableentry_vec_t> wearableentry_map_t; // wearable "categories" arranged by wearable type + wearableentry_map_t mWearableDatas; + +}; + + + +#endif // LL_WEARABLEDATA_H + diff --git a/indra/newview/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index c090ab5c3d..618e2a1941 100755..100644 --- a/indra/newview/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -24,23 +24,35 @@ * $/LicenseInfo$ */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h" #include "llwearabletype.h" -#include "llinventoryfunctions.h" -#include "lltrans.h" +#include "llinventorytype.h" + +static LLTranslationBridge* sTrans = NULL; + +// static +void LLWearableType::initClass(LLTranslationBridge* trans) +{ + sTrans = trans; +} + +void LLWearableType::cleanupClass() +{ + delete sTrans; +} struct WearableEntry : public LLDictionaryEntry { WearableEntry(const std::string &name, const std::string& default_new_name, LLAssetType::EType assetType, - LLInventoryIcon::EIconName iconName, + LLInventoryType::EIconName iconName, BOOL disable_camera_switch = FALSE, BOOL allow_multiwear = TRUE) : LLDictionaryEntry(name), mAssetType(assetType), mDefaultNewName(default_new_name), - mLabel(LLTrans::getString(name)), + mLabel(sTrans->getString(name)), mIconName(iconName), mDisableCameraSwitch(disable_camera_switch), mAllowMultiwear(allow_multiwear) @@ -50,7 +62,7 @@ struct WearableEntry : public LLDictionaryEntry const LLAssetType::EType mAssetType; const std::string mLabel; const std::string mDefaultNewName; //keep mLabel for backward compatibility - LLInventoryIcon::EIconName mIconName; + LLInventoryType::EIconName mIconName; BOOL mDisableCameraSwitch; BOOL mAllowMultiwear; }; @@ -64,26 +76,26 @@ public: LLWearableDictionary::LLWearableDictionary() { - addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); - addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); - - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - - addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); - addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); + addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); + + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); + + addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); } // static @@ -131,7 +143,7 @@ LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) } // static -LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType type) +LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type) { const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); const WearableEntry *entry = dict->lookup(type); diff --git a/indra/newview/llwearabletype.h b/indra/llappearance/llwearabletype.h index d633b4807e..e51e6731d3 100755..100644 --- a/indra/newview/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -29,9 +29,16 @@ #include "llassettype.h" #include "lldictionary.h" -#include "llinventoryicon.h" +#include "llinventorytype.h" #include "llsingleton.h" +class LLTranslationBridge +{ +public: + virtual std::string getString(const std::string &xml_desc) = 0; +}; + + class LLWearableType { public: @@ -59,12 +66,15 @@ public: WT_NONE = -1, }; + static void initClass(LLTranslationBridge* trans); // initializes static members + static void cleanupClass(); // initializes static members + static const std::string& getTypeName(EType type); static const std::string& getTypeDefaultNewName(EType type); static const std::string& getTypeLabel(EType type); static LLAssetType::EType getAssetType(EType type); static EType typeNameToType(const std::string& type_name); - static LLInventoryIcon::EIconName getIconName(EType type); + static LLInventoryType::EIconName getIconName(EType type); static BOOL getDisableCameraSwitch(EType type); static BOOL getAllowMultiwear(EType type); diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 632e5d46e3..1b2bdb9888 100755 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -5,7 +5,7 @@ project(llaudio) include(00-Common) include(Audio) include(LLAudio) -include(FMOD) +include(FMODEX) include(OPENAL) include(LLCommon) include(LLMath) @@ -24,7 +24,6 @@ include_directories( ${VORBIS_INCLUDE_DIRS} ${OPENAL_LIB_INCLUDE_DIRS} ${FREEAULT_LIB_INCLUDE_DIRS} - ${FMOD_INCLUDE_DIR} ) set(llaudio_SOURCE_FILES @@ -44,29 +43,22 @@ set(llaudio_HEADER_FILES llwindgen.h ) -if (FMOD) +if (FMODEX) include_directories( - ${FMOD_INCLUDE_DIR} + ${FMODEX_INCLUDE_DIR} ) - list(APPEND llaudio_SOURCE_FILES - llaudioengine_fmod.cpp - lllistener_fmod.cpp - llstreamingaudio_fmod.cpp + llaudioengine_fmodex.cpp + lllistener_fmodex.cpp + llstreamingaudio_fmodex.cpp ) list(APPEND llaudio_HEADER_FILES - llaudioengine_fmod.h - lllistener_fmod.h - llstreamingaudio_fmod.h + llaudioengine_fmodex.h + lllistener_fmodex.h + llstreamingaudio_fmodex.h ) - - if (LINUX OR DARWIN) - set_source_files_properties(llaudioengine_fmod.cpp - llstreamingaudio_fmod.cpp - COMPILE_FLAGS -Wno-write-strings) - endif (LINUX OR DARWIN) -endif (FMOD) +endif (FMODEX) if (OPENAL) list(APPEND llaudio_SOURCE_FILES @@ -88,6 +80,10 @@ list(APPEND llaudio_SOURCE_FILES ${llaudio_HEADER_FILES}) add_library (llaudio ${llaudio_SOURCE_FILES}) target_link_libraries( llaudio + ${LLCOMMON_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLVFS_LIBRARIES} ${VORBISENC_LIBRARIES} ${VORBISFILE_LIBRARIES} ${VORBIS_LIBRARIES} diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 99b96c3c38..da1629a1db 100755 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -42,7 +42,6 @@ #include "lllistener.h" const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; -const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f; diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp deleted file mode 100755 index a40de9fa68..0000000000 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ /dev/null @@ -1,781 +0,0 @@ -/** - * @file audioengine_fmod.cpp - * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llstreamingaudio.h" -#include "llstreamingaudio_fmod.h" - -#include "llaudioengine_fmod.h" -#include "lllistener_fmod.h" - -#include "llerror.h" -#include "llmath.h" -#include "llrand.h" - -#include "fmod.h" -#include "fmod_errors.h" -#include "lldir.h" -#include "llapr.h" - -#include "sound_ids.h" - - -extern "C" { - void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); -} - - -LLAudioEngine_FMOD::LLAudioEngine_FMOD() -{ - mInited = false; - mWindGen = NULL; - mWindDSP = NULL; -} - - -LLAudioEngine_FMOD::~LLAudioEngine_FMOD() -{ -} - - -bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) -{ - LLAudioEngine::init(num_channels, userdata); - - // Reserve one extra channel for the http stream. - if (!FSOUND_SetMinHardwareChannels(num_channels + 1)) - { - LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL; - - F32 version = FSOUND_GetVersion(); - if (version < FMOD_VERSION) - { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version - << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; - //return false; - } - - U32 fmod_flags = 0x0; - -#if LL_WINDOWS - // Windows needs to know which window is frontmost. - // This must be called before FSOUND_Init() per the FMOD docs. - // This could be used to let FMOD handle muting when we lose focus, - // but we don't actually want to do that because we want to distinguish - // between minimized and not-focused states. - if (!FSOUND_SetHWND(userdata)) - { - LL_WARNS("AppInit") << "Error setting FMOD window: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - return false; - } - // Play audio when we don't have focus. - // (For example, IM client on top of us.) - // This means we also try to play audio when minimized, - // so we manually handle muting in that case. JC - fmod_flags |= FSOUND_INIT_GLOBALFOCUS; -#endif - -#if LL_LINUX - // initialize the FMOD engine - - // This is a hack to use only FMOD's basic FPU mixer - // when the LL_VALGRIND environmental variable is set, - // otherwise valgrind will fall over on FMOD's MMX detection - if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/ - { - LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL; - FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU); - } - - // If we don't set an output method, Linux FMOD always - // decides on OSS and fails otherwise. So we'll manually - // try ESD, then OSS, then ALSA. - // Why this order? See SL-13250, but in short, OSS emulated - // on top of ALSA is ironically more reliable than raw ALSA. - // Ack, and ESD has more reliable failure modes - but has worse - // latency - than all of them, so wins for now. - bool audio_ok = false; - - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" - << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; - return false; - } - - // On Linux, FMOD causes a SIGPIPE for some netstream error - // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us. - // NOW FIXED in FMOD 3.x since 2006-10-01. - //signal(SIGPIPE, SIG_IGN); - - // We're interested in logging which output method we - // ended up with, for QA purposes. - switch (FSOUND_GetOutput()) - { - case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break; - case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break; - case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; - default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; - }; - -#else // LL_LINUX - - // initialize the FMOD engine - if (!FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_WARNS("AppInit") << "Error initializing FMOD: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - return false; - } - -#endif - - // set up our favourite FMOD-native streaming audio implementation if none has already been added - if (!getStreamingAudioImpl()) // no existing implementation added - setStreamingAudioImpl(new LLStreamingAudio_FMOD()); - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; - - mInited = true; - - return true; -} - - -std::string LLAudioEngine_FMOD::getDriverName(bool verbose) -{ - if (verbose) - { - F32 version = FSOUND_GetVersion(); - return llformat("FMOD version %f", version); - } - else - { - return "FMOD"; - } -} - - -void LLAudioEngine_FMOD::allocateListener(void) -{ - mListenerp = (LLListener *) new LLListener_FMOD(); - if (!mListenerp) - { - llwarns << "Listener creation failed" << llendl; - } -} - - -void LLAudioEngine_FMOD::shutdown() -{ - if (mWindDSP) - { - FSOUND_DSP_SetActive(mWindDSP,false); - FSOUND_DSP_Free(mWindDSP); - } - - stopInternetStream(); - - LLAudioEngine::shutdown(); - - llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl; - FSOUND_Close(); - llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl; - - delete mListenerp; - mListenerp = NULL; -} - - -LLAudioBuffer * LLAudioEngine_FMOD::createBuffer() -{ - return new LLAudioBufferFMOD(); -} - - -LLAudioChannel * LLAudioEngine_FMOD::createChannel() -{ - return new LLAudioChannelFMOD(); -} - - -bool LLAudioEngine_FMOD::initWind() -{ - if (!mWindGen) - { - bool enable; - - switch (FSOUND_GetMixer()) - { - case FSOUND_MIXER_MMXP5: - case FSOUND_MIXER_MMXP6: - case FSOUND_MIXER_QUALITY_MMXP5: - case FSOUND_MIXER_QUALITY_MMXP6: - enable = (typeid(MIXBUFFERFORMAT) == typeid(S16)); - break; - case FSOUND_MIXER_BLENDMODE: - enable = (typeid(MIXBUFFERFORMAT) == typeid(S32)); - break; - case FSOUND_MIXER_QUALITY_FPU: - enable = (typeid(MIXBUFFERFORMAT) == typeid(F32)); - break; - default: - // FSOUND_GetMixer() does not return a valid mixer type on Darwin - LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL; - enable = true; - break; - } - - if (enable) - { - mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate()); - } - else - { - LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL; - } - } - - mNextWindUpdate = 0.0; - - if (mWindGen && !mWindDSP) - { - mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); - } - if (mWindDSP) - { - FSOUND_DSP_SetActive(mWindDSP, true); - return true; - } - - return false; -} - - -void LLAudioEngine_FMOD::cleanupWind() -{ - if (mWindDSP) - { - FSOUND_DSP_SetActive(mWindDSP, false); - FSOUND_DSP_Free(mWindDSP); - mWindDSP = NULL; - } - - delete mWindGen; - mWindGen = NULL; -} - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) -{ - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; - - if (!mEnableWind) - { - return; - } - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards - - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - - // cerr << "Wind update" << endl; - - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - } -} - -/* -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance) -{ - if (!mInited) - { - return; - } - if (mBuffer[source_num]) - { - mMinDistance[source_num] = (F32) distance; - if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) - { - llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance) -{ - if (!mInited) - { - return; - } - if (mBuffer[source_num]) - { - mMaxDistance[source_num] = (F32) distance; - if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) - { - llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist) -{ - *volume = 0; - *freq = 0; - *inside = 0; - *outside = 0; - *orient = LLVector3::zero; - *out_volume = 0; - *min_dist = 0.f; - *max_dist = 0.f; -} - -*/ - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setInternalGain(F32 gain) -{ - if (!mInited) - { - return; - } - - gain = llclamp( gain, 0.0f, 1.0f ); - FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); - - LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); - if ( saimpl ) - { - // fmod likes its streaming audio channel gain re-asserted after - // master volume change. - saimpl->setGain(saimpl->getGain()); - } -} - -// -// LLAudioChannelFMOD implementation -// - -LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0) -{ -} - - -LLAudioChannelFMOD::~LLAudioChannelFMOD() -{ - cleanup(); -} - - -bool LLAudioChannelFMOD::updateBuffer() -{ - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means that we need to actually - // set up the channel for a different buffer. - - LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); - - // Grab the FMOD sample associated with the buffer - FSOUND_SAMPLE *samplep = bufferp->getSample(); - if (!samplep) - { - // This is bad, there should ALWAYS be a sample associated with a legit - // buffer. - llerrs << "No FMOD sample!" << llendl; - return false; - } - - - // Actually play the sound. Start it off paused so we can do all the necessary - // setup. - mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true); - - //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; - } - - // If we have a source for the channel, we need to update its gain. - if (mCurrentSourcep) - { - // SJB: warnings can spam and hurt framerate, disabling - if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f))) - { -// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - - if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF)) - { -// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID() -// << " at " << mCurrentSourcep->getPositionGlobal() << llendl; -// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } - - return true; -} - - -void LLAudioChannelFMOD::update3DPosition() -{ - if (!mChannelID) - { - // We're not actually a live channel (i.e., we're not playing back anything) - return; - } - - LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp; - if (!bufferp) - { - // We don't have a buffer associated with us (should really have been picked up - // by the above if. - return; - } - - if (mCurrentSourcep->isAmbient()) - { - // Ambient sound, don't need to do any positional updates. - bufferp->set3DMode(false); - } - else - { - // Localized sound. Update the position and velocity of the sound. - bufferp->set3DMode(true); - - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV)) - { - LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } -} - - -void LLAudioChannelFMOD::updateLoop() -{ - if (!mChannelID) - { - // May want to clear up the loop/sample counters. - return; - } - - // - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); - if (cur_pos < (U32)mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; -} - - -void LLAudioChannelFMOD::cleanup() -{ - if (!mChannelID) - { - //llinfos << "Aborting cleanup with no channelID." << llendl; - return; - } - - //llinfos << "Cleaning up channel: " << mChannelID << llendl; - if (!FSOUND_StopSound(mChannelID)) - { - LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - - mCurrentBufferp = NULL; - mChannelID = 0; -} - - -void LLAudioChannelFMOD::play() -{ - if (!mChannelID) - { - llwarns << "Playing without a channelID, aborting" << llendl; - return; - } - - if (!FSOUND_SetPaused(mChannelID, false)) - { - llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - getSource()->setPlayedOnce(true); -} - - -void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp) -{ - LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp; - if (!(fmod_channelp->mChannelID && mChannelID)) - { - // Don't have channels allocated to both the master and the slave - return; - } - - U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength(); - // Try to match the position of our sync master - if (!FSOUND_SetCurrentPosition(mChannelID, position)) - { - llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl; - } - - // Start us playing - play(); -} - - -bool LLAudioChannelFMOD::isPlaying() -{ - if (!mChannelID) - { - return false; - } - - return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); -} - - - -// -// LLAudioBufferFMOD implementation -// - - -LLAudioBufferFMOD::LLAudioBufferFMOD() -{ - mSamplep = NULL; -} - - -LLAudioBufferFMOD::~LLAudioBufferFMOD() -{ - if (mSamplep) - { - // Clean up the associated FMOD sample if it exists. - FSOUND_Sample_Free(mSamplep); - mSamplep = NULL; - } -} - - -bool LLAudioBufferFMOD::loadWAV(const std::string& filename) -{ - // Try to open a wav file from disk. This will eventually go away, as we don't - // really want to block doing this. - if (filename.empty()) - { - // invalid filename, abort. - return false; - } - - if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) - { - // File not found, abort. - return false; - } - - if (mSamplep) - { - // If there's already something loaded in this buffer, clean it up. - FSOUND_Sample_Free(mSamplep); - mSamplep = NULL; - } - - // Load up the wav file into an fmod sample -#if LL_WINDOWS - // MikeS. - Loading the sound file manually and then handing it over to FMOD, - // since FMOD uses posix IO internally, - // which doesn't work with unicode file paths. - LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */ - if (sound_file) - { - fseek(sound_file,0,SEEK_END); - U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset - size_t read_count; - fseek(sound_file,0,SEEK_SET); //Seek back to the beginning - char* buffer = new char[file_length]; - llassert(buffer); - read_count = fread((void*)buffer,file_length,1,sound_file);//Load it.. - if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size... - unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY; - //FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL; - mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length); - } - delete[] buffer; - fclose(sound_file); - } -#else - mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0); -#endif - - if (!mSamplep) - { - // We failed to load the file for some reason. - llwarns << "Could not load data '" << filename << "': " - << FMOD_ErrorString(FSOUND_GetError()) << llendl; - - // - // If we EVER want to load wav files provided by end users, we need - // to rethink this! - // - // file is probably corrupt - remove it. - LLFile::remove(filename); - return false; - } - - // Everything went well, return true - return true; -} - - -U32 LLAudioBufferFMOD::getLength() -{ - if (!mSamplep) - { - return 0; - } - - return FSOUND_Sample_GetLength(mSamplep); -} - - -void LLAudioBufferFMOD::set3DMode(bool use3d) -{ - U16 current_mode = FSOUND_Sample_GetMode(mSamplep); - - if (use3d) - { - if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D)))) - { - llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } - else - { - if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D)) - { - llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - - -void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) -{ - // originalbuffer = fmod's original mixbuffer. - // newbuffer = the buffer passed from the previous DSP unit. - // length = length in samples at this mix time. - // userdata = user parameter passed through in FSOUND_DSP_Create. - - LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen = - (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata; - - newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length); - - return newbuffer; -} diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp new file mode 100644 index 0000000000..5ec30c7d1d --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -0,0 +1,746 @@ +/** + * @file audioengine_fmodex.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio + * support as a FMODEX implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llstreamingaudio.h" +#include "llstreamingaudio_fmodex.h" + +#include "llaudioengine_fmodex.h" +#include "lllistener_fmodex.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmod.hpp" +#include "fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); + +FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; + +LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler) +{ + mInited = false; + mWindGen = NULL; + mWindDSP = NULL; + mSystem = NULL; + mEnableProfiler = enable_profiler; +} + + +LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX() +{ +} + + +inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) +{ + if(result == FMOD_OK) + return false; + llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl; + return true; +} + +void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + if(type & FMOD_MEMORY_STREAM_DECODE) + { + llinfos << "Decode buffer size: " << size << llendl; + } + else if(type & FMOD_MEMORY_STREAM_FILE) + { + llinfos << "Strean buffer size: " << size << llendl; + } + return new char[size]; +} +void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + memset(ptr,0,size); + return ptr; +} +void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + delete[] (char*)ptr; +} + +bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) +{ + U32 version; + FMOD_RESULT result; + + LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; + + //result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE); + //if(Check_FMOD_Error(result, "FMOD::Memory_Initialize")) + // return false; + + result = FMOD::System_Create(&mSystem); + if(Check_FMOD_Error(result, "FMOD::System_Create")) + return false; + + //will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer. + LLAudioEngine::init(num_channels, userdata); + + result = mSystem->getVersion(&version); + Check_FMOD_Error(result, "FMOD::System::getVersion"); + + if (version < FMOD_VERSION) + { + LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version + << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; + } + + result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); + Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); + + // In this case, all sounds, PLUS wind and stream will be software. + result = mSystem->setSoftwareChannels(num_channels + 2); + Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); + + U32 fmod_flags = FMOD_INIT_NORMAL; + if(mEnableProfiler) + { + fmod_flags |= FMOD_INIT_ENABLE_PROFILE; + mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]); + mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]); + mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]); + mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]); + } + +#if LL_LINUX + bool audio_ok = false; + + if (!audio_ok) + { + if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "OSS audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; + return false; + } + + // We're interested in logging which output method we + // ended up with, for QA purposes. + FMOD_OUTPUTTYPE output_type; + mSystem->getOutput(&output_type); + switch (output_type) + { + case FMOD_OUTPUTTYPE_NOSOUND: + LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_PULSEAUDIO: + LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_ALSA: + LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_OSS: + LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; + default: + LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; + }; +#else // LL_LINUX + + // initialize the FMOD engine + result = mSystem->init( num_channels + 2, fmod_flags, 0); + if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) + { + /* + Ok, the speaker mode selected isn't supported by this soundcard. Switch it + back to stereo... + */ + result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); + Check_FMOD_Error(result,"Error falling back to stereo mode"); + /* + ... and re-init. + */ + result = mSystem->init( num_channels + 2, fmod_flags, 0); + } + if(Check_FMOD_Error(result, "Error initializing FMOD Ex")) + return false; +#endif + + // set up our favourite FMOD-native streaming audio implementation if none has already been added + if (!getStreamingAudioImpl()) // no existing implementation added + setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); + + LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL; + + int r_numbuffers, r_samplerate, r_channels, r_bits; + unsigned int r_bufferlength; + char r_name[256]; + mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); + mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits); + mSystem->getDriverInfo(0, r_name, 255, 0); + r_name[255] = '\0'; + int latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); + + LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n" + << "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n" + << "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL; + + mInited = true; + + return true; +} + + +std::string LLAudioEngine_FMODEX::getDriverName(bool verbose) +{ + llassert_always(mSystem); + if (verbose) + { + U32 version; + if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) + { + return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); + } + } + return "FMODEx"; +} + + +void LLAudioEngine_FMODEX::allocateListener(void) +{ + mListenerp = (LLListener *) new LLListener_FMODEX(mSystem); + if (!mListenerp) + { + llwarns << "Listener creation failed" << llendl; + } +} + + +void LLAudioEngine_FMODEX::shutdown() +{ + stopInternetStream(); + + llinfos << "About to LLAudioEngine::shutdown()" << llendl; + LLAudioEngine::shutdown(); + + llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl; + mSystem->close(); + mSystem->release(); + llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl; + + delete mListenerp; + mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer() +{ + return new LLAudioBufferFMODEX(mSystem); +} + + +LLAudioChannel * LLAudioEngine_FMODEX::createChannel() +{ + return new LLAudioChannelFMODEX(mSystem); +} + +bool LLAudioEngine_FMODEX::initWind() +{ + mNextWindUpdate = 0.0; + + if (!mWindDSP) + { + FMOD_DSP_DESCRIPTION dspdesc; + memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero + strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit" + dspdesc.channels=2; + dspdesc.read = &windCallback; //Assign callback. + if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP")) + return false; + + if(mWindGen) + delete mWindGen; + + float frequency = 44100; + mWindDSP->getDefaults(&frequency,0,0,0); + mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); + mWindDSP->setUserData((void*)mWindGen); + } + + if (mWindDSP) + { + mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0); + return true; + } + return false; +} + + +void LLAudioEngine_FMODEX::cleanupWind() +{ + if (mWindDSP) + { + mWindDSP->remove(); + mWindDSP->release(); + mWindDSP = NULL; + } + + delete mWindGen; + mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) +{ + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; + + if (!mEnableWind) + { + return; + } + + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { + + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards + + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + // cerr << "Wind update" << endl; + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + } +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODEX::setInternalGain(F32 gain) +{ + if (!mInited) + { + return; + } + + gain = llclamp( gain, 0.0f, 1.0f ); + + FMOD::ChannelGroup *master_group; + mSystem->getMasterChannelGroup(&master_group); + + master_group->setVolume(gain); + + LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); + if ( saimpl ) + { + // fmod likes its streaming audio channel gain re-asserted after + // master volume change. + saimpl->setGain(saimpl->getGain()); + } +} + +// +// LLAudioChannelFMODEX implementation +// + +LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMODEX::~LLAudioChannelFMODEX() +{ + cleanup(); +} + +bool LLAudioChannelFMODEX::updateBuffer() +{ + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the channel for a different buffer. + + LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer(); + + // Grab the FMOD sample associated with the buffer + FMOD::Sound *soundp = bufferp->getSound(); + if (!soundp) + { + // This is bad, there should ALWAYS be a sound associated with a legit + // buffer. + llerrs << "No FMOD sound!" << llendl; + return false; + } + + + // Actually play the sound. Start it off paused so we can do all the necessary + // setup. + if(!mChannelp) + { + FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); + Check_FMOD_Error(result, "FMOD::System::playSound"); + } + + //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; + } + + // If we have a source for the channel, we need to update its gain. + if (mCurrentSourcep) + { + // SJB: warnings can spam and hurt framerate, disabling + //FMOD_RESULT result; + + mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); + //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + + mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) + { + S32 index; + mChannelp->getIndex(&index); + llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() + << " at " << mCurrentSourcep->getPositionGlobal() << llendl; + }*/ + } + + return true; +} + + +void LLAudioChannelFMODEX::update3DPosition() +{ + if (!mChannelp) + { + // We're not actually a live channel (i.e., we're not playing back anything) + return; + } + + LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentBufferp; + if (!bufferp) + { + // We don't have a buffer associated with us (should really have been picked up + // by the above if. + return; + } + + if (mCurrentSourcep->isAmbient()) + { + // Ambient sound, don't need to do any positional updates. + set3DMode(false); + } + else + { + // Localized sound. Update the position and velocity of the sound. + set3DMode(true); + + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); + Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); + } +} + + +void LLAudioChannelFMODEX::updateLoop() +{ + if (!mChannelp) + { + // May want to clear up the loop/sample counters. + return; + } + + // + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + U32 cur_pos; + mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES); + + if (cur_pos < (U32)mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMODEX::cleanup() +{ + if (!mChannelp) + { + //llinfos << "Aborting cleanup with no channel handle." << llendl; + return; + } + + //llinfos << "Cleaning up channel: " << mChannelID << llendl; + Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); + + mCurrentBufferp = NULL; + mChannelp = NULL; +} + + +void LLAudioChannelFMODEX::play() +{ + if (!mChannelp) + { + llwarns << "Playing without a channel handle, aborting" << llendl; + return; + } + + Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + + getSource()->setPlayedOnce(true); + + if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) + mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]); +} + + +void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp) +{ + LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp; + if (!(fmod_channelp->mChannelp && mChannelp)) + { + // Don't have channels allocated to both the master and the slave + return; + } + + U32 cur_pos; + if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) + return; + + cur_pos %= mCurrentBufferp->getLength(); + + // Try to match the position of our sync master + Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position"); + + // Start us playing + play(); +} + + +bool LLAudioChannelFMODEX::isPlaying() +{ + if (!mChannelp) + { + return false; + } + + bool paused, playing; + mChannelp->getPaused(&paused); + mChannelp->isPlaying(&playing); + return !paused && playing; +} + + +// +// LLAudioChannelFMODEX implementation +// + + +LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +{ +} + + +LLAudioBufferFMODEX::~LLAudioBufferFMODEX() +{ + if(mSoundp) + { + mSoundp->release(); + mSoundp = NULL; + } +} + + +bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) +{ + // Try to open a wav file from disk. This will eventually go away, as we don't + // really want to block doing this. + if (filename.empty()) + { + // invalid filename, abort. + return false; + } + + if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) + { + // File not found, abort. + return false; + } + + if (mSoundp) + { + // If there's already something loaded in this buffer, clean it up. + mSoundp->release(); + mSoundp = NULL; + } + + FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE; + FMOD_CREATESOUNDEXINFO exinfo; + memset(&exinfo,0,sizeof(exinfo)); + exinfo.cbsize = sizeof(exinfo); + exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. + // Load up the wav file into an fmod sample +#if LL_WINDOWS + FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp); +#else + FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); +#endif + + if (result != FMOD_OK) + { + // We failed to load the file for some reason. + llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl; + + // + // If we EVER want to load wav files provided by end users, we need + // to rethink this! + // + // file is probably corrupt - remove it. + LLFile::remove(filename); + return false; + } + + // Everything went well, return true + return true; +} + + +U32 LLAudioBufferFMODEX::getLength() +{ + if (!mSoundp) + { + return 0; + } + + U32 length; + mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); + return length; +} + + +void LLAudioChannelFMODEX::set3DMode(bool use3d) +{ + FMOD_MODE current_mode; + if(mChannelp->getMode(¤t_mode) != FMOD_OK) + return; + FMOD_MODE new_mode = current_mode; + new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); + new_mode |= use3d ? FMOD_3D : FMOD_2D; + + if(current_mode != new_mode) + { + mChannelp->setMode(new_mode); + } +} + + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels) +{ + // originalbuffer = fmod's original mixbuffer. + // newbuffer = the buffer passed from the previous DSP unit. + // length = length in samples at this mix time. + // userdata = user parameter passed through in FSOUND_DSP_Create. + + LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen; + FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + + thisdsp->getUserData((void **)&windgen); + S32 channels, configwidth, configheight; + thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight); + + windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); + + return FMOD_OK; +} diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmodex.h index 4582a5d57e..415a9ed0ef 100755..100644 --- a/indra/llaudio/llaudioengine_fmod.h +++ b/indra/llaudio/llaudioengine_fmodex.h @@ -1,7 +1,7 @@ /** - * @file audioengine_fmod.h - * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMOD 3D implementation + * @file audioengine_fmodex.h + * @brief Definition of LLAudioEngine class abstracting the audio + * support as a FMODEX implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code @@ -25,26 +25,33 @@ * $/LicenseInfo$ */ -#ifndef LL_AUDIOENGINE_FMOD_H -#define LL_AUDIOENGINE_FMOD_H +#ifndef LL_AUDIOENGINE_FMODEX_H +#define LL_AUDIOENGINE_FMODEX_H #include "llaudioengine.h" -#include "lllistener_fmod.h" #include "llwindgen.h" -#include "fmod.h" - -class LLAudioStreamManagerFMOD; - -class LLAudioEngine_FMOD : public LLAudioEngine +//Stubs +class LLAudioStreamManagerFMODEX; +namespace FMOD +{ + class System; + class Channel; + class ChannelGroup; + class Sound; + class DSP; +} + +//Interfaces +class LLAudioEngine_FMODEX : public LLAudioEngine { public: - LLAudioEngine_FMOD(); - virtual ~LLAudioEngine_FMOD(); + LLAudioEngine_FMODEX(bool enable_profiler); + virtual ~LLAudioEngine_FMODEX(); // initialization/startup/shutdown virtual bool init(const S32 num_channels, void *user_data); - virtual std::string getDriverName(bool verbose); + virtual std::string getDriverName(bool verbose); virtual void allocateListener(); virtual void shutdown(); @@ -54,38 +61,33 @@ public: /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); -#if LL_DARWIN - typedef S32 MIXBUFFERFORMAT; -#else - typedef S16 MIXBUFFERFORMAT; -#endif + typedef F32 MIXBUFFERFORMAT; + FMOD::System *getSystem() const {return mSystem;} protected: /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. /*virtual*/ void setInternalGain(F32 gain); -protected: - static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); - - //F32 mMinDistance[MAX_BUFFERS]; - //F32 mMaxDistance[MAX_BUFFERS]; bool mInited; - // On Windows, userdata is the HWND of the application window. - void* mUserData; - LLWindGen<MIXBUFFERFORMAT> *mWindGen; - FSOUND_DSPUNIT *mWindDSP; + + FMOD::DSP *mWindDSP; + FMOD::System *mSystem; + bool mEnableProfiler; + +public: + static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT]; }; -class LLAudioChannelFMOD : public LLAudioChannel +class LLAudioChannelFMODEX : public LLAudioChannel { public: - LLAudioChannelFMOD(); - virtual ~LLAudioChannelFMOD(); + LLAudioChannelFMODEX(FMOD::System *audioengine); + virtual ~LLAudioChannelFMODEX(); protected: /*virtual*/ void play(); @@ -97,28 +99,30 @@ protected: /*virtual*/ void update3DPosition(); /*virtual*/ void updateLoop(); + void set3DMode(bool use3d); protected: - int mChannelID; + FMOD::System *getSystem() const {return mSystemp;} + FMOD::System *mSystemp; + FMOD::Channel *mChannelp; S32 mLastSamplePos; }; -class LLAudioBufferFMOD : public LLAudioBuffer +class LLAudioBufferFMODEX : public LLAudioBuffer { public: - LLAudioBufferFMOD(); - virtual ~LLAudioBufferFMOD(); + LLAudioBufferFMODEX(FMOD::System *audioengine); + virtual ~LLAudioBufferFMODEX(); /*virtual*/ bool loadWAV(const std::string& filename); /*virtual*/ U32 getLength(); - friend class LLAudioChannelFMOD; - - void set3DMode(bool use3d); -protected: - FSOUND_SAMPLE *getSample() { return mSamplep; } + friend class LLAudioChannelFMODEX; protected: - FSOUND_SAMPLE *mSamplep; + FMOD::System *getSystem() const {return mSystemp;} + FMOD::System *mSystemp; + FMOD::Sound *getSound() const{ return mSoundp; } + FMOD::Sound *mSoundp; }; -#endif // LL_AUDIOENGINE_FMOD_H +#endif // LL_AUDIOENGINE_FMODEX_H diff --git a/indra/llaudio/lllistener_fmod.cpp b/indra/llaudio/lllistener_fmodex.cpp index 0138f4345e..2509a7aebc 100755..100644 --- a/indra/llaudio/lllistener_fmod.cpp +++ b/indra/llaudio/lllistener_fmodex.cpp @@ -1,7 +1,7 @@ /** - * @file listener_fmod.cpp - * @brief implementation of LISTENER class abstracting the audio - * support as a FMOD 3D implementation (windows only) + * @file listener_fmodex.cpp + * @brief Implementation of LISTENER class abstracting the audio + * support as a FMODEX implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code @@ -27,24 +27,25 @@ #include "linden_common.h" #include "llaudioengine.h" -#include "lllistener_fmod.h" -#include "fmod.h" +#include "lllistener_fmodex.h" +#include "fmod.hpp" //----------------------------------------------------------------------- // constructor //----------------------------------------------------------------------- -LLListener_FMOD::LLListener_FMOD() +LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system) { + mSystem = system; init(); } //----------------------------------------------------------------------- -LLListener_FMOD::~LLListener_FMOD() +LLListener_FMODEX::~LLListener_FMODEX() { } //----------------------------------------------------------------------- -void LLListener_FMOD::init(void) +void LLListener_FMODEX::init(void) { // do inherited LLListener::init(); @@ -53,31 +54,31 @@ void LLListener_FMOD::init(void) } //----------------------------------------------------------------------- -void LLListener_FMOD::translate(LLVector3 offset) +void LLListener_FMODEX::translate(LLVector3 offset) { LLListener::translate(offset); - FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); } //----------------------------------------------------------------------- -void LLListener_FMOD::setPosition(LLVector3 pos) +void LLListener_FMODEX::setPosition(LLVector3 pos) { LLListener::setPosition(pos); - FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); } //----------------------------------------------------------------------- -void LLListener_FMOD::setVelocity(LLVector3 vel) +void LLListener_FMODEX::setVelocity(LLVector3 vel) { LLListener::setVelocity(vel); - FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); + mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); } //----------------------------------------------------------------------- -void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) +void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at) { LLListener::orient(up, at); @@ -87,37 +88,46 @@ void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed at = -at; - FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); + mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); } //----------------------------------------------------------------------- -void LLListener_FMOD::commitDeferredChanges() +void LLListener_FMODEX::commitDeferredChanges() { - FSOUND_Update(); + mSystem->update(); } -void LLListener_FMOD::setRolloffFactor(F32 factor) +void LLListener_FMODEX::setRolloffFactor(F32 factor) { + //An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment. + //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. + //In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call. + if(mRolloffFactor != factor) + { + LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL); + } mRolloffFactor = factor; - FSOUND_3D_SetRolloffFactor(factor); + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); } -F32 LLListener_FMOD::getRolloffFactor() +F32 LLListener_FMODEX::getRolloffFactor() { return mRolloffFactor; } -void LLListener_FMOD::setDopplerFactor(F32 factor) +void LLListener_FMODEX::setDopplerFactor(F32 factor) { mDopplerFactor = factor; - FSOUND_3D_SetDopplerFactor(factor); + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); } -F32 LLListener_FMOD::getDopplerFactor() +F32 LLListener_FMODEX::getDopplerFactor() { return mDopplerFactor; } diff --git a/indra/llaudio/lllistener_fmod.h b/indra/llaudio/lllistener_fmodex.h index 818da05d51..073b65d53a 100755..100644 --- a/indra/llaudio/lllistener_fmod.h +++ b/indra/llaudio/lllistener_fmodex.h @@ -1,5 +1,5 @@ /** - * @file listener_fmod.h + * @file listener_fmodex.h * @brief Description of LISTENER class abstracting the audio support * as an FMOD 3D implementation (windows and Linux) * @@ -25,16 +25,23 @@ * $/LicenseInfo$ */ -#ifndef LL_LISTENER_FMOD_H -#define LL_LISTENER_FMOD_H +#ifndef LL_LISTENER_FMODEX_H +#define LL_LISTENER_FMODEX_H #include "lllistener.h" -class LLListener_FMOD : public LLListener +//Stubs +namespace FMOD +{ + class System; +} + +//Interfaces +class LLListener_FMODEX : public LLListener { public: - LLListener_FMOD(); - virtual ~LLListener_FMOD(); + LLListener_FMODEX(FMOD::System *system); + virtual ~LLListener_FMODEX(); virtual void init(); virtual void translate(LLVector3 offset); @@ -47,8 +54,8 @@ class LLListener_FMOD : public LLListener virtual F32 getDopplerFactor(); virtual void setRolloffFactor(F32 factor); virtual F32 getRolloffFactor(); - protected: + FMOD::System *mSystem; F32 mDopplerFactor; F32 mRolloffFactor; }; diff --git a/indra/llaudio/llstreamingaudio.h b/indra/llaudio/llstreamingaudio.h index 20104af744..93479f9d59 100755 --- a/indra/llaudio/llstreamingaudio.h +++ b/indra/llaudio/llstreamingaudio.h @@ -45,6 +45,8 @@ class LLStreamingAudioInterface virtual void setGain(F32 vol) = 0; virtual F32 getGain() = 0; virtual std::string getURL() = 0; + virtual bool supportsAdjustableBufferSizes(){return false;} + virtual void setBufferSizes(U32 streambuffertime, U32 decodebuffertime){}; }; #endif // LL_STREAMINGAUDIO_H diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp index bcdea771a7..4a74267650 100755..100644 --- a/indra/llaudio/llstreamingaudio_fmod.cpp +++ b/indra/llaudio/llstreamingaudio_fmodex.cpp @@ -1,8 +1,8 @@ /** - * @file streamingaudio_fmod.cpp - * @brief LLStreamingAudio_FMOD implementation + * @file streamingaudio_fmodex.cpp + * @brief LLStreamingAudio_FMODEX implementation * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -28,25 +28,27 @@ #include "llmath.h" -#include "fmod.h" +#include "fmod.hpp" #include "fmod_errors.h" -#include "llstreamingaudio_fmod.h" +#include "llstreamingaudio_fmodex.h" -class LLAudioStreamManagerFMOD +class LLAudioStreamManagerFMODEX { public: - LLAudioStreamManagerFMOD(const std::string& url); - int startStream(); + LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url); + FMOD::Channel* startStream(); bool stopStream(); // Returns true if the stream was successfully stopped. bool ready(); const std::string& getURL() { return mInternetStreamURL; } - int getOpenState(); + FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL); protected: - FSOUND_STREAM* mInternetStream; + FMOD::System* mSystem; + FMOD::Channel* mStreamChannel; + FMOD::Sound* mInternetStream; bool mReady; std::string mInternetStreamURL; @@ -57,14 +59,17 @@ protected: //--------------------------------------------------------------------------- // Internet Streaming //--------------------------------------------------------------------------- -LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : +LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) : + mSystem(system), mCurrentInternetStreamp(NULL), - mFMODInternetStreamChannel(-1), + mFMODInternetStreamChannelp(NULL), mGain(1.0f) { // Number of milliseconds of audio to buffer for the audio card. // Must be larger than the usual Second Life frame stutter time. - FSOUND_Stream_SetBufferSize(200); + const U32 buffer_seconds = 10; //sec + const U32 estimated_bitrate = 128; //kbit/sec + mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); // Here's where we set the size of the network buffer and some buffering // parameters. In this case we want a network buffer of 16k, we want it @@ -76,13 +81,13 @@ LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : } -LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD() +LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() { // nothing interesting/safe to do. } -void LLStreamingAudio_FMOD::start(const std::string& url) +void LLStreamingAudio_FMODEX::start(const std::string& url) { //if (!mInited) //{ @@ -96,7 +101,7 @@ void LLStreamingAudio_FMOD::start(const std::string& url) if (!url.empty()) { llinfos << "Starting internet stream: " << url << llendl; - mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url); + mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url); mURL = url; } else @@ -107,13 +112,13 @@ void LLStreamingAudio_FMOD::start(const std::string& url) } -void LLStreamingAudio_FMOD::update() +void LLStreamingAudio_FMODEX::update() { // Kill dead internet streams, if possible - std::list<LLAudioStreamManagerFMOD *>::iterator iter; + std::list<LLAudioStreamManagerFMODEX *>::iterator iter; for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) { - LLAudioStreamManagerFMOD *streamp = *iter; + LLAudioStreamManagerFMODEX *streamp = *iter; if (streamp->stopStream()) { llinfos << "Closed dead stream" << llendl; @@ -132,62 +137,66 @@ void LLStreamingAudio_FMOD::update() return; } - int open_state = mCurrentInternetStreamp->getOpenState(); + unsigned int progress; + bool starving; + bool diskbusy; + FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); - if (!open_state) + if (open_state == FMOD_OPENSTATE_READY) { // Stream is live // start the stream if it's ready - if (mFMODInternetStreamChannel < 0) + if (!mFMODInternetStreamChannelp && + (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) { - mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream(); - - if (mFMODInternetStreamChannel != -1) - { - // Reset volume to previously set volume - setGain(getGain()); - FSOUND_SetPaused(mFMODInternetStreamChannel, false); - } + // Reset volume to previously set volume + setGain(getGain()); + mFMODInternetStreamChannelp->setPaused(false); + mLastStarved.stop(); } } - - switch(open_state) + else if(open_state == FMOD_OPENSTATE_ERROR) { - default: - case 0: - // success - break; - case -1: - // stream handle is invalid - llwarns << "InternetStream - invalid handle" << llendl; stop(); return; - case -2: - // opening - break; - case -3: - // failed to open, file not found, perhaps - llwarns << "InternetStream - failed to open" << llendl; - stop(); - return; - case -4: - // connecting - break; - case -5: - // buffering - break; } + if(mFMODInternetStreamChannelp) + { + FMOD::Sound *sound = NULL; + + if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) + { + if(starving) + { + if(!mLastStarved.getStarted()) + { + llinfos << "Stream starvation detected! Muting stream audio until it clears." << llendl; + llinfos << " (diskbusy="<<diskbusy<<")" << llendl; + llinfos << " (progress="<<progress<<")" << llendl; + mFMODInternetStreamChannelp->setMute(true); + } + mLastStarved.start(); + } + else if(mLastStarved.getStarted() && mLastStarved.getElapsedTimeF32() > 1.f) + { + mLastStarved.stop(); + mFMODInternetStreamChannelp->setMute(false); + } + } + } } -void LLStreamingAudio_FMOD::stop() +void LLStreamingAudio_FMODEX::stop() { - if (mFMODInternetStreamChannel != -1) + mLastStarved.stop(); + + if (mFMODInternetStreamChannelp) { - FSOUND_SetPaused(mFMODInternetStreamChannel, true); - FSOUND_SetPriority(mFMODInternetStreamChannel, 0); - mFMODInternetStreamChannel = -1; + mFMODInternetStreamChannelp->setPaused(true); + mFMODInternetStreamChannelp->setPriority(0); + mFMODInternetStreamChannelp = NULL; } if (mCurrentInternetStreamp) @@ -207,7 +216,7 @@ void LLStreamingAudio_FMOD::stop() } } -void LLStreamingAudio_FMOD::pause(int pauseopt) +void LLStreamingAudio_FMODEX::pause(int pauseopt) { if (pauseopt < 0) { @@ -230,7 +239,7 @@ void LLStreamingAudio_FMOD::pause(int pauseopt) // A stream is "playing" if it has been requested to start. That // doesn't necessarily mean audio is coming out of the speakers. -int LLStreamingAudio_FMOD::isPlaying() +int LLStreamingAudio_FMODEX::isPlaying() { if (mCurrentInternetStreamp) { @@ -247,44 +256,47 @@ int LLStreamingAudio_FMOD::isPlaying() } -F32 LLStreamingAudio_FMOD::getGain() +F32 LLStreamingAudio_FMODEX::getGain() { return mGain; } -std::string LLStreamingAudio_FMOD::getURL() +std::string LLStreamingAudio_FMODEX::getURL() { return mURL; } -void LLStreamingAudio_FMOD::setGain(F32 vol) +void LLStreamingAudio_FMODEX::setGain(F32 vol) { mGain = vol; - if (mFMODInternetStreamChannel != -1) + if (mFMODInternetStreamChannelp) { - vol = llclamp(vol * vol, 0.f, 1.f); - int vol_int = llround(vol * 255.f); - FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int); + vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? + + mFMODInternetStreamChannelp->setVolume(vol); } } - /////////////////////////////////////////////////////// // manager of possibly-multiple internet audio streams -LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : +LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) : + mSystem(system), + mStreamChannel(NULL), mInternetStream(NULL), mReady(false) { mInternetStreamURL = url; - mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); - if (!mInternetStream) + + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_MPEGSEARCH | FMOD_IGNORETAGS, 0, &mInternetStream); + + if (result!= FMOD_OK) { llwarns << "Couldn't open fmod stream, error " - << FMOD_ErrorString(FSOUND_GetError()) + << FMOD_ErrorString(result) << llendl; mReady = false; return; @@ -293,48 +305,42 @@ LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : mReady = true; } -int LLAudioStreamManagerFMOD::startStream() +FMOD::Channel *LLAudioStreamManagerFMODEX::startStream() { // We need a live and opened stream before we try and play it. - if (!mInternetStream || getOpenState()) + if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY) { llwarns << "No internet stream to start playing!" << llendl; - return -1; + return NULL; } - // Make sure the stream is set to 2D mode. - FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); + if(mStreamChannel) + return mStreamChannel; //Already have a channel for this stream. - return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); + mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel); + return mStreamChannel; } -bool LLAudioStreamManagerFMOD::stopStream() +bool LLAudioStreamManagerFMODEX::stopStream() { if (mInternetStream) { - int read_percent = 0; - int status = 0; - int bitrate = 0; - unsigned int flags = 0x0; - FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); + bool close = true; - switch (status) + switch (getOpenState()) { - case FSOUND_STREAM_NET_CONNECTING: + case FMOD_OPENSTATE_CONNECTING: close = false; break; - case FSOUND_STREAM_NET_NOTCONNECTED: - case FSOUND_STREAM_NET_BUFFERING: - case FSOUND_STREAM_NET_READY: - case FSOUND_STREAM_NET_ERROR: default: close = true; } if (close) { - FSOUND_Stream_Close(mInternetStream); + mInternetStream->release(); + mStreamChannel = NULL; mInternetStream = NULL; return true; } @@ -349,8 +355,19 @@ bool LLAudioStreamManagerFMOD::stopStream() } } -int LLAudioStreamManagerFMOD::getOpenState() +FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) +{ + FMOD_OPENSTATE state; + mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); + return state; +} + +void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) { - int open_state = FSOUND_Stream_GetOpenState(mInternetStream); - return open_state; + mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES); + FMOD_ADVANCEDSETTINGS settings; + memset(&settings,0,sizeof(settings)); + settings.cbsize=sizeof(settings); + settings.defaultDecodeBufferSize = decodebuffertime;//ms + mSystem->setAdvancedSettings(&settings); } diff --git a/indra/llaudio/llstreamingaudio_fmod.h b/indra/llaudio/llstreamingaudio_fmodex.h index 9970f0d03b..42b6b3aaa8 100755..100644 --- a/indra/llaudio/llstreamingaudio_fmod.h +++ b/indra/llaudio/llstreamingaudio_fmodex.h @@ -1,9 +1,8 @@ /** - * @file streamingaudio_fmod.h - * @author Tofu Linden - * @brief Definition of LLStreamingAudio_FMOD implementation + * @file streamingaudio_fmodex.h + * @brief Definition of LLStreamingAudio_FMODEX implementation * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -25,20 +24,28 @@ * $/LicenseInfo$ */ -#ifndef LL_STREAMINGAUDIO_FMOD_H -#define LL_STREAMINGAUDIO_FMOD_H +#ifndef LL_STREAMINGAUDIO_FMODEX_H +#define LL_STREAMINGAUDIO_FMODEX_H #include "stdtypes.h" // from llcommon #include "llstreamingaudio.h" +#include "lltimer.h" -class LLAudioStreamManagerFMOD; +//Stubs +class LLAudioStreamManagerFMODEX; +namespace FMOD +{ + class System; + class Channel; +} -class LLStreamingAudio_FMOD : public LLStreamingAudioInterface +//Interfaces +class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface { public: - LLStreamingAudio_FMOD(); - /*virtual*/ ~LLStreamingAudio_FMOD(); + LLStreamingAudio_FMODEX(FMOD::System *system); + /*virtual*/ ~LLStreamingAudio_FMODEX(); /*virtual*/ void start(const std::string& url); /*virtual*/ void stop(); @@ -49,14 +56,20 @@ class LLStreamingAudio_FMOD : public LLStreamingAudioInterface /*virtual*/ F32 getGain(); /*virtual*/ std::string getURL(); + /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} + /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); private: - LLAudioStreamManagerFMOD *mCurrentInternetStreamp; - int mFMODInternetStreamChannel; - std::list<LLAudioStreamManagerFMOD *> mDeadStreams; + FMOD::System *mSystem; + + LLAudioStreamManagerFMODEX *mCurrentInternetStreamp; + FMOD::Channel *mFMODInternetStreamChannelp; + std::list<LLAudioStreamManagerFMODEX *> mDeadStreams; std::string mURL; F32 mGain; + + LLTimer mLastStarved; }; -#endif // LL_STREAMINGAUDIO_FMOD_H +#endif // LL_STREAMINGAUDIO_FMODEX_H diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 0e0c80a456..dfd5da12b3 100755 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -35,7 +35,7 @@ #include "llapr.h" //#if LL_DARWIN -// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. +// MBW -- XXX -- Getting rid of SecondLifeVorbis for now #if 0 #include "VorbisFramework.h" diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h index b9cecb60a1..719b0ecbf2 100755 --- a/indra/llaudio/llwindgen.h +++ b/indra/llaudio/llwindgen.h @@ -27,6 +27,7 @@ #define WINDGEN_H #include "llcommon.h" +#include "llrand.h" template <class MIXBUFFERFORMAT_T> class LLWindGen @@ -54,7 +55,9 @@ public: } const U32 getInputSamplingRate() { return mInputSamplingRate; } - + const F32 getNextSample(); + const F32 getClampedSample(bool clamp, F32 sample); + // newbuffer = the buffer passed from the previous DSP unit. // numsamples = length in samples-per-channel at this mix time. // NOTE: generates L/R interleaved stereo @@ -89,7 +92,7 @@ public: // Start with white noise // This expression is fragile, rearrange it and it will break! - next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); + next_sample = getNextSample(); // Apply a pinking filter // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ @@ -126,23 +129,13 @@ public: for (U8 i=mSubSamples; i && numsamples; --i, --numsamples) { mLastSample = mLastSample + delta; - S32 sample_right = (S32)(mLastSample * mCurrentPanGainR); - S32 sample_left = (S32)mLastSample - sample_right; + MIXBUFFERFORMAT_T sample_right = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample * mCurrentPanGainR); + MIXBUFFERFORMAT_T sample_left = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample - (F32)sample_right); - if (!clip) - { - *cursamplep = (MIXBUFFERFORMAT_T)sample_left; - ++cursamplep; - *cursamplep = (MIXBUFFERFORMAT_T)sample_right; - ++cursamplep; - } - else - { - *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX); - ++cursamplep; - *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX); - ++cursamplep; - } + *cursamplep = sample_left; + ++cursamplep; + *cursamplep = sample_right; + ++cursamplep; } } @@ -173,4 +166,9 @@ private: F32 mLastSample; }; +template<class T> inline const F32 LLWindGen<T>::getNextSample() { return (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); } +template<> inline const F32 LLWindGen<F32>::getNextSample() { return ll_frand()-.5f; } +template<class T> inline const F32 LLWindGen<T>::getClampedSample(bool clamp, F32 sample) { return clamp ? (F32)llclamp((S32)sample,(S32)S16_MIN,(S32)S16_MAX) : sample; } +template<> inline const F32 LLWindGen<F32>::getClampedSample(bool clamp, F32 sample) { return sample; } + #endif diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index a1712699eb..2573417b26 100755 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -16,6 +16,10 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llcharacter_SOURCE_FILES llanimationstates.cpp @@ -76,6 +80,15 @@ list(APPEND llcharacter_SOURCE_FILES ${llcharacter_HEADER_FILES}) add_library (llcharacter ${llcharacter_SOURCE_FILES}) +target_link_libraries( + llcharacter + ${LLCOMMON_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLXML_LIBRARIES} + ) + # Add tests if (LL_TESTS) diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 0a6a8f9fa6..85cf1cd3f5 100755 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -286,7 +286,7 @@ void LLCharacter::removeAnimationData(std::string name) //----------------------------------------------------------------------------- // setVisualParamWeight() //----------------------------------------------------------------------------- -BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL upload_bake) +BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake) { S32 index = which_param->getID(); visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 3ebb2bffb0..5740dbce77 100755 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -93,13 +93,6 @@ public: // get the height & normal of the ground under a point virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm) = 0; - // allocate an array of joints for the character skeleton - // this must be overloaded to support joint subclasses, - // and is called implicitly from buildSkeleton(). - // Note this must handle reallocation as it will be called - // each time buildSkeleton() is called. - virtual BOOL allocateCharacterJoints( U32 num ) = 0; - // skeleton joint accessor to support joint subclasses virtual LLJoint *getCharacterJoint( U32 i ) = 0; @@ -197,7 +190,7 @@ public: void addVisualParam(LLVisualParam *param); void addSharedVisualParam(LLVisualParam *param); - virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 19907933cb..09a7c11a22 100755 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -40,7 +40,9 @@ S32 LLJoint::sNumTouches = 0; // LLJoint() // Class Constructor //----------------------------------------------------------------------------- -LLJoint::LLJoint() + + +void LLJoint::init() { mName = "unnamed"; mParent = NULL; @@ -48,7 +50,20 @@ LLJoint::LLJoint() mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; - mJointNum = -1; +} + +LLJoint::LLJoint() : + mJointNum(-1) +{ + init(); + touch(); + mResetAfterRestoreOldXform = false; +} + +LLJoint::LLJoint(S32 joint_num) : + mJointNum(joint_num) +{ + init(); touch(); mResetAfterRestoreOldXform = false; } @@ -58,15 +73,12 @@ LLJoint::LLJoint() // LLJoint() // Class Constructor //----------------------------------------------------------------------------- -LLJoint::LLJoint(const std::string &name, LLJoint *parent) +LLJoint::LLJoint(const std::string &name, LLJoint *parent) : + mJointNum(0) { - mName = "unnamed"; - mParent = NULL; - mXform.setScaleChildOffset(TRUE); - mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); - mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; + init(); mUpdateXform = FALSE; - mJointNum = 0; + // *TODO: mResetAfterRestoreOldXform is not initialized!!! setName(name); if (parent) diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index dc3c58cf64..2b1e2005c6 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -105,10 +105,15 @@ public: public: LLJoint(); + LLJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLJoint( const std::string &name, LLJoint *parent=NULL ); - virtual ~LLJoint(); +private: + void init(); + +public: // set name and parent void setup( const std::string &name, LLJoint *parent=NULL ); @@ -178,7 +183,6 @@ public: virtual BOOL isAnimatable() const { return TRUE; } S32 getJointNum() const { return mJointNum; } - void setJointNum(S32 joint_num) { mJointNum = joint_num; } void restoreOldXform( void ); void restoreToDefaultXform( void ); diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index 809b312abe..f7cb0f76b7 100755 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -168,7 +168,8 @@ LLVisualParam::LLVisualParam() mIsAnimating( FALSE ), mID( -1 ), mInfo( 0 ), - mIsDummy(FALSE) + mIsDummy(FALSE), + mParamLocation(LOC_UNKNOWN) { } @@ -250,6 +251,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake) if (mIsDummy) { setWeight(target_value, upload_bake); + mTargetWeight = mCurWeight; return; } @@ -319,3 +321,32 @@ void LLVisualParam::resetDrivenParams() // nothing to do for non-driver parameters return; } + +const std::string param_location_name(const EParamLocation& loc) +{ + switch (loc) + { + case LOC_UNKNOWN: return "unknown"; + case LOC_AV_SELF: return "self"; + case LOC_AV_OTHER: return "other"; + case LOC_WEARABLE: return "wearable"; + default: return "error"; + } +} + +void LLVisualParam::setParamLocation(EParamLocation loc) +{ + if (mParamLocation == LOC_UNKNOWN || loc == LOC_UNKNOWN) + { + mParamLocation = loc; + } + else if (mParamLocation == loc) + { + // no action + } + else + { + lldebugs << "param location is already " << mParamLocation << ", not slamming to " << loc << llendl; + } +} + diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index 281fb14781..60ea7a369a 100755 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -50,6 +50,16 @@ enum EVisualParamGroup NUM_VISUAL_PARAM_GROUPS }; +enum EParamLocation +{ + LOC_UNKNOWN, + LOC_AV_SELF, + LOC_AV_OTHER, + LOC_WEARABLE +}; + +const std::string param_location_name(const EParamLocation& loc); + const S32 MAX_TRANSMITTED_VISUAL_PARAMS = 255; //----------------------------------------------------------------------------- @@ -150,6 +160,9 @@ public: void setIsDummy(BOOL is_dummy) { mIsDummy = is_dummy; } + void setParamLocation(EParamLocation loc); + EParamLocation getParamLocation() const { return mParamLocation; } + protected: F32 mCurWeight; // current weight F32 mLastWeight; // last weight @@ -161,6 +174,7 @@ protected: S32 mID; // id for storing weight/morphtarget compares compactly LLVisualParamInfo *mInfo; + EParamLocation mParamLocation; // where does this visual param live? } LL_ALIGN_POSTFIX(16); #endif // LL_LLVisualParam_H diff --git a/indra/llcharacter/tests/lljoint_test.cpp b/indra/llcharacter/tests/lljoint_test.cpp index e92aa832d6..da151808f2 100755 --- a/indra/llcharacter/tests/lljoint_test.cpp +++ b/indra/llcharacter/tests/lljoint_test.cpp @@ -150,11 +150,11 @@ namespace tut template<> template<> void lljoint_object::test<11>() { - LLJoint lljoint("parent"); S32 joint_num = 12; - lljoint.setJointNum(joint_num); + LLJoint lljoint(joint_num); + lljoint.setName("parent"); S32 jointNum = lljoint.getJointNum(); - ensure("setJointNum()/getJointNum failed ", (jointNum == joint_num)); + ensure("getJointNum failed ", (jointNum == joint_num)); } template<> template<> diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp index fe11465221..7d647e5c36 100755 --- a/indra/llcommon/imageids.cpp +++ b/indra/llcommon/imageids.cpp @@ -68,3 +68,6 @@ const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); / const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER + +const LLUUID IMG_CHECKERBOARD_RGBA ("2585a0f3-4163-6dd1-0f34-ad48cb909e25"); // dataserver + diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h index e0c2683fdc..18c8ecb074 100755 --- a/indra/llcommon/imageids.h +++ b/indra/llcommon/imageids.h @@ -66,4 +66,5 @@ LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL; LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL; +LL_COMMON_API extern const LLUUID IMG_CHECKERBOARD_RGBA; #endif diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 95ecce509b..642bd82e90 100755 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -178,6 +178,21 @@ std::string LLAvatarName::getCompleteName() const return name; } +std::string LLAvatarName::getLegacyName() const +{ + if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled? + { + return mDisplayName; + } + + std::string name; + name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() ); + name = mLegacyFirstName; + name += " "; + name += mLegacyLastName; + return name; +} + std::string LLAvatarName::getDisplayName() const { if (sUseDisplayNames) diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index 4827353018..7542a8dece 100755 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -63,6 +63,11 @@ public: // For normal names, returns "James Linden (james.linden)" // When display names are disabled returns just "James Linden" std::string getCompleteName() const; + + // Returns "James Linden" or "bobsmith123 Resident" for backwards + // compatibility with systems like voice and muting + // *TODO: Eliminate this in favor of username only + std::string getLegacyName() const; // "José Sanchez" or "James Linden", UTF-8 encoded Unicode // Takes the display name preference into account. This is truly the name that should diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h index bc3bc3e74a..c752859a36 100755 --- a/indra/llcommon/lldictionary.h +++ b/indra/llcommon/lldictionary.h @@ -30,6 +30,8 @@ #include <map> #include <string> +#include "llerror.h" + struct LL_COMMON_API LLDictionaryEntry { LLDictionaryEntry(const std::string &name); diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 6970c29092..9b15804e97 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -561,6 +561,12 @@ std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren() return mChildren; } +// static +LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() +{ + return *NamedTimerFactory::instance().getRootTimer(); +} + //static void LLFastTimer::nextFrame() { diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index e42e549df5..81c4b78775 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -91,6 +91,8 @@ public: U32 getHistoricalCount(S32 history_index = 0) const; U32 getHistoricalCalls(S32 history_index = 0) const; + static NamedTimer& getRootNamedTimer(); + void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); } FrameState& getFrameState() const; diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index c51d042a3d..bc615ed39e 100755 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -56,6 +56,8 @@ std::string strerr(int errn) return buffer; } +typedef std::basic_ios<char,std::char_traits < char > > _Myios; + #else // On Posix we want to call strerror_r(), but alarmingly, there are two // different variants. The one that returns int always populates the passed @@ -324,9 +326,10 @@ const char *LLFile::tmpdir() /***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/ -#if USE_LLFILESTREAMS +#if LL_WINDOWS -LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int) // protection currently unused +LLFILE * LLFile::_Fiopen(const std::string& filename, + std::ios::openmode mode) { // open a file static const char *mods[] = { // fopen mode strings corresponding to valid[i] @@ -385,117 +388,681 @@ LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,in return (0); } -/************** input file stream ********************************/ +#endif /* LL_WINDOWS */ -void llifstream::close() -{ // close the C stream - if (_Filebuffer && _Filebuffer->close() == 0) +/************** llstdio file buffer ********************************/ + + +//llstdio_filebuf* llstdio_filebuf::open(const char *_Filename, +// ios_base::openmode _Mode) +//{ +//#if LL_WINDOWS +// _Filet *_File; +// if (is_open() || (_File = LLFILE::_Fiopen(_Filename, _Mode)) == 0) +// return (0); // open failed +// +// _Init(_File, _Openfl); +// _Initcvt(&_USE(_Mysb::getloc(), _Cvt)); +// return (this); // open succeeded +//#else +// std::filebuf* _file = std::filebuf::open(_Filename, _Mode); +// if (NULL == _file) return NULL; +// return this; +//#endif +//} + + +// *TODO: Seek the underlying c stream for better cross-platform compatibility? +#if !LL_WINDOWS +llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c) +{ + int_type __ret = traits_type::eof(); + const bool __testeof = traits_type::eq_int_type(__c, __ret); + const bool __testout = _M_mode & ios_base::out; + if (__testout && !_M_reading) { - _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ + if (this->pbase() < this->pptr()) + { + // If appropriate, append the overflow char. + if (!__testeof) + { + *this->pptr() = traits_type::to_char_type(__c); + this->pbump(1); + } + + // Convert pending sequence to external representation, + // and output. + if (_convert_to_external(this->pbase(), + this->pptr() - this->pbase())) + { + _M_set_buffer(0); + __ret = traits_type::not_eof(__c); + } + } + else if (_M_buf_size > 1) + { + // Overflow in 'uncommitted' mode: set _M_writing, set + // the buffer to the initial 'write' mode, and put __c + // into the buffer. + _M_set_buffer(0); + _M_writing = true; + if (!__testeof) + { + *this->pptr() = traits_type::to_char_type(__c); + this->pbump(1); + } + __ret = traits_type::not_eof(__c); + } + else + { + // Unbuffered. + char_type __conv = traits_type::to_char_type(__c); + if (__testeof || _convert_to_external(&__conv, 1)) + { + _M_writing = true; + __ret = traits_type::not_eof(__c); + } + } } + return __ret; } -void llifstream::open(const std::string& _Filename, /* Flawfinder: ignore */ - ios_base::openmode _Mode, - int _Prot) -{ // open a C stream with specified mode +bool llstdio_filebuf::_convert_to_external(char_type* __ibuf, + std::streamsize __ilen) +{ + // Sizes of external and pending output. + streamsize __elen; + streamsize __plen; + if (__check_facet(_M_codecvt).always_noconv()) + { + //__elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen); + __elen = fwrite(reinterpret_cast<void*>(__ibuf), 1, + __ilen, _M_file.file()); + __plen = __ilen; + } + else + { + // Worst-case number of external bytes needed. + // XXX Not done encoding() == -1. + streamsize __blen = __ilen * _M_codecvt->max_length(); + char* __buf = static_cast<char*>(__builtin_alloca(__blen)); - LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); - if(filep == NULL) + char* __bend; + const char_type* __iend; + codecvt_base::result __r; + __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, + __iend, __buf, __buf + __blen, __bend); + + if (__r == codecvt_base::ok || __r == codecvt_base::partial) + __blen = __bend - __buf; + else if (__r == codecvt_base::noconv) + { + // Same as the always_noconv case above. + __buf = reinterpret_cast<char*>(__ibuf); + __blen = __ilen; + } + else + __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " + "conversion error")); + + //__elen = _M_file.xsputn(__buf, __blen); + __elen = fwrite(__buf, 1, __blen, _M_file.file()); + __plen = __blen; + + // Try once more for partial conversions. + if (__r == codecvt_base::partial && __elen == __plen) + { + const char_type* __iresume = __iend; + streamsize __rlen = this->pptr() - __iend; + __r = _M_codecvt->out(_M_state_cur, __iresume, + __iresume + __rlen, __iend, __buf, + __buf + __blen, __bend); + if (__r != codecvt_base::error) + { + __rlen = __bend - __buf; + //__elen = _M_file.xsputn(__buf, __rlen); + __elen = fwrite(__buf, 1, __rlen, _M_file.file()); + __plen = __rlen; + } + else + { + __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " + "conversion error")); + } + } + } + return __elen == __plen; +} + +llstdio_filebuf::int_type llstdio_filebuf::underflow() +{ + int_type __ret = traits_type::eof(); + const bool __testin = _M_mode & ios_base::in; + if (__testin) { - _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ - return; + if (_M_writing) + { + if (overflow() == traits_type::eof()) + return __ret; + //_M_set_buffer(-1); + //_M_writing = false; + } + // Check for pback madness, and if so switch back to the + // normal buffers and jet outta here before expensive + // fileops happen... + _M_destroy_pback(); + + if (this->gptr() < this->egptr()) + return traits_type::to_int_type(*this->gptr()); + + // Get and convert input sequence. + const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; + + // Will be set to true if ::fread() returns 0 indicating EOF. + bool __got_eof = false; + // Number of internal characters produced. + streamsize __ilen = 0; + codecvt_base::result __r = codecvt_base::ok; + if (__check_facet(_M_codecvt).always_noconv()) + { + //__ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()), + // __buflen); + __ilen = fread(reinterpret_cast<void*>(this->eback()), 1, + __buflen, _M_file.file()); + if (__ilen == 0) + __got_eof = true; + } + else + { + // Worst-case number of external bytes. + // XXX Not done encoding() == -1. + const int __enc = _M_codecvt->encoding(); + streamsize __blen; // Minimum buffer size. + streamsize __rlen; // Number of chars to read. + if (__enc > 0) + __blen = __rlen = __buflen * __enc; + else + { + __blen = __buflen + _M_codecvt->max_length() - 1; + __rlen = __buflen; + } + const streamsize __remainder = _M_ext_end - _M_ext_next; + __rlen = __rlen > __remainder ? __rlen - __remainder : 0; + + // An imbue in 'read' mode implies first converting the external + // chars already present. + if (_M_reading && this->egptr() == this->eback() && __remainder) + __rlen = 0; + + // Allocate buffer if necessary and move unconverted + // bytes to front. + if (_M_ext_buf_size < __blen) + { + char* __buf = new char[__blen]; + if (__remainder) + __builtin_memcpy(__buf, _M_ext_next, __remainder); + + delete [] _M_ext_buf; + _M_ext_buf = __buf; + _M_ext_buf_size = __blen; + } + else if (__remainder) + __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); + + _M_ext_next = _M_ext_buf; + _M_ext_end = _M_ext_buf + __remainder; + _M_state_last = _M_state_cur; + + do + { + if (__rlen > 0) + { + // Sanity check! + // This may fail if the return value of + // codecvt::max_length() is bogus. + if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size) + { + __throw_ios_failure(__N("llstdio_filebuf::underflow " + "codecvt::max_length() " + "is not valid")); + } + //streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen); + streamsize __elen = fread(_M_ext_end, 1, + __rlen, _M_file.file()); + if (__elen == 0) + __got_eof = true; + else if (__elen == -1) + break; + //_M_ext_end += __elen; + } + + char_type* __iend = this->eback(); + if (_M_ext_next < _M_ext_end) + { + __r = _M_codecvt->in(_M_state_cur, _M_ext_next, + _M_ext_end, _M_ext_next, + this->eback(), + this->eback() + __buflen, __iend); + } + if (__r == codecvt_base::noconv) + { + size_t __avail = _M_ext_end - _M_ext_buf; + __ilen = std::min(__avail, __buflen); + traits_type::copy(this->eback(), + reinterpret_cast<char_type*> + (_M_ext_buf), __ilen); + _M_ext_next = _M_ext_buf + __ilen; + } + else + __ilen = __iend - this->eback(); + + // _M_codecvt->in may return error while __ilen > 0: this is + // ok, and actually occurs in case of mixed encodings (e.g., + // XML files). + if (__r == codecvt_base::error) + break; + + __rlen = 1; + } while (__ilen == 0 && !__got_eof); + } + + if (__ilen > 0) + { + _M_set_buffer(__ilen); + _M_reading = true; + __ret = traits_type::to_int_type(*this->gptr()); + } + else if (__got_eof) + { + // If the actual end of file is reached, set 'uncommitted' + // mode, thus allowing an immediate write without an + // intervening seek. + _M_set_buffer(-1); + _M_reading = false; + // However, reaching it while looping on partial means that + // the file has got an incomplete character. + if (__r == codecvt_base::partial) + __throw_ios_failure(__N("llstdio_filebuf::underflow " + "incomplete character in file")); + } + else if (__r == codecvt_base::error) + __throw_ios_failure(__N("llstdio_filebuf::underflow " + "invalid byte sequence in file")); + else + __throw_ios_failure(__N("llstdio_filebuf::underflow " + "error reading the file")); } - llassert(_Filebuffer == NULL); - _Filebuffer = new _Myfb(filep); - _ShouldClose = true; - _Myios::init(_Filebuffer); + return __ret; } -bool llifstream::is_open() const -{ // test if C stream has been opened - if(_Filebuffer) - return (_Filebuffer->is_open()); - return false; +std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n) +{ + // Clear out pback buffer before going on to the real deal... + streamsize __ret = 0; + if (_M_pback_init) + { + if (__n > 0 && this->gptr() == this->eback()) + { + *__s++ = *this->gptr(); + this->gbump(1); + __ret = 1; + --__n; + } + _M_destroy_pback(); + } + + // Optimization in the always_noconv() case, to be generalized in the + // future: when __n > __buflen we read directly instead of using the + // buffer repeatedly. + const bool __testin = _M_mode & ios_base::in; + const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; + + if (__n > __buflen && __check_facet(_M_codecvt).always_noconv() + && __testin && !_M_writing) + { + // First, copy the chars already present in the buffer. + const streamsize __avail = this->egptr() - this->gptr(); + if (__avail != 0) + { + if (__avail == 1) + *__s = *this->gptr(); + else + traits_type::copy(__s, this->gptr(), __avail); + __s += __avail; + this->gbump(__avail); + __ret += __avail; + __n -= __avail; + } + + // Need to loop in case of short reads (relatively common + // with pipes). + streamsize __len; + for (;;) + { + //__len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n); + __len = fread(reinterpret_cast<void*>(__s), 1, + __n, _M_file.file()); + if (__len == -1) + __throw_ios_failure(__N("llstdio_filebuf::xsgetn " + "error reading the file")); + if (__len == 0) + break; + + __n -= __len; + __ret += __len; + if (__n == 0) + break; + + __s += __len; + } + + if (__n == 0) + { + _M_set_buffer(0); + _M_reading = true; + } + else if (__len == 0) + { + // If end of file is reached, set 'uncommitted' + // mode, thus allowing an immediate write without + // an intervening seek. + _M_set_buffer(-1); + _M_reading = false; + } + } + else + __ret += __streambuf_type::xsgetn(__s, __n); + + return __ret; } -llifstream::~llifstream() + +std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n) { - if (_ShouldClose) + // Optimization in the always_noconv() case, to be generalized in the + // future: when __n is sufficiently large we write directly instead of + // using the buffer. + streamsize __ret = 0; + const bool __testout = _M_mode & ios_base::out; + if (__check_facet(_M_codecvt).always_noconv() + && __testout && !_M_reading) { - close(); + // Measurement would reveal the best choice. + const streamsize __chunk = 1ul << 10; + streamsize __bufavail = this->epptr() - this->pptr(); + + // Don't mistake 'uncommitted' mode buffered with unbuffered. + if (!_M_writing && _M_buf_size > 1) + __bufavail = _M_buf_size - 1; + + const streamsize __limit = std::min(__chunk, __bufavail); + if (__n >= __limit) + { + const streamsize __buffill = this->pptr() - this->pbase(); + const char* __buf = reinterpret_cast<const char*>(this->pbase()); + //__ret = _M_file.xsputn_2(__buf, __buffill, + // reinterpret_cast<const char*>(__s), __n); + if (__buffill) + { + __ret = fwrite(__buf, 1, __buffill, _M_file.file()); + } + if (__ret == __buffill) + { + __ret += fwrite(reinterpret_cast<const char*>(__s), 1, + __n, _M_file.file()); + } + if (__ret == __buffill + __n) + { + _M_set_buffer(0); + _M_writing = true; + } + if (__ret > __buffill) + __ret -= __buffill; + else + __ret = 0; + } + else + __ret = __streambuf_type::xsputn(__s, __n); } - delete _Filebuffer; + else + __ret = __streambuf_type::xsputn(__s, __n); + return __ret; } -llifstream::llifstream(const std::string& _Filename, - ios_base::openmode _Mode, - int _Prot) - : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) +int llstdio_filebuf::sync() +{ + return (_M_file.sync() == 0 ? 0 : -1); +} +#endif + +/************** input file stream ********************************/ -{ // construct with named file and specified mode - open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */ + +llifstream::llifstream() : _M_filebuf(), +#if LL_WINDOWS + std::istream(&_M_filebuf) {} +#else + std::istream() +{ + this->init(&_M_filebuf); +} +#endif + +// explicit +llifstream::llifstream(const std::string& _Filename, + ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS + std::istream(&_M_filebuf) +{ + if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::in) == 0) + { + _Myios::setstate(ios_base::failbit); + } } +#else + std::istream() +{ + this->init(&_M_filebuf); + this->open(_Filename.c_str(), _Mode | ios_base::in); +} +#endif +// explicit +llifstream::llifstream(const char* _Filename, + ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS + std::istream(&_M_filebuf) +{ + if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0) + { + _Myios::setstate(ios_base::failbit); + } +} +#else + std::istream() +{ + this->init(&_M_filebuf); + this->open(_Filename, _Mode | ios_base::in); +} +#endif -/************** output file stream ********************************/ -bool llofstream::is_open() const +// explicit +llifstream::llifstream(_Filet *_File, + ios_base::openmode _Mode, size_t _Size) : + _M_filebuf(_File, _Mode, _Size), +#if LL_WINDOWS + std::istream(&_M_filebuf) {} +#else + std::istream() +{ + this->init(&_M_filebuf); +} +#endif + +#if !LL_WINDOWS +// explicit +llifstream::llifstream(int __fd, + ios_base::openmode _Mode, size_t _Size) : + _M_filebuf(__fd, _Mode, _Size), + std::istream() +{ + this->init(&_M_filebuf); +} +#endif + +bool llifstream::is_open() const { // test if C stream has been opened - if(_Filebuffer) - return (_Filebuffer->is_open()); - return false; + return _M_filebuf.is_open(); } -void llofstream::open(const std::string& _Filename, /* Flawfinder: ignore */ - ios_base::openmode _Mode, - int _Prot) +void llifstream::open(const char* _Filename, ios_base::openmode _Mode) { // open a C stream with specified mode - - LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); - if(filep == NULL) + if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0) +#if LL_WINDOWS + { + _Myios::setstate(ios_base::failbit); + } + else { - _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ - return; + _Myios::clear(); } - llassert(_Filebuffer==NULL); - _Filebuffer = new _Myfb(filep); - _ShouldClose = true; - _Myios::init(_Filebuffer); +#else + { + this->setstate(ios_base::failbit); + } + else + { + this->clear(); + } +#endif } -void llofstream::close() +void llifstream::close() { // close the C stream - if(is_open()) + if (_M_filebuf.close() == 0) { - if (_Filebuffer->close() == 0) - { - _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ - } - delete _Filebuffer; - _Filebuffer = NULL; - _ShouldClose = false; +#if LL_WINDOWS + _Myios::setstate(ios_base::failbit); +#else + this->setstate(ios_base::failbit); +#endif } } + +/************** output file stream ********************************/ + + +llofstream::llofstream() : _M_filebuf(), +#if LL_WINDOWS + std::ostream(&_M_filebuf) {} +#else + std::ostream() +{ + this->init(&_M_filebuf); +} +#endif + +// explicit llofstream::llofstream(const std::string& _Filename, - std::ios_base::openmode _Mode, - int _Prot) - : std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) -{ // construct with named file and specified mode - open(_Filename, _Mode , _Prot); /* Flawfinder: ignore */ + ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS + std::ostream(&_M_filebuf) +{ + if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::out) == 0) + { + _Myios::setstate(ios_base::failbit); + } +} +#else + std::ostream() +{ + this->init(&_M_filebuf); + this->open(_Filename.c_str(), _Mode | ios_base::out); +} +#endif + +// explicit +llofstream::llofstream(const char* _Filename, + ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS + std::ostream(&_M_filebuf) +{ + if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0) + { + _Myios::setstate(ios_base::failbit); + } +} +#else + std::ostream() +{ + this->init(&_M_filebuf); + this->open(_Filename, _Mode | ios_base::out); +} +#endif + +// explicit +llofstream::llofstream(_Filet *_File, + ios_base::openmode _Mode, size_t _Size) : + _M_filebuf(_File, _Mode, _Size), +#if LL_WINDOWS + std::ostream(&_M_filebuf) {} +#else + std::ostream() +{ + this->init(&_M_filebuf); } +#endif -llofstream::~llofstream() +#if !LL_WINDOWS +// explicit +llofstream::llofstream(int __fd, + ios_base::openmode _Mode, size_t _Size) : + _M_filebuf(__fd, _Mode, _Size), + std::ostream() { - // destroy the object - if (_ShouldClose) + this->init(&_M_filebuf); +} +#endif + +bool llofstream::is_open() const +{ // test if C stream has been opened + return _M_filebuf.is_open(); +} + +void llofstream::open(const char* _Filename, ios_base::openmode _Mode) +{ // open a C stream with specified mode + if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0) +#if LL_WINDOWS + { + _Myios::setstate(ios_base::failbit); + } + else { - close(); + _Myios::clear(); } - delete _Filebuffer; +#else + { + this->setstate(ios_base::failbit); + } + else + { + this->clear(); + } +#endif } -#endif // #if USE_LLFILESTREAMS +void llofstream::close() +{ // close the C stream + if (_M_filebuf.close() == 0) + { +#if LL_WINDOWS + _Myios::setstate(ios_base::failbit); +#else + this->setstate(ios_base::failbit); +#endif + } +} /************** helper functions ********************************/ diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index dd7d36513a..9d70db96ea 100755 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -35,16 +35,9 @@ * Attempts to mostly mirror the POSIX style IO functions. */ -typedef FILE LLFILE; +typedef FILE LLFILE; #include <fstream> - -#ifdef LL_WINDOWS -#define USE_LLFILESTREAMS 1 -#else -#define USE_LLFILESTREAMS 0 -#endif - #include <sys/stat.h> #if LL_WINDOWS @@ -52,6 +45,8 @@ typedef FILE LLFILE; typedef struct _stat llstat; #else typedef struct stat llstat; +#include <ext/stdio_filebuf.h> +#include <bits/postypes.h> #endif #ifndef S_ISREG @@ -83,142 +78,342 @@ public: static int stat(const std::string& filename,llstat* file_status); static bool isdir(const std::string& filename); static bool isfile(const std::string& filename); - static LLFILE * _Fiopen(const std::string& filename, std::ios::openmode mode,int); // protection currently unused + static LLFILE * _Fiopen(const std::string& filename, + std::ios::openmode mode); static const char * tmpdir(); }; +/** + * @brief Provides a layer of compatibility for C/POSIX. + * + * This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and + * VC's basic_filebuf implementation. + * This file buffer provides extensions for working with standard C FILE*'s + * and POSIX file descriptors for platforms that support this. +*/ +namespace +{ +#if LL_WINDOWS +typedef std::filebuf _Myfb; +#else +typedef __gnu_cxx::stdio_filebuf< char > _Myfb; +typedef std::__c_file _Filet; +#endif /* LL_WINDOWS */ +} -#if USE_LLFILESTREAMS - -class LL_COMMON_API llifstream : public std::basic_istream < char , std::char_traits < char > > +class LL_COMMON_API llstdio_filebuf : public _Myfb { - // input stream associated with a C stream public: - typedef std::basic_ifstream<char,std::char_traits < char > > _Myt; - typedef std::basic_filebuf<char,std::char_traits< char > > _Myfb; - typedef std::basic_ios<char,std::char_traits< char > > _Myios; - - llifstream() - : std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) - { // construct unopened - } + /** + * deferred initialization / destruction + */ + llstdio_filebuf() : _Myfb() {} + virtual ~llstdio_filebuf() {} + + /** + * @param f An open @c FILE*. + * @param mode Same meaning as in a standard filebuf. + * @param size Optimal or preferred size of internal buffer, in chars. + * Defaults to system's @c BUFSIZ. + * + * This constructor associates a file stream buffer with an open + * C @c FILE*. The @c FILE* will not be automatically closed when the + * stdio_filebuf is closed/destroyed. + */ + llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode, + //size_t __size = static_cast<size_t>(BUFSIZ)) : + size_t __size = static_cast<size_t>(1)) : +#if LL_WINDOWS + _Myfb(__f) {} +#else + _Myfb(__f, __mode, __size) {} +#endif - explicit llifstream(const std::string& _Filename, - ios_base::openmode _Mode = ios_base::in, - int _Prot = (int)ios_base::_Openprot); - - explicit llifstream(_Filet *_File) - : std::basic_istream<char,std::char_traits< char > >(NULL,true), - _Filebuffer(new _Myfb(_File)), - _ShouldClose(false) - { // construct with specified C stream - } - virtual ~llifstream(); - - _Myfb *rdbuf() const - { // return pointer to file buffer - return _Filebuffer; - } - bool is_open() const; - void open(const std::string& _Filename, /* Flawfinder: ignore */ - ios_base::openmode _Mode = ios_base::in, - int _Prot = (int)ios_base::_Openprot); - void close(); + /** + * @brief Opens an external file. + * @param s The name of the file. + * @param mode The open mode flags. + * @return @c this on success, NULL on failure + * + * If a file is already open, this function immediately fails. + * Otherwise it tries to open the file named @a s using the flags + * given in @a mode. + */ + //llstdio_filebuf* open(const char *_Filename, + // std::ios_base::openmode _Mode); + + /** + * @param fd An open file descriptor. + * @param mode Same meaning as in a standard filebuf. + * @param size Optimal or preferred size of internal buffer, in chars. + * + * This constructor associates a file stream buffer with an open + * POSIX file descriptor. The file descriptor will be automatically + * closed when the stdio_filebuf is closed/destroyed. + */ +#if !LL_WINDOWS + llstdio_filebuf(int __fd, std::ios_base::openmode __mode, + //size_t __size = static_cast<size_t>(BUFSIZ)) : + size_t __size = static_cast<size_t>(1)) : + _Myfb(__fd, __mode, __size) {} +#endif -private: - _Myfb* _Filebuffer; // the file buffer - bool _ShouldClose; +// *TODO: Seek the underlying c stream for better cross-platform compatibility? +#if !LL_WINDOWS +protected: + /** underflow() and uflow() functions are called to get the next + * character from the real input source when the buffer is empty. + * Buffered input uses underflow() + */ + /*virtual*/ int_type underflow(); + + /* Convert internal byte sequence to external, char-based + * sequence via codecvt. + */ + bool _convert_to_external(char_type*, std::streamsize); + + /** The overflow() function is called to transfer characters to the + * real output destination when the buffer is full. A call to + * overflow(c) outputs the contents of the buffer plus the + * character c. + * Consume some sequence of the characters in the pending sequence. + */ + /*virtual*/ int_type overflow(int_type __c = traits_type::eof()); + + /** sync() flushes the underlying @c FILE* stream. + */ + /*virtual*/ int sync(); + + std::streamsize xsgetn(char_type*, std::streamsize); + std::streamsize xsputn(char_type*, std::streamsize); +#endif }; -class LL_COMMON_API llofstream : public std::basic_ostream< char , std::char_traits < char > > +/** + * @brief Controlling input for files. + * + * This class supports reading from named files, using the inherited + * functions from std::basic_istream. To control the associated + * sequence, an instance of std::basic_filebuf (or a platform-specific derivative) + * which allows construction using a pre-exisintg file stream buffer. + * We refer to this std::basic_filebuf (or derivative) as @c sb. +*/ +class LL_COMMON_API llifstream : public std::istream { + // input stream associated with a C stream public: - typedef std::basic_ostream< char , std::char_traits < char > > _Myt; - typedef std::basic_filebuf< char , std::char_traits < char > > _Myfb; - typedef std::basic_ios<char,std::char_traits < char > > _Myios; - - llofstream() - : std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) - { // construct unopened - } - - explicit llofstream(const std::string& _Filename, - std::ios_base::openmode _Mode = ios_base::out, - int _Prot = (int)std::ios_base::_Openprot); - - - explicit llofstream(_Filet *_File) - : std::basic_ostream<char,std::char_traits < char > >(NULL,true), - _Filebuffer(new _Myfb(_File)),//_File) - _ShouldClose(false) - { // construct with specified C stream - } - - virtual ~llofstream(); - - _Myfb *rdbuf() const - { // return pointer to file buffer - return _Filebuffer; - } + // Constructors: + /** + * @brief Default constructor. + * + * Initializes @c sb using its default constructor, and passes + * @c &sb to the base class initializer. Does not open any files + * (you haven't given it a filename to open). + */ + llifstream(); + + /** + * @brief Create an input file stream. + * @param Filename String specifying the filename. + * @param Mode Open file in specified mode (see std::ios_base). + * + * @c ios_base::in is automatically included in @a mode. + */ + explicit llifstream(const std::string& _Filename, + ios_base::openmode _Mode = ios_base::in); + explicit llifstream(const char* _Filename, + ios_base::openmode _Mode = ios_base::in); + + /** + * @brief Create a stream using an open c file stream. + * @param File An open @c FILE*. + @param Mode Same meaning as in a standard filebuf. + @param Size Optimal or preferred size of internal buffer, in chars. + Defaults to system's @c BUFSIZ. + */ + explicit llifstream(_Filet *_File, + ios_base::openmode _Mode = ios_base::in, + //size_t _Size = static_cast<size_t>(BUFSIZ)); + size_t _Size = static_cast<size_t>(1)); + + /** + * @brief Create a stream using an open file descriptor. + * @param fd An open file descriptor. + @param Mode Same meaning as in a standard filebuf. + @param Size Optimal or preferred size of internal buffer, in chars. + Defaults to system's @c BUFSIZ. + */ +#if !LL_WINDOWS + explicit llifstream(int __fd, + ios_base::openmode _Mode = ios_base::in, + //size_t _Size = static_cast<size_t>(BUFSIZ)); + size_t _Size = static_cast<size_t>(1)); +#endif + /** + * @brief The destructor does nothing. + * + * The file is closed by the filebuf object, not the formatting + * stream. + */ + virtual ~llifstream() {} + + // Members: + /** + * @brief Accessing the underlying buffer. + * @return The current basic_filebuf buffer. + * + * This hides both signatures of std::basic_ios::rdbuf(). + */ + llstdio_filebuf* rdbuf() const + { return const_cast<llstdio_filebuf*>(&_M_filebuf); } + + /** + * @brief Wrapper to test for an open file. + * @return @c rdbuf()->is_open() + */ bool is_open() const; - void open(const std::string& _Filename,ios_base::openmode _Mode = ios_base::out,int _Prot = (int)ios_base::_Openprot); /* Flawfinder: ignore */ - + /** + * @brief Opens an external file. + * @param Filename The name of the file. + * @param Node The open mode flags. + * + * Calls @c llstdio_filebuf::open(s,mode|in). If that function + * fails, @c failbit is set in the stream's error state. + */ + void open(const std::string& _Filename, + ios_base::openmode _Mode = ios_base::in) + { open(_Filename.c_str(), _Mode); } + void open(const char* _Filename, + ios_base::openmode _Mode = ios_base::in); + + /** + * @brief Close the file. + * + * Calls @c llstdio_filebuf::close(). If that function + * fails, @c failbit is set in the stream's error state. + */ void close(); private: - _Myfb *_Filebuffer; // the file buffer - bool _ShouldClose; -}; - - - -#else -//Use standard file streams on non windows platforms -//#define llifstream std::ifstream -//#define llofstream std::ofstream - -class LL_COMMON_API llifstream : public std::ifstream -{ -public: - llifstream() : std::ifstream() - { - } - - explicit llifstream(const std::string& _Filename, std::_Ios_Openmode _Mode = in) - : std::ifstream(_Filename.c_str(), _Mode) - { - } - void open(const std::string& _Filename, std::_Ios_Openmode _Mode = in) /* Flawfinder: ignore */ - { - std::ifstream::open(_Filename.c_str(), _Mode); - } + llstdio_filebuf _M_filebuf; }; -class LL_COMMON_API llofstream : public std::ofstream +/** + * @brief Controlling output for files. + * + * This class supports writing to named files, using the inherited + * functions from std::basic_ostream. To control the associated + * sequence, an instance of std::basic_filebuf (or a platform-specific derivative) + * which allows construction using a pre-exisintg file stream buffer. + * We refer to this std::basic_filebuf (or derivative) as @c sb. +*/ +class LL_COMMON_API llofstream : public std::ostream { public: - llofstream() : std::ofstream() - { - } + // Constructors: + /** + * @brief Default constructor. + * + * Initializes @c sb using its default constructor, and passes + * @c &sb to the base class initializer. Does not open any files + * (you haven't given it a filename to open). + */ + llofstream(); + + /** + * @brief Create an output file stream. + * @param Filename String specifying the filename. + * @param Mode Open file in specified mode (see std::ios_base). + * + * @c ios_base::out|ios_base::trunc is automatically included in + * @a mode. + */ + explicit llofstream(const std::string& _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + explicit llofstream(const char* _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + + /** + * @brief Create a stream using an open c file stream. + * @param File An open @c FILE*. + @param Mode Same meaning as in a standard filebuf. + @param Size Optimal or preferred size of internal buffer, in chars. + Defaults to system's @c BUFSIZ. + */ + explicit llofstream(_Filet *_File, + ios_base::openmode _Mode = ios_base::out, + //size_t _Size = static_cast<size_t>(BUFSIZ)); + size_t _Size = static_cast<size_t>(1)); + + /** + * @brief Create a stream using an open file descriptor. + * @param fd An open file descriptor. + @param Mode Same meaning as in a standard filebuf. + @param Size Optimal or preferred size of internal buffer, in chars. + Defaults to system's @c BUFSIZ. + */ +#if !LL_WINDOWS + explicit llofstream(int __fd, + ios_base::openmode _Mode = ios_base::out, + //size_t _Size = static_cast<size_t>(BUFSIZ)); + size_t _Size = static_cast<size_t>(1)); +#endif - explicit llofstream(const std::string& _Filename, std::_Ios_Openmode _Mode = out) - : std::ofstream(_Filename.c_str(), _Mode) - { - } + /** + * @brief The destructor does nothing. + * + * The file is closed by the filebuf object, not the formatting + * stream. + */ + virtual ~llofstream() {} + + // Members: + /** + * @brief Accessing the underlying buffer. + * @return The current basic_filebuf buffer. + * + * This hides both signatures of std::basic_ios::rdbuf(). + */ + llstdio_filebuf* rdbuf() const + { return const_cast<llstdio_filebuf*>(&_M_filebuf); } + + /** + * @brief Wrapper to test for an open file. + * @return @c rdbuf()->is_open() + */ + bool is_open() const; - void open(const std::string& _Filename, std::_Ios_Openmode _Mode = out) /* Flawfinder: ignore */ - { - std::ofstream::open(_Filename.c_str(), _Mode); - } + /** + * @brief Opens an external file. + * @param Filename The name of the file. + * @param Node The open mode flags. + * + * Calls @c llstdio_filebuf::open(s,mode|out). If that function + * fails, @c failbit is set in the stream's error state. + */ + void open(const std::string& _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc) + { open(_Filename.c_str(), _Mode); } + void open(const char* _Filename, + ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + + /** + * @brief Close the file. + * + * Calls @c llstdio_filebuf::close(). If that function + * fails, @c failbit is set in the stream's error state. + */ + void close(); +private: + llstdio_filebuf _M_filebuf; }; -#endif /** * @breif filesize helpers. diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 41d3eb0bf3..731e58bd20 100755 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -100,7 +100,7 @@ LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& i LLSD ret; LLSD cur; - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is)) { for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) { diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 6b549e4b6f..ad4fce6f35 100755 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1453,8 +1453,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeUUID: { ostr.put('u'); - LLSD::UUID value = data.asUUID(); - ostr.write((const char*)(&value.mData), UUID_BYTES); + LLUUID temp = data.asUUID(); + ostr.write((const char*)(&(temp.mData)), UUID_BYTES); break; } diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 86e3fc864c..e7a5507385 100755 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -300,7 +300,7 @@ public: /** * @brief Constructor */ - LLSDXMLParser(); + LLSDXMLParser(bool emit_errors=true); protected: /** @@ -747,25 +747,25 @@ public: return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY); } - static S32 fromXMLEmbedded(LLSD& sd, std::istream& str) + static S32 fromXMLEmbedded(LLSD& sd, std::istream& str, bool emit_errors=true) { // no need for max_bytes since xml formatting is not // subvertable by bad sizes. - LLPointer<LLSDXMLParser> p = new LLSDXMLParser; + LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors); return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED); } // Line oriented parser, 30% faster than fromXML(), but can // only be used when you know you have the complete XML // document available in the stream. - static S32 fromXMLDocument(LLSD& sd, std::istream& str) + static S32 fromXMLDocument(LLSD& sd, std::istream& str, bool emit_errors=true) { - LLPointer<LLSDXMLParser> p = new LLSDXMLParser(); + LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors); return p->parseLines(str, sd); } - static S32 fromXML(LLSD& sd, std::istream& str) + static S32 fromXML(LLSD& sd, std::istream& str, bool emit_errors=true) { - return fromXMLEmbedded(sd, str); -// return fromXMLDocument(sd, str); + return fromXMLEmbedded(sd, str, emit_errors); +// return fromXMLDocument(sd, str, emit_errors); } /* diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 34b3dbb99a..cef743a7be 100755 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -250,7 +250,7 @@ std::string LLSDXMLFormatter::escapeString(const std::string& in) class LLSDXMLParser::Impl { public: - Impl(); + Impl(bool emit_errors); ~Impl(); S32 parse(std::istream& input, LLSD& data); @@ -294,6 +294,7 @@ private: static const XML_Char* findAttribute(const XML_Char* name, const XML_Char** pairs); + bool mEmitErrors; XML_Parser mParser; @@ -315,7 +316,8 @@ private: }; -LLSDXMLParser::Impl::Impl() +LLSDXMLParser::Impl::Impl(bool emit_errors) + : mEmitErrors(emit_errors) { mParser = XML_ParserCreate(NULL); reset(); @@ -402,7 +404,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { ((char*) buffer)[count ? count - 1 : 0] = '\0'; } - llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl; + if (mEmitErrors) + { + llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl; + } data = LLSD(); return LLSDParser::PARSE_FAILURE; } @@ -480,7 +485,10 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data) if (status == XML_STATUS_ERROR && !mGracefullStop) { - llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl; + if (mEmitErrors) + { + llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl; + } return LLSDParser::PARSE_FAILURE; } @@ -897,7 +905,7 @@ LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* na /** * LLSDXMLParser */ -LLSDXMLParser::LLSDXMLParser() : impl(* new Impl) +LLSDXMLParser::LLSDXMLParser(bool emit_errors /* = true */) : impl(* new Impl(emit_errors)) { } diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index b19ba3bf74..ef68a0eaf5 100755 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -30,7 +30,7 @@ const S32 LL_VERSION_MAJOR = 2; const S32 LL_VERSION_MINOR = 1; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 13828; +const S32 LL_VERSION_BUILD = 264760; const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 0b0c74b3d3..0ea130e86b 100755 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,8 +29,8 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 5; -const S32 LL_VERSION_PATCH = 1; -const S32 LL_VERSION_BUILD = 0; +const S32 LL_VERSION_PATCH = 2; +const S32 LL_VERSION_BUILD = 264760; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp index 4c3bc674af..afc0c18cd0 100755 --- a/indra/llcommon/tests/bitpack_test.cpp +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -71,7 +71,6 @@ namespace tut U8 packbuffer[255]; U8 unpackbuffer[255]; int pack_bufsize = 0; - int unpack_bufsize = 0; LLBitPack bitpack(packbuffer, 255); @@ -81,21 +80,20 @@ namespace tut pack_bufsize = bitpack.flushBitPack(); LLBitPack bitunpack(packbuffer, pack_bufsize*8); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]); - unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + bitunpack.bitUnpack(&unpackbuffer[0], 8); ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]); - unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life + bitunpack.bitUnpack(unpackbuffer, 8*4); // Life ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); - ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize); } // U32 packing diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 454695ff9f..e769c3e22c 100755 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -267,7 +267,6 @@ namespace tut { existing.insert(&*uki); } - Unkeyed* puk = NULL; try { // We don't expect the assignment to take place because we expect @@ -280,7 +279,7 @@ namespace tut // realize we're testing the C++ implementation more than // Unkeyed's implementation, but this seems an important point to // nail down. - puk = new Unkeyed("throw"); + new Unkeyed("throw"); } catch (const Badness&) { diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt index b2639aec30..12986de8b2 100755 --- a/indra/llcrashlogger/CMakeLists.txt +++ b/indra/llcrashlogger/CMakeLists.txt @@ -16,6 +16,10 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llcrashlogger_SOURCE_FILES llcrashlogger.cpp diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 34e25a8a71..fb2d43e3b0 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -147,7 +147,7 @@ void LLCrashLogger::gatherFiles() // Look for it in the debug_info.log file if (debug_log_file.is_open()) - { + { LLSDSerialize::fromXML(mDebugLog, debug_log_file); mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean(); diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index ea8c1a1107..e837b0cac2 100755 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -7,12 +7,15 @@ include(LLCommon) include(LLImage) include(LLMath) include(LLVFS) +include(LLKDU) +include(LLImageJ2COJ) include(ZLIB) include(LLAddBuildTest) include(Tut) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} @@ -56,8 +59,16 @@ list(APPEND llimage_SOURCE_FILES ${llimage_HEADER_FILES}) add_library (llimage ${llimage_SOURCE_FILES}) # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level +if (USE_KDU) + target_link_libraries(llimage ${LLKDU_LIBRARIES}) +else (USE_KDU) + target_link_libraries(llimage ${LLIMAGEJ2COJ_LIBRARIES}) +endif (USE_KDU) + target_link_libraries(llimage - llcommon + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index a88ac148ef..1c25256e95 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -640,6 +640,29 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src ) } } +void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill) +{ + LLImageRaw* dst = this; // Just for clarity. + + llassert( 1 == src->getComponents() ); + llassert( 4 == dst->getComponents() ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + + S32 pixels = getWidth() * getHeight(); + U8* src_data = src->getData(); + U8* dst_data = dst->getData(); + for ( S32 i = 0; i < pixels; i++ ) + { + dst_data[0] = fill.mV[0]; + dst_data[1] = fill.mV[1]; + dst_data[2] = fill.mV[2]; + dst_data[3] = src_data[0]; + src_data += 1; + dst_data += 4; + } +} + + // Fill the buffer with a constant color void LLImageRaw::fill( const LLColor4U& color ) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 6cb1226da0..4fc40ecff7 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -226,6 +226,11 @@ public: // Src and dst are same size. Src has 3 components. Dst has 4 components. void copyUnscaled3onto4( LLImageRaw* src ); + // Src and dst are same size. Src has 1 component. Dst has 4 components. + // Alpha component is set to source alpha mask component. + // RGB components are set to fill color. + void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill); + // Src and dst can be any size. Src and dst have same number of components. void copyScaled( LLImageRaw* src ); diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index 58426d31fa..920ae2891f 100755 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -132,12 +132,12 @@ BOOL LLImageTGA::updateData() ** FIELD 2 : COLOR MAP TYPE (1 BYTES) ** FIELD 3 : IMAGE TYPE CODE (1 BYTES) ** = 0 NO IMAGE DATA INCLUDED - ** = 1 UNCOMPRESSED, COLOR-MAPPED IMAGE - ** = 2 UNCOMPRESSED, TRUE-COLOR IMAGE - ** = 3 UNCOMPRESSED, BLACK AND WHITE IMAGE - ** = 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE - ** = 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE - ** = 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE + ** = (0001) 1 UNCOMPRESSED, COLOR-MAPPED IMAGE + ** = (0010) 2 UNCOMPRESSED, TRUE-COLOR IMAGE + ** = (0011) 3 UNCOMPRESSED, BLACK AND WHITE IMAGE + ** = (1001) 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE + ** = (1010) 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE + ** = (1011) 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE ** FIELD 4 : COLOR MAP SPECIFICATION (5 BYTES) ** 4.1 : COLOR MAP ORIGIN (2 BYTES) ** 4.2 : COLOR MAP LENGTH (2 BYTES) diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index a80ae73dca..41d58c6deb 100755 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -288,7 +288,15 @@ void LLInventoryObject::setCreationDate(time_t creation_date_utc) } +const std::string& LLInventoryItem::getDescription() const +{ + return mDescription; +} +const std::string& LLInventoryItem::getActualDescription() const +{ + return mDescription; +} ///---------------------------------------------------------------------------- /// Class LLInventoryItem @@ -389,11 +397,6 @@ void LLInventoryItem::setAssetUUID(const LLUUID& asset_id) } -const std::string& LLInventoryItem::getDescription() const -{ - return mDescription; -} - U32 LLInventoryItem::getCRC32() const { // *FIX: Not a real crc - more of a checksum. diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 4516e548df..99716ed7be 100755 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -160,6 +160,7 @@ public: virtual const LLUUID& getCreatorUUID() const; virtual const LLUUID& getAssetUUID() const; virtual const std::string& getDescription() const; + virtual const std::string& getActualDescription() const; // Does not follow links virtual const LLSaleInfo& getSaleInfo() const; virtual LLInventoryType::EType getInventoryType() const; virtual U32 getFlags() const; diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 645ebab234..fc3c78cf50 100755 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -69,6 +69,53 @@ public: IT_NONE = -1 }; + enum EIconName + { + ICONNAME_TEXTURE, + ICONNAME_SOUND, + ICONNAME_CALLINGCARD_ONLINE, + ICONNAME_CALLINGCARD_OFFLINE, + ICONNAME_LANDMARK, + ICONNAME_LANDMARK_VISITED, + ICONNAME_SCRIPT, + ICONNAME_CLOTHING, + ICONNAME_OBJECT, + ICONNAME_OBJECT_MULTI, + ICONNAME_NOTECARD, + ICONNAME_BODYPART, + ICONNAME_SNAPSHOT, + + ICONNAME_BODYPART_SHAPE, + ICONNAME_BODYPART_SKIN, + ICONNAME_BODYPART_HAIR, + ICONNAME_BODYPART_EYES, + ICONNAME_CLOTHING_SHIRT, + ICONNAME_CLOTHING_PANTS, + ICONNAME_CLOTHING_SHOES, + ICONNAME_CLOTHING_SOCKS, + ICONNAME_CLOTHING_JACKET, + ICONNAME_CLOTHING_GLOVES, + ICONNAME_CLOTHING_UNDERSHIRT, + ICONNAME_CLOTHING_UNDERPANTS, + ICONNAME_CLOTHING_SKIRT, + ICONNAME_CLOTHING_ALPHA, + ICONNAME_CLOTHING_TATTOO, + + ICONNAME_ANIMATION, + ICONNAME_GESTURE, + + ICONNAME_CLOTHING_PHYSICS, + + ICONNAME_LINKITEM, + ICONNAME_LINKFOLDER, + ICONNAME_MESH, + + ICONNAME_INVALID, + ICONNAME_COUNT, + ICONNAME_NONE = -1 + }; + + // machine transation between type and strings static EType lookup(const std::string& name); static const std::string &lookup(EType type); diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt index bdac2eded7..b8f8b420c3 100755 --- a/indra/llkdu/CMakeLists.txt +++ b/indra/llkdu/CMakeLists.txt @@ -41,7 +41,10 @@ set_source_files_properties(${llkdu_HEADER_FILES} list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES}) if (USE_KDU) - add_library (${LLKDU_LIBRARIES} ${llkdu_SOURCE_FILES}) + add_library (llkdu ${llkdu_SOURCE_FILES}) + + target_link_libraries(llkdu + ${KDU_LIBRARY}) # Add tests if (LL_TESTS) diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 5865ae030c..0614fd92ef 100755 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -7,6 +7,7 @@ include(LLCommon) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ) set(llmath_SOURCE_FILES @@ -99,6 +100,10 @@ list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) add_library (llmath ${llmath_SOURCE_FILES}) +target_link_libraries(llmath + ${LLCOMMON_LIBRARIES} + ) + # Add tests if (LL_TESTS) include(LLAddBuildTest) diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 02c8d2b86f..3f06e6b99e 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -6066,12 +6066,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) S32 max_t = volume->getPath().mPath.size(); // S32 i; - S32 num_vertices = 0, num_indices = 0; S32 grid_size = (profile.size()-1)/4; - S32 quad_count = (grid_size * grid_size); - - num_vertices = (grid_size+1)*(grid_size+1); - num_indices = quad_count * 4; LLVector4a& min = mExtents[0]; LLVector4a& max = mExtents[1]; diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index d98781e9e6..1a90c32fe4 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -218,6 +218,9 @@ add_library (llmessage ${llmessage_SOURCE_FILES}) target_link_libraries( llmessage ${CURL_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${LLVFS_LIBRARES} + ${LLMATH_LIBRARIES} ${CARES_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} @@ -243,7 +246,7 @@ if (LL_TESTS) ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} - ${GOOGLEMOCK_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} ) LL_ADD_INTEGRATION_TEST( diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 8f91d2a23f..9a68093427 100755 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -435,8 +435,10 @@ void LLAvatarNameCache::cleanupClass() void LLAvatarNameCache::importFile(std::istream& istr) { LLSD data; - S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); - if (parse_count < 1) return; + if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr)) + { + return; + } // by convention LLSD storage is a map // we only store one entry in the map diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 3fb36eecf0..267c48e1d2 100755 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -308,8 +308,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& bool LLCacheName::importFile(std::istream& istr) { LLSD data; - if(LLSDSerialize::fromXMLDocument(data, istr) < 1) + if(LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr)) + { return false; + } // We'll expire entries more than a week old U32 now = (U32)time(NULL); diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 8ffa8e4271..47041a2880 100755 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -175,9 +175,11 @@ void LLCurl::Responder::completedRaw( { LLSD content; LLBufferStream istr(channels, buffer.get()); - if (!LLSDSerialize::fromXML(content, istr)) + const bool emit_errors = false; + if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors)) { llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + content["reason"] = reason; } completed(status, reason, content); diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index d6ed08055e..7dcf160c9b 100755 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -747,9 +747,9 @@ LLAssetRequest* LLHTTPAssetStorage::findNextRequest(LLAssetStorage::request_list request_list_t::iterator running_end = running.end(); request_list_t::iterator pending_iter = pending.begin(); - request_list_t::iterator pending_end = pending.end(); + // Loop over all pending requests until we miss finding it in the running list. - for (; pending_iter != pending_end; ++pending_iter) + for (; pending_iter != pending.end(); ++pending_iter) { LLAssetRequest* req = *pending_iter; // Look for this pending request in the running list. diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0c325a68aa..3561459bb4 100755 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -222,7 +222,11 @@ static void request( { if (!LLHTTPClient::hasPump()) { - responder->completed(U32_MAX, "No pump", LLSD()); + if (responder) + { + responder->completed(U32_MAX, "No pump", LLSD()); + } + delete body_injector; return; } LLPumpIO::chain_t chain; @@ -230,8 +234,13 @@ static void request( LLURLRequest* req = new LLURLRequest(method, url); if(!req->isValid())//failed { - delete req ; - return ; + if (responder) + { + responder->completed(498, "Internal Error - curl failure", LLSD()); + } + delete req; + delete body_injector; + return; } req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index f5d7a9abb6..0b59209af1 100755 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -43,8 +43,11 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) { LLSD empty_pragma_header = headers; - // as above - empty_pragma_header["Pragma"] = " "; + if (!empty_pragma_header.has("Pragma")) + { + // as above + empty_pragma_header["Pragma"] = " "; + } LLHTTPClient::get(url, responder, empty_pragma_header); } diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 0287026659..2043bae5e7 100755 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -592,6 +592,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( PUMP_DEBUG; apr_pool_t* new_pool = NULL; apr_status_t status = apr_pool_create(&new_pool, mPool); + if(ll_apr_warn_status(status)) + { + if(new_pool) + { + apr_pool_destroy(new_pool); + } + return STATUS_ERROR; + } + apr_socket_t* socket = NULL; status = apr_socket_accept( &socket, diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index 7b796a0fa8..1cf940918b 100755 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -28,95 +28,98 @@ #define LL_LLREGIONFLAGS_H // Can you be hurt here? Should health be on? -const U32 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0); +const U64 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0); // Can you make landmarks here? -const U32 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1); +const U64 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1); // Do we reset the home position when someone teleports away from here? -const U32 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2); +const U64 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2); // Do we reset the home position when someone teleports away from here? -const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3); +const U64 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3); // Does the sun move? -const U32 REGION_FLAGS_SUN_FIXED = (1 << 4); +const U64 REGION_FLAGS_SUN_FIXED = (1 << 4); // Can't change the terrain heightfield, even on owned parcels, // but can plant trees and grass. -const U32 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6); +const U64 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6); // Can't release, sell, or buy land. -const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); +const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); // All content wiped once per night -const U32 REGION_FLAGS_SANDBOX = (1 << 8); -const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies -const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); -const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics -const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15); -const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); -const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17); -const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18); +const U64 REGION_FLAGS_SANDBOX = (1 << 8); +const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies +const U64 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); +const U64 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics +const U64 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15); +const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); +const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17); +const U64 REGION_FLAGS_BLOCK_DWELL = (1 << 18); // Is flight allowed? -const U32 REGION_FLAGS_BLOCK_FLY = (1 << 19); +const U64 REGION_FLAGS_BLOCK_FLY = (1 << 19); // Is direct teleport (p2p) allowed? -const U32 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20); +const U64 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20); // Is there an administrative override on scripts in the region at the // moment. This is the similar skip scripts, except this flag is // presisted in the database on an estate level. -const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21); +const U64 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21); -const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22); +const U64 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22); -const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23); +const U64 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23); -const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); +const U64 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); -const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28); +const U64 REGION_FLAGS_ALLOW_VOICE = (1 << 28); -const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29); -const U32 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30); +const U64 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29); +const U64 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30); -const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK | +const U64 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME | REGION_FLAGS_ALLOW_PARCEL_CHANGES | REGION_FLAGS_ALLOW_VOICE; -const U32 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT; -const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK +const U64 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT; +const U64 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME; -const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE +const U64 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE | REGION_FLAGS_SUN_FIXED | REGION_FLAGS_DENY_ANONYMOUS | REGION_FLAGS_DENY_AGEUNVERIFIED; -inline BOOL is_prelude( U32 flags ) +inline BOOL is_prelude( U64 flags ) { // definition of prelude does not depend on fixed-sun return 0 == (flags & REGION_FLAGS_PRELUDE_UNSET) && 0 != (flags & REGION_FLAGS_PRELUDE_SET); } -inline U32 set_prelude_flags(U32 flags) +inline U64 set_prelude_flags(U64 flags) { // also set the sun-fixed flag return ((flags & ~REGION_FLAGS_PRELUDE_UNSET) | (REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED)); } -inline U32 unset_prelude_flags(U32 flags) +inline U64 unset_prelude_flags(U64 flags) { // also unset the fixed-sun flag return ((flags | REGION_FLAGS_PRELUDE_UNSET) & ~(REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED)); } +// Region protocols +const U64 REGION_PROTOCOLS_AGENT_APPEARANCE_SERVICE = (1 << 0); + // estate constants. Need to match first few etries in indra.estate table. const U32 ESTATE_ALL = 0; // will not match in db, reserved key for logic const U32 ESTATE_MAINLAND = 1; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 227efdb07a..627d591839 100755 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -174,6 +174,10 @@ LLURLRequest::~LLURLRequest() void LLURLRequest::setURL(const std::string& url) { mDetail->mURL = url; + if (url.empty()) + { + llwarns << "empty URL specified" << llendl; + } } std::string LLURLRequest::getURL() const diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index d7658862da..39cfb6019e 100755 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -279,6 +279,8 @@ char const* const _PREHASH_GrabOffset = LLMessageStringTable::getInstance()->get char const* const _PREHASH_SimPort = LLMessageStringTable::getInstance()->getString("SimPort"); char const* const _PREHASH_PricePerMeter = LLMessageStringTable::getInstance()->getString("PricePerMeter"); char const* const _PREHASH_RegionFlags = LLMessageStringTable::getInstance()->getString("RegionFlags"); +char const* const _PREHASH_RegionFlagsExtended = LLMessageStringTable::getInstance()->getString("RegionFlagsExtended"); +char const* const _PREHASH_RegionProtocols = LLMessageStringTable::getInstance()->getString("RegionProtocols"); char const* const _PREHASH_VoteResult = LLMessageStringTable::getInstance()->getString("VoteResult"); char const* const _PREHASH_ParcelDirFeeEstimate = LLMessageStringTable::getInstance()->getString("ParcelDirFeeEstimate"); char const* const _PREHASH_ModifyBlock = LLMessageStringTable::getInstance()->getString("ModifyBlock"); @@ -305,6 +307,8 @@ char const* const _PREHASH_ViewerStartAuction = LLMessageStringTable::getInstanc char const* const _PREHASH_StartAuction = LLMessageStringTable::getInstance()->getString("StartAuction"); char const* const _PREHASH_DuplicateFlags = LLMessageStringTable::getInstance()->getString("DuplicateFlags"); char const* const _PREHASH_RegionInfo2 = LLMessageStringTable::getInstance()->getString("RegionInfo2"); +char const* const _PREHASH_RegionInfo3 = LLMessageStringTable::getInstance()->getString("RegionInfo3"); +char const* const _PREHASH_RegionInfo4 = LLMessageStringTable::getInstance()->getString("RegionInfo4"); char const* const _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextColor"); char const* const _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID"); char const* const _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter"); @@ -1376,3 +1380,6 @@ char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->get char const* const _PREHASH_SeeAVs = LLMessageStringTable::getInstance()->getString("SeeAVs"); char const* const _PREHASH_AnyAVSounds = LLMessageStringTable::getInstance()->getString("AnyAVSounds"); char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->getString("GroupAVSounds"); +char const* const _PREHASH_AppearanceData = LLMessageStringTable::getInstance()->getString("AppearanceData"); +char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance()->getString("AppearanceVersion"); +char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index da2b613f53..573e10dc0b 100755 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -279,6 +279,8 @@ extern char const* const _PREHASH_GrabOffset; extern char const* const _PREHASH_SimPort; extern char const* const _PREHASH_PricePerMeter; extern char const* const _PREHASH_RegionFlags; +extern char const* const _PREHASH_RegionFlagsExtended; +extern char const* const _PREHASH_RegionProtocols; extern char const* const _PREHASH_VoteResult; extern char const* const _PREHASH_ParcelDirFeeEstimate; extern char const* const _PREHASH_ModifyBlock; @@ -305,6 +307,8 @@ extern char const* const _PREHASH_ViewerStartAuction; extern char const* const _PREHASH_StartAuction; extern char const* const _PREHASH_DuplicateFlags; extern char const* const _PREHASH_RegionInfo2; +extern char const* const _PREHASH_RegionInfo3; +extern char const* const _PREHASH_RegionInfo4; extern char const* const _PREHASH_TextColor; extern char const* const _PREHASH_SlaveID; extern char const* const _PREHASH_Charter; @@ -1376,4 +1380,7 @@ extern char const* const _PREHASH_ProductSKU; extern char const* const _PREHASH_SeeAVs; extern char const* const _PREHASH_AnyAVSounds; extern char const* const _PREHASH_GroupAVSounds; +extern char const* const _PREHASH_AppearanceData; +extern char const* const _PREHASH_AppearanceVersion; +extern char const* const _PREHASH_CofVersion; #endif diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index 7c3def6024..87cbafa404 100755 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -47,37 +47,6 @@ namespace tut { - LLSD storage; - - class LLSDStorageNode : public LLHTTPNode - { - public: - LLSD simpleGet() const { return storage; } - LLSD simplePut(const LLSD& value) const { storage = value; return LLSD(); } - }; - - class ErrorNode : public LLHTTPNode - { - public: - void get(ResponsePtr r, const LLSD& context) const - { r->status(599, "Intentional error"); } - void post(ResponsePtr r, const LLSD& context, const LLSD& input) const - { r->status(input["status"], input["reason"]); } - }; - - class TimeOutNode : public LLHTTPNode - { - public: - void get(ResponsePtr r, const LLSD& context) const - { - /* do nothing, the request will eventually time out */ - } - }; - - LLHTTPRegistration<LLSDStorageNode> gStorageNode("/test/storage"); - LLHTTPRegistration<ErrorNode> gErrorNode("/test/error"); - LLHTTPRegistration<TimeOutNode> gTimeOutNode("/test/timeout"); - struct HTTPClientTestData { public: @@ -91,7 +60,6 @@ namespace tut ensure("Set environment variable PORT to local test server port", PORT); apr_pool_create(&mPool, NULL); LLCurl::initClass(false); - mServerPump = new LLPumpIO(mPool); mClientPump = new LLPumpIO(mPool); LLHTTPClient::setPump(*mClientPump); @@ -99,20 +67,11 @@ namespace tut ~HTTPClientTestData() { - delete mServerPump; delete mClientPump; LLProxy::cleanupClass(); apr_pool_destroy(mPool); } - void setupTheServer() - { - LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888); - - LLHTTPStandardServices::useServices(); - LLHTTPRegistrar::buildAllServices(root); - } - void runThePump(float timeout = 100.0f) { LLTimer timer; @@ -120,11 +79,7 @@ namespace tut while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired()) { - if (mServerPump) - { - mServerPump->pump(); - mServerPump->callback(); - } + LLFrameTimer::updateFrameTime(); if (mClientPump) { mClientPump->pump(); @@ -133,18 +88,11 @@ namespace tut } } - void killServer() - { - delete mServerPump; - mServerPump = NULL; - } - const char* const PORT; const std::string local_server; private: apr_pool_t* mPool; - LLPumpIO* mServerPump; LLPumpIO* mClientPump; protected: @@ -288,14 +236,12 @@ namespace tut sd["list"][1]["three"] = 3; sd["list"][1]["four"] = 4; - setupTheServer(); - - LLHTTPClient::post("http://localhost:8888/web/echo", sd, newResult()); + LLHTTPClient::post(local_server + "web/echo", sd, newResult()); runThePump(); ensureStatusOK(); ensure_equals("echoed result matches", getResult(), sd); } - + template<> template<> void HTTPClientTestObject::test<4>() { @@ -303,12 +249,11 @@ namespace tut sd["message"] = "This is my test message."; - setupTheServer(); - LLHTTPClient::put("http://localhost:8888/test/storage", sd, newResult()); + LLHTTPClient::put(local_server + "test/storage", sd, newResult()); runThePump(); ensureStatusOK(); - LLHTTPClient::get("http://localhost:8888/test/storage", newResult()); + LLHTTPClient::get(local_server + "test/storage", newResult()); runThePump(); ensureStatusOK(); ensure_equals("echoed result matches", getResult(), sd); @@ -322,9 +267,7 @@ namespace tut sd["status"] = 543; sd["reason"] = "error for testing"; - setupTheServer(); - - LLHTTPClient::post("http://localhost:8888/test/error", sd, newResult()); + LLHTTPClient::post(local_server + "test/error", sd, newResult()); runThePump(); ensureStatusError(); ensure_contains("reason", mReason, sd["reason"]); @@ -333,23 +276,16 @@ namespace tut template<> template<> void HTTPClientTestObject::test<6>() { - setupTheServer(); - - LLHTTPClient::get("http://localhost:8888/test/timeout", newResult()); - runThePump(1.0f); - killServer(); - runThePump(); + const F32 timeout = 1.0f; + LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout); + runThePump(timeout * 5.0f); ensureStatusError(); - ensure_equals("reason", mReason, "STATUS_ERROR"); + ensure_equals("reason", mReason, "STATUS_EXPIRED"); } template<> template<> void HTTPClientTestObject::test<7>() { - // Can not use the little mini server. The blocking request - // won't ever let it run. Instead get from a known LLSD - // source and compare results with the non-blocking get which - // is tested against the mini server earlier. LLHTTPClient::get(local_server, newResult()); runThePump(); ensureStatusOK(); diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index fe4f3a8c01..e45249b1cb 100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -39,6 +39,9 @@ sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse from indra.base import llsd from testrunner import freeport, run, debug, VERBOSE +import time + +_storage=None class TestHTTPRequestHandler(BaseHTTPRequestHandler): """This subclass of BaseHTTPRequestHandler is to receive and echo @@ -90,21 +93,14 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): # Read the provided POST data. self.answer(self.read_xml()) + def do_PUT(self): + # Read the provided PUT data. + self.answer(self.read_xml()) + def answer(self, data, withdata=True): + global _storage debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path) - if "fail" not in self.path: - data = data.copy() # we're going to modify - # Ensure there's a "reply" key in data, even if there wasn't before - data["reply"] = data.get("reply", llsd.LLSD("success")) - response = llsd.format_xml(data) - debug("success: %s", response) - self.send_response(200) - self.send_header("Content-type", "application/llsd+xml") - self.send_header("Content-Length", str(len(response))) - self.end_headers() - if withdata: - self.wfile.write(response) - else: # fail requested + if "fail" in self.path or "test/error" in self.path: # fail requested status = data.get("status", 500) # self.responses maps an int status to a (short, long) pair of # strings. We want the longer string. That's why we pass a string @@ -117,6 +113,30 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): "without providing a reason" % status))[1]) debug("fail requested: %s: %r", status, reason) self.send_error(status, reason) + else: + if "web/echo" in self.path: + pass + elif "test/timeout" in self.path: + time.sleep(5.0) + return + elif "test/storage" in self.path: + if "GET" == self.command: + data = _storage + else: + _storage = data + data = "ok" + else: + data = data.copy() # we're going to modify + # Ensure there's a "reply" key in data, even if there wasn't before + data["reply"] = data.get("reply", llsd.LLSD("success")) + response = llsd.format_xml(data) + debug("success: %s", response) + self.send_response(200) + self.send_header("Content-type", "application/llsd+xml") + self.send_header("Content-Length", str(len(response))) + self.end_headers() + if withdata: + self.wfile.write(response) if not VERBOSE: # When VERBOSE is set, skip both these overrides because they exist to diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 1353b7a458..75d89aac78 100755 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -22,6 +22,10 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLQTWEBKIT_INCLUDE_DIR} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llplugin_SOURCE_FILES llpluginclassmedia.cpp diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 71a6145b58..a4da7674d5 100755 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -31,6 +31,7 @@ #include "llpluginprocessparent.h" #include "llpluginmessagepipe.h" #include "llpluginmessageclasses.h" +#include "llsdserialize.h" #include "stringize.h" #include "llapr.h" @@ -836,7 +837,7 @@ void LLPluginProcessParent::receiveMessageRaw(const std::string &message) LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; LLPluginMessage parsed; - if(parsed.parse(message) != -1) + if(LLSDParser::PARSE_FAILURE != parsed.parse(message)) { if(parsed.hasValue("blocking_request")) { diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt index 8183467dc5..03412d95d5 100755 --- a/indra/llplugin/slplugin/CMakeLists.txt +++ b/indra/llplugin/slplugin/CMakeLists.txt @@ -12,6 +12,9 @@ include_directories( ${LLMESSAGE_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) if (DARWIN) include(CMakeFindFrameworks) diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index e4d9de7eb6..1768a06a27 100755 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -14,10 +14,14 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada ${LIBS_PREBUILT_DIR}/include/collada/1.4 ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} + ) set(llprimitive_SOURCE_FILES llmaterialtable.cpp @@ -59,6 +63,15 @@ list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES}) add_library (llprimitive ${llprimitive_SOURCE_FILES}) +target_link_libraries(llprimitive + ${LLCOMMON_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLPHYSICSEXTENSIONS_LIBRARIES} + ) + + #add unit tests if (LL_TESTS) INCLUDE(LLAddBuildTest) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 946251f383..c340fc2d35 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -38,6 +38,7 @@ #include "lldatapacker.h" #include "llsdutil_math.h" #include "llprimtexturelist.h" +#include "imageids.h" /** * exported constants @@ -1230,94 +1231,78 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const return FALSE; } -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name) +S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec) { - return(unpackTEMessage(mesgsys,block_name,-1)); -} - -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num) -{ - // use a negative block_num to indicate a single-block read (a non-variable block) S32 retval = 0; - const U32 MAX_TES = 32; - - // Avoid construction of 32 UUIDs per call. JC - - U8 image_data[MAX_TES*16]; - U8 colors[MAX_TES*4]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; - U8 glow[MAX_TES]; - - const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; - U8 *cur_ptr = packed_buffer; - - U32 size; - U32 face_count = 0; if (block_num < 0) { - size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); + tec.size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); } else { - size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); + tec.size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); } - if (size == 0) + if (tec.size == 0) { + tec.face_count = 0; return retval; } if (block_num < 0) { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, 0, MAX_TE_BUFFER); + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER); } else { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, block_num, MAX_TE_BUFFER); + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER); } - face_count = getNumTEs(); + tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES); - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); + U8 *cur_ptr = tec.packed_buffer; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8); - + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8); + + retval = 1; + return retval; +} + +S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec) +{ + S32 retval = 0; + LLColor4 color; LLColor4U coloru; - for (U32 i = 0; i < face_count; i++) - { - retval |= setTETexture(i, ((LLUUID*)image_data)[i]); - retval |= setTEScale(i, scale_s[i], scale_t[i]); - retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); - retval |= setTEBumpShinyFullbright(i, bump[i]); - retval |= setTEMediaTexGen(i, media_flags[i]); - retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); - coloru = LLColor4U(colors + 4*i); + for (U32 i = 0; i < tec.face_count; i++) + { + LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; + retval |= setTETexture(i, req_id); + retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]); + retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, tec.bump[i]); + retval |= setTEMediaTexGen(i, tec.media_flags[i]); + retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF); + coloru = LLColor4U(tec.colors + 4*i); // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) // as all zeros. However, the subtraction and addition must be done in unsigned @@ -1334,6 +1319,15 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam return retval; } +S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num) +{ + LLTEContents tec; + S32 retval = parseTEMessage(mesgsys, block_name, block_num, tec); + if (!retval) + return retval; + return applyParsedTEMessage(tec); +} + S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { // use a negative block_num to indicate a single-block read (a non-variable block) diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 8dcaa8c740..6a8b59c81c 100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -289,6 +289,34 @@ public: }; +// This code is not naming-standards compliant. Leaving it like this for +// now to make the connection to code in +// BOOL packTEMessage(LLDataPacker &dp) const; +// more obvious. This should be refactored to remove the duplication, at which +// point we can fix the names as well. +// - Vir +struct LLTEContents +{ + static const U32 MAX_TES = 32; + + U8 image_data[MAX_TES*16]; + U8 colors[MAX_TES*4]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + U8 glow[MAX_TES]; + + static const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + + U32 size; + U32 face_count; +}; + class LLPrimitive : public LLXform { public: @@ -360,9 +388,10 @@ public: S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name); S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks BOOL unpackTEMessage(LLDataPacker &dp); + S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec); + S32 applyParsedTEMessage(LLTEContents& tec); #ifdef CHECK_FOR_FINITE inline void setPosition(const LLVector3& pos); diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 516af93316..669b70aa43 100755 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -3,7 +3,7 @@ project(llrender) include(00-Common) -include(FindOpenGL) +include(OpenGL) include(FreeType) include(LLCommon) include(LLImage) @@ -25,21 +25,31 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llrender_SOURCE_FILES llcubemap.cpp + llfontbitmapcache.cpp llfontfreetype.cpp llfontgl.cpp - llfontbitmapcache.cpp llfontregistry.cpp + llgl.cpp llgldbg.cpp llglslshader.cpp + llgltexture.cpp llimagegl.cpp llpostprocess.cpp + llrender.cpp + llrender2dutils.cpp llrendernavprim.cpp llrendersphere.cpp + llrendertarget.cpp llshadermgr.cpp lltexture.cpp + lluiimage.cpp llvertexbuffer.cpp ) @@ -56,14 +66,17 @@ set(llrender_HEADER_FILES llglheaders.h llglslshader.h llglstates.h + llgltexture.h llgltypes.h llimagegl.h llpostprocess.h llrender.h + llrender2dutils.h llrendernavprim.h llrendersphere.h llshadermgr.h lltexture.h + lluiimage.h llvertexbuffer.h ) @@ -72,33 +85,47 @@ set_source_files_properties(${llrender_HEADER_FILES} list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES}) -if (SERVER AND NOT WINDOWS AND NOT DARWIN) - copy_server_sources( - llgl - llrender - ) - - - set_source_files_properties( - ${server_SOURCE_FILES} - PROPERTIES - COMPILE_FLAGS "-DLL_MESA=1 -DLL_MESA_HEADLESS=1" - ) +if (BUILD_HEADLESS) add_library (llrenderheadless ${llrender_SOURCE_FILES} - ${server_SOURCE_FILES} ) -else (SERVER AND NOT WINDOWS AND NOT DARWIN) - list(APPEND llrender_SOURCE_FILES - llgl.cpp - llrender.cpp - llrendertarget.cpp - ) -endif (SERVER AND NOT WINDOWS AND NOT DARWIN) + + set_property(TARGET llrenderheadless + PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1 + ) + + target_link_libraries(llrenderheadless + ${LLCOMMON_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLRENDER_HEADLESS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLWINDOW_HEADLESS_LIBRARIES} + ${OPENGL_HEADLESS_LIBRARIES}) + +endif (BUILD_HEADLESS) + add_library (llrender ${llrender_SOURCE_FILES}) + +if (SDL_FOUND) + set_property(TARGET llrender + PROPERTY COMPILE_DEFINITIONS LL_SDL=1 + ) +endif (SDL_FOUND) + # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level target_link_libraries(llrender - llimage + ${LLCOMMON_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLRENDER_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLWINDOW_LIBRARIES} ${FREETYPE_LIBRARIES} ${OPENGL_LIBRARIES}) + diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 66d4ad2d87..058bef43a5 100755 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -485,14 +485,11 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const if (mFTFace == NULL) return; - int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT ); - llassert(!error); + llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT) ); - error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); + llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) ); mRenderGlyphCount++; - - llassert(!error); } void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 8772779645..c4f36cabd0 100755 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -541,7 +541,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch BOOL clip = FALSE; F32 cur_x = 0; - F32 drawn_x = 0; S32 start_of_last_word = 0; BOOL in_word = FALSE; @@ -629,7 +628,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch // Round after kerning. cur_x = (F32)llround(cur_x); - drawn_x = cur_x; } if( clip ) diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index b5bdba996f..f5ca8d5b04 100755 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -223,7 +223,7 @@ std::string currentOsName() return "Windows"; #elif LL_DARWIN return "Mac"; -#elif LL_SDL +#elif LL_SDL || LL_MESA_HEADLESS return "Linux"; #else return ""; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index fd668f2d34..6c798aa4ed 100755 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1485,6 +1485,7 @@ void assert_glerror() void clear_glerror() { glGetError(); + glGetError(); } /////////////////////////////////////////////////////////////// diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 5c68cb46eb..cf21101e35 100755 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -159,6 +159,8 @@ public: extern LLGLSLShader gUIProgram; //output vec4(color.rgb,color.a*tex0[tc0].a) extern LLGLSLShader gSolidColorProgram; +//Alpha mask shader (declared here so llappearance can access properly) +extern LLGLSLShader gAlphaMaskProgram; #endif diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp new file mode 100644 index 0000000000..d06ed5e57b --- /dev/null +++ b/indra/llrender/llgltexture.cpp @@ -0,0 +1,396 @@ +/** + * @file llgltexture.cpp + * @brief Opengl texture implementation + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" +#include "llgltexture.h" + + +// static +S32 LLGLTexture::getTotalNumOfCategories() +{ + return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; +} + +// static +//index starts from zero. +S32 LLGLTexture::getIndexFromCategory(S32 category) +{ + return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; +} + +//static +S32 LLGLTexture::getCategoryFromIndex(S32 index) +{ + return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; +} + +LLGLTexture::LLGLTexture(BOOL usemipmaps) +{ + init(); + mUseMipMaps = usemipmaps; +} + +LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) +{ + init(); + mFullWidth = width ; + mFullHeight = height ; + mUseMipMaps = usemipmaps; + mComponents = components ; + setTexelsPerImage(); +} + +LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) +{ + init(); + mUseMipMaps = usemipmaps ; + // Create an empty image of the specified size and width + mGLTexturep = new LLImageGL(raw, usemipmaps) ; +} + +LLGLTexture::~LLGLTexture() +{ + cleanup(); +} + +void LLGLTexture::init() +{ + mBoostLevel = LLGLTexture::BOOST_NONE; + + mFullWidth = 0; + mFullHeight = 0; + mTexelsPerImage = 0 ; + mUseMipMaps = FALSE ; + mComponents = 0 ; + + mTextureState = NO_DELETE ; + mDontDiscard = FALSE; + mNeedsGLTexture = FALSE ; +} + +void LLGLTexture::cleanup() +{ + if(mGLTexturep) + { + mGLTexturep->cleanup(); + } +} + +// virtual +void LLGLTexture::dump() +{ + if(mGLTexturep) + { + mGLTexturep->dump(); + } +} + +void LLGLTexture::setBoostLevel(S32 level) +{ + if(mBoostLevel != level) + { + mBoostLevel = level ; + if(mBoostLevel != LLGLTexture::BOOST_NONE) + { + setNoDelete() ; + } + } +} + +void LLGLTexture::forceActive() +{ + mTextureState = ACTIVE ; +} + +void LLGLTexture::setActive() +{ + if(mTextureState != NO_DELETE) + { + mTextureState = ACTIVE ; + } +} + +//set the texture to stay in memory +void LLGLTexture::setNoDelete() +{ + mTextureState = NO_DELETE ; +} + +void LLGLTexture::generateGLTexture() +{ + if(mGLTexturep.isNull()) + { + mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; + } +} + +LLImageGL* LLGLTexture::getGLTexture() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep ; +} + +BOOL LLGLTexture::createGLTexture() +{ + if(mGLTexturep.isNull()) + { + generateGLTexture() ; + } + + return mGLTexturep->createGLTexture() ; +} + +BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) +{ + llassert(mGLTexturep.notNull()) ; + + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; + + if(ret) + { + mFullWidth = mGLTexturep->getCurrentWidth() ; + mFullHeight = mGLTexturep->getCurrentHeight() ; + mComponents = mGLTexturep->getComponents() ; + setTexelsPerImage(); + } + + return ret ; +} + +void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; +} +void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) +{ + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setAddressMode(mode) ; +} +void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) +{ + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setFilteringOption(option) ; +} + +//virtual +S32 LLGLTexture::getWidth(S32 discard_level) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getWidth(discard_level) ; +} + +//virtual +S32 LLGLTexture::getHeight(S32 discard_level) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getHeight(discard_level) ; +} + +S32 LLGLTexture::getMaxDiscardLevel() const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getMaxDiscardLevel() ; +} +S32 LLGLTexture::getDiscardLevel() const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getDiscardLevel() ; +} +S8 LLGLTexture::getComponents() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getComponents() ; +} + +LLGLuint LLGLTexture::getTexName() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexName() ; +} + +BOOL LLGLTexture::hasGLTexture() const +{ + if(mGLTexturep.notNull()) + { + return mGLTexturep->getHasGLTexture() ; + } + return FALSE ; +} + +BOOL LLGLTexture::getBoundRecently() const +{ + if(mGLTexturep.notNull()) + { + return mGLTexturep->getBoundRecently() ; + } + return FALSE ; +} + +LLTexUnit::eTextureType LLGLTexture::getTarget(void) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getTarget() ; +} + +BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; +} + +BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; +} + +void LLGLTexture::setGLTextureCreated (bool initialized) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setGLTextureCreated (initialized) ; +} + +void LLGLTexture::setCategory(S32 category) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setCategory(category) ; +} + +LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getAddressMode() ; +} + +S32 LLGLTexture::getTextureMemory() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->mTextureMemory ; +} + +LLGLenum LLGLTexture::getPrimaryFormat() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getPrimaryFormat() ; +} + +BOOL LLGLTexture::getIsAlphaMask() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getIsAlphaMask() ; +} + +BOOL LLGLTexture::getMask(const LLVector2 &tc) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getMask(tc) ; +} + +F32 LLGLTexture::getTimePassedSinceLastBound() +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTimePassedSinceLastBound() ; +} +BOOL LLGLTexture::getMissed() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getMissed() ; +} + +BOOL LLGLTexture::isJustBound() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->isJustBound() ; +} + +void LLGLTexture::forceUpdateBindStats(void) const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->forceUpdateBindStats() ; +} + +U32 LLGLTexture::getTexelsInAtlas() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexelsInAtlas() ; +} + +U32 LLGLTexture::getTexelsInGLTexture() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexelsInGLTexture() ; +} + +BOOL LLGLTexture::isGLTextureCreated() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->isGLTextureCreated() ; +} + +S32 LLGLTexture::getDiscardLevelInAtlas() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getDiscardLevelInAtlas() ; +} + +void LLGLTexture::destroyGLTexture() +{ + if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) + { + mGLTexturep->destroyGLTexture() ; + mTextureState = DELETED ; + } +} + +void LLGLTexture::setTexelsPerImage() +{ + S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); + S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); + mTexelsPerImage = (F32)fullwidth * fullheight; +} + + diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h new file mode 100644 index 0000000000..e69b322d60 --- /dev/null +++ b/indra/llrender/llgltexture.h @@ -0,0 +1,199 @@ +/** + * @file llglviewertexture.h + * @brief Object for managing opengl textures + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#ifndef LL_GL_TEXTURE_H +#define LL_GL_TEXTURE_H + +#include "lltexture.h" +#include "llgl.h" + +class LLImageRaw; + +// +//this the parent for the class LLViewerTexture +//through the following virtual functions, the class LLViewerTexture can be reached from /llrender. +// +class LLGLTexture : public LLTexture +{ +public: + enum + { + MAX_IMAGE_SIZE_DEFAULT = 1024, + INVALID_DISCARD_LEVEL = 0x7fff + }; + + enum EBoostLevel + { + BOOST_NONE = 0, + BOOST_AVATAR_BAKED , + BOOST_AVATAR , + BOOST_CLOUDS , + BOOST_SCULPTED , + + BOOST_HIGH = 10, + BOOST_BUMP , + BOOST_TERRAIN , // has to be high priority for minimap / low detail + BOOST_SELECTED , + BOOST_AVATAR_BAKED_SELF , + BOOST_AVATAR_SELF , // needed for baking avatar + BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. + BOOST_HUD , + BOOST_ICON , + BOOST_UI , + BOOST_PREVIEW , + BOOST_MAP , + BOOST_MAP_VISIBLE , + BOOST_MAX_LEVEL, + + //other texture Categories + LOCAL = BOOST_MAX_LEVEL, + AVATAR_SCRATCH_TEX, + DYNAMIC_TEX, + MEDIA, + ATLAS, + OTHER, + MAX_GL_IMAGE_CATEGORY + }; + + typedef enum + { + DELETED = 0, //removed from memory + DELETION_CANDIDATE, //ready to be removed from memory + INACTIVE, //not be used for the last certain period (i.e., 30 seconds). + ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). + NO_DELETE = 99 //stay in memory, can not be removed. + } LLGLTextureState; + + static S32 getTotalNumOfCategories() ; + static S32 getIndexFromCategory(S32 category) ; + static S32 getCategoryFromIndex(S32 index) ; + +protected: + virtual ~LLGLTexture(); + LOG_CLASS(LLGLTexture); + +public: + LLGLTexture(BOOL usemipmaps = TRUE); + LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + + virtual void dump(); // debug info to llinfos + + virtual const LLUUID& getID() const = 0; + + void setBoostLevel(S32 level); + S32 getBoostLevel() { return mBoostLevel; } + + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } + + void generateGLTexture() ; + void destroyGLTexture() ; + + //--------------------------------------------------------------------------------------------- + //functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + /*virtual*/S32 getWidth(S32 discard_level = -1) const; + /*virtual*/S32 getHeight(S32 discard_level = -1) const; + + BOOL hasGLTexture() const ; + LLGLuint getTexName() const ; + BOOL createGLTexture() ; + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER); + + void setFilteringOption(LLTexUnit::eTextureFilterOptions option); + void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); + void setAddressMode(LLTexUnit::eTextureAddressMode mode); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); + void setGLTextureCreated (bool initialized); + void setCategory(S32 category) ; + + LLTexUnit::eTextureAddressMode getAddressMode(void) const ; + S32 getMaxDiscardLevel() const; + S32 getDiscardLevel() const; + S8 getComponents() const; + BOOL getBoundRecently() const; + S32 getTextureMemory() const ; + LLGLenum getPrimaryFormat() const; + BOOL getIsAlphaMask() const ; + LLTexUnit::eTextureType getTarget(void) const ; + BOOL getMask(const LLVector2 &tc); + F32 getTimePassedSinceLastBound(); + BOOL getMissed() const ; + BOOL isJustBound()const ; + void forceUpdateBindStats(void) const; + + U32 getTexelsInAtlas() const ; + U32 getTexelsInGLTexture() const ; + BOOL isGLTextureCreated() const ; + S32 getDiscardLevelInAtlas() const ; + LLGLTextureState getTextureState() const { return mTextureState; } + + //--------------------------------------------------------------------------------------------- + //end of functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + + //----------------- + /*virtual*/ void setActive() ; + void forceActive() ; + void setNoDelete() ; + void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } + BOOL getDontDiscard() const { return mDontDiscard; } + //----------------- + +private: + void cleanup(); + void init(); + +protected: + void setTexelsPerImage(); + + //note: do not make this function public. + /*virtual*/ LLImageGL* getGLTexture() const ; + +protected: + S32 mBoostLevel; // enum describing priority level + S32 mFullWidth; + S32 mFullHeight; + BOOL mUseMipMaps; + S8 mComponents; + F32 mTexelsPerImage; // Texels per image. + mutable S8 mNeedsGLTexture; + + //GL texture + LLPointer<LLImageGL> mGLTexturep ; + S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + +protected: + LLGLTextureState mTextureState ; + + +}; + +#endif // LL_GL_TEXTURE_H + diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 552dac518a..5c171d372c 100755..100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -74,6 +74,9 @@ S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; S32 LLImageGL::sMaxCategories = 1 ; +//optimization for when we don't need to calculate mIsMask +BOOL LLImageGL::sSkipAnalyzeAlpha; + //------------------------ //**************************************************************************************************** //End for texture auditing use only @@ -169,8 +172,9 @@ BOOL is_little_endian() return (*c == 0x78) ; } //static -void LLImageGL::initClass(S32 num_catagories) +void LLImageGL::initClass(S32 num_catagories, BOOL skip_analyze_alpha /* = false */) { + sSkipAnalyzeAlpha = skip_analyze_alpha; } //static @@ -611,14 +615,16 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) setImage(rawdata, FALSE); } +static LLFastTimer::DeclareTimer FTM_SET_IMAGE("setImage"); void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { + LLFastTimer t(FTM_SET_IMAGE); bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { is_compressed = true; } - + if (mUseMipMaps) @@ -744,8 +750,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = width, h = height; const U8* prev_mip_data = 0; const U8* cur_mip_data = 0; - S32 prev_mip_size = 0; +#ifdef SHOW_ASSERT S32 cur_mip_size = 0; +#endif mMipLevels = nummips; @@ -754,18 +761,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) if (m==0) { cur_mip_data = data_in; +#ifdef SHOW_ASSERT cur_mip_size = width * height * mComponents; +#endif } else { S32 bytes = w * h * mComponents; +#ifdef SHOW_ASSERT llassert(prev_mip_data); - llassert(prev_mip_size == bytes*4); + llassert(cur_mip_size == bytes*4); +#endif U8* new_data = new U8[bytes]; llassert_always(new_data); LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents); cur_mip_data = new_data; +#ifdef SHOW_ASSERT cur_mip_size = bytes; +#endif } llassert(w > 0 && h > 0 && cur_mip_data); { @@ -798,7 +811,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) delete[] prev_mip_data; } prev_mip_data = cur_mip_data; - prev_mip_size = cur_mip_size; w >>= 1; h >>= 1; } @@ -1059,8 +1071,10 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } // static +static LLFastTimer::DeclareTimer FTM_GENERATE_TEXTURES("generate textures"); void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures) { + LLFastTimer t(FTM_GENERATE_TEXTURES); bool empty = true; dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format); @@ -1140,8 +1154,10 @@ void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip } // static +static LLFastTimer::DeclareTimer FTM_SET_MANUAL_IMAGE("setManualImage"); void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) { + LLFastTimer t(FTM_SET_MANUAL_IMAGE); bool use_scratch = false; U32* scratch = NULL; if (LLRender::sGLCoreProfile) @@ -1245,9 +1261,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt //create an empty GL texture: just create a texture name //the texture is assiciate with some image by calling glTexImage outside LLImageGL +static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE1("createGLTexture()"); BOOL LLImageGL::createGLTexture() { - if (gHeadlessClient) return FALSE; + LLFastTimer t(FTM_CREATE_GL_TEXTURE1); if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; @@ -1275,9 +1292,10 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } +static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE2("createGLTexture(raw)"); BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) { - if (gHeadlessClient) return FALSE; + LLFastTimer t(FTM_CREATE_GL_TEXTURE2); if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; @@ -1349,8 +1367,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } +static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)"); BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { + LLFastTimer t(FTM_CREATE_GL_TEXTURE3); llassert(data_in); stop_glerror(); @@ -1727,6 +1747,12 @@ BOOL LLImageGL::getBoundRecently() const return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); } +BOOL LLImageGL::getIsAlphaMask() const +{ + llassert_always(!sSkipAnalyzeAlpha); + return mIsMask; +} + void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target) { mTarget = target; @@ -1824,7 +1850,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) { - if(!mNeedsAlphaAndPickMask) + if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask) { return ; } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index cf3c484c79..57a052b258 100755 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -142,7 +142,7 @@ public: BOOL getHasGLTexture() const { return mTexName != 0; } LLGLuint getTexName() const { return mTexName; } - BOOL getIsAlphaMask() const { return mIsMask; } + BOOL getIsAlphaMask() const; BOOL getIsResident(BOOL test_now = FALSE); // not const @@ -262,11 +262,12 @@ public: #endif public: - static void initClass(S32 num_catagories) ; + static void initClass(S32 num_catagories, BOOL skip_analyze_alpha = false); static void cleanupClass() ; private: static S32 sMaxCategories; + static BOOL sSkipAnalyzeAlpha; //the flag to allow to call readBackRaw(...). //can be removed if we do not use that function at all. diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 4597d06260..c60eb8d9d9 100755 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -357,7 +357,6 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) } // LLRenderTarget is unavailible on the mapserver since it uses FBOs. -#if !LL_MESA_HEADLESS bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) { if (mIndex < 0) return false; @@ -380,7 +379,6 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) return true; } -#endif // LL_MESA_HEADLESS bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp new file mode 100644 index 0000000000..d3cfbaf03a --- /dev/null +++ b/indra/llrender/llrender2dutils.cpp @@ -0,0 +1,1608 @@ +/** + * @file llrender2dutils.cpp + * @brief GL function implementations for immediate-mode gl drawing. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// Linden library includes +#include "v2math.h" +#include "m3math.h" +#include "v4color.h" +#include "llfontgl.h" +#include "llrender.h" +#include "llrect.h" +#include "llgl.h" +#include "lltexture.h" + +// Project includes +#include "llrender2dutils.h" +#include "lluiimage.h" + + +// +// Globals +// +const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); +/*static*/ LLVector2 LLRender2D::sGLScaleFactor(1.f, 1.f); +/*static*/ LLImageProviderInterface* LLRender2D::sImageProvider = NULL; + +// +// Functions +// + +BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) +{ + if (x < left || right < x) return FALSE; + if (y < bottom || top < y) return FALSE; + return TRUE; +} + + +// Puts GL into 2D drawing mode by turning off lighting, setting to an +// orthographic projection, etc. +void gl_state_for_2d(S32 width, S32 height) +{ + stop_glerror(); + F32 window_width = (F32) width;//gViewerWindow->getWindowWidth(); + F32 window_height = (F32) height;//gViewerWindow->getWindowHeight(); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadIdentity(); + gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadIdentity(); + stop_glerror(); +} + + +void gl_draw_x(const LLRect& rect, const LLColor4& color) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv( color.mV ); + + gGL.begin( LLRender::LINES ); + gGL.vertex2i( rect.mLeft, rect.mTop ); + gGL.vertex2i( rect.mRight, rect.mBottom ); + gGL.vertex2i( rect.mLeft, rect.mBottom ); + gGL.vertex2i( rect.mRight, rect.mTop ); + gGL.end(); +} + + +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled) +{ + gGL.color4fv(color.mV); + gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled); +} + +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled) +{ + gGL.pushUIMatrix(); + left += LLFontGL::sCurOrigin.mX; + right += LLFontGL::sCurOrigin.mX; + bottom += LLFontGL::sCurOrigin.mY; + top += LLFontGL::sCurOrigin.mY; + + gGL.loadUIIdentity(); + gl_rect_2d(llfloor((F32)left * LLRender2D::sGLScaleFactor.mV[VX]) - pixel_offset, + llfloor((F32)top * LLRender2D::sGLScaleFactor.mV[VY]) + pixel_offset, + llfloor((F32)right * LLRender2D::sGLScaleFactor.mV[VX]) + pixel_offset, + llfloor((F32)bottom * LLRender2D::sGLScaleFactor.mV[VY]) - pixel_offset, + filled); + gGL.popUIMatrix(); +} + + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) +{ + stop_glerror(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Counterclockwise quad will face the viewer + if( filled ) + { + gGL.begin( LLRender::QUADS ); + gGL.vertex2i(left, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + gGL.end(); + } + else + { + if( gGLManager.mATIOffsetVerticalLines ) + { + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + gGL.begin( LLRender::LINES ); + + // Verticals + gGL.vertex2i(left + 1, top); + gGL.vertex2i(left + 1, bottom); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + + // Horizontals + top--; + right--; + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + + gGL.vertex2i(left, top); + gGL.vertex2i(right, top); + gGL.end(); + } + else + { + top--; + right--; + gGL.begin( LLRender::LINE_STRIP ); + gGL.vertex2i(left, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + gGL.vertex2i(left, top); + gGL.end(); + } + } + stop_glerror(); +} + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled ) +{ + gGL.color4fv( color.mV ); + gl_rect_2d( left, top, right, bottom, filled ); +} + + +void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled ) +{ + gGL.color4fv( color.mV ); + gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); +} + +// Given a rectangle on the screen, draws a drop shadow _outside_ +// the right and bottom edges of it. Along the right it has width "lines" +// and along the bottom it has height "lines". +void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines) +{ + stop_glerror(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // HACK: Overlap with the rectangle by a single pixel. + right--; + bottom++; + lines++; + + LLColor4 end_color = start_color; + end_color.mV[VALPHA] = 0.f; + + gGL.begin(LLRender::QUADS); + + // Right edge, CCW faces screen + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top-lines); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right+lines, bottom); + gGL.vertex2i(right+lines, top-lines); + + // Bottom edge, CCW faces screen + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(right, bottom-lines); + + // bottom left Corner + gGL.color4fv(start_color.mV); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left, bottom); + // make the bottom left corner not sharp + gGL.vertex2i(left+1, bottom-lines+1); + gGL.vertex2i(left+lines, bottom-lines); + + // bottom right corner + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right, bottom-lines); + // make the rightmost corner not sharp + gGL.vertex2i(right+lines-1, bottom-lines+1); + gGL.vertex2i(right+lines, bottom); + + // top right corner + gGL.color4fv(start_color.mV); + gGL.vertex2i( right, top-lines ); + gGL.color4fv(end_color.mV); + gGL.vertex2i( right+lines, top-lines ); + // make the corner not sharp + gGL.vertex2i( right+lines-1, top-1 ); + gGL.vertex2i( right, top ); + + gGL.end(); + stop_glerror(); +} + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) +{ + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) + { + x1++; + x2++; + y1++; + y2++; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.begin(LLRender::LINES); + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.end(); +} + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) +{ + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) + { + x1++; + x2++; + y1++; + y2++; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv( color.mV ); + + gGL.begin(LLRender::LINES); + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.end(); +} + +void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv(color.mV); + + if (filled) + { + gGL.begin(LLRender::TRIANGLES); + } + else + { + gGL.begin(LLRender::LINE_LOOP); + } + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.vertex2i(x3, y3); + gGL.end(); +} + +void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + length = llmin((S32)(max_frac*(right - left)), length); + length = llmin((S32)(max_frac*(top - bottom)), length); + gGL.begin(LLRender::LINES); + gGL.vertex2i(left, top); + gGL.vertex2i(left + length, top); + + gGL.vertex2i(left, top); + gGL.vertex2i(left, top - length); + + gGL.vertex2i(left, bottom); + gGL.vertex2i(left + length, bottom); + + gGL.vertex2i(left, bottom); + gGL.vertex2i(left, bottom + length); + + gGL.vertex2i(right, top); + gGL.vertex2i(right - length, top); + + gGL.vertex2i(right, top); + gGL.vertex2i(right, top - length); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right - length, bottom); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, bottom + length); + gGL.end(); +} + + +void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect ) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); +} + +void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); +} + +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + // scale screen size of borders down + F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); + F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); + + LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); + gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); +} + +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) +{ + stop_glerror(); + + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + // add in offset of current image to current UI translation + const LLVector3 ui_scale = gGL.getUIScale(); + const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); + + F32 uv_width = uv_outer_rect.getWidth(); + F32 uv_height = uv_outer_rect.getHeight(); + + // shrink scaling region to be proportional to clipped image region + LLRectf uv_center_rect( + uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), + uv_outer_rect.mBottom + (center_rect.mTop * uv_height), + uv_outer_rect.mLeft + (center_rect.mRight * uv_width), + uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); + + F32 image_width = image->getWidth(0); + F32 image_height = image->getHeight(0); + + S32 image_natural_width = llround(image_width * uv_width); + S32 image_natural_height = llround(image_height * uv_height); + + LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, + uv_center_rect.mTop * image_height, + uv_center_rect.mRight * image_width, + uv_center_rect.mBottom * image_height); + + { // scale fixed region of image to drawn region + draw_center_rect.mRight += width - image_natural_width; + draw_center_rect.mTop += height - image_natural_height; + + F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); + F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); + + F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); + F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); + + F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + + draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); + draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); + draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); + draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); + } + + LLRectf draw_outer_rect(ui_translation.mV[VX], + ui_translation.mV[VY] + height * ui_scale.mV[VY], + ui_translation.mV[VX] + width * ui_scale.mV[VX], + ui_translation.mV[VY]); + + LLGLSUIDefault gls_ui; + + if (solid_color) + { + if (LLGLSLShader::sNoFixedFunction) + { + gSolidColorProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + } + } + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + const S32 NUM_VERTICES = 9 * 4; // 9 quads + LLVector2 uv[NUM_VERTICES]; + LLVector3 pos[NUM_VERTICES]; + + S32 index = 0; + + gGL.begin(LLRender::QUADS); + { + // draw bottom left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + // draw bottom middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + // draw bottom right + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + // draw left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + // draw middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + // draw right + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + // draw top left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // draw top middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // draw top right + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); + + if (solid_color) + { + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } + } +} + +void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); +} + +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + LLGLSUIDefault gls_ui; + + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + if (degrees == 0.f) + { + const S32 NUM_VERTICES = 4; // 9 quads + LLVector2 uv[NUM_VERTICES]; + LLVector3 pos[NUM_VERTICES]; + + gGL.begin(LLRender::QUADS); + { + LLVector3 ui_scale = gGL.getUIScale(); + LLVector3 ui_translation = gGL.getUITranslation(); + ui_translation.mV[VX] += x; + ui_translation.mV[VY] += y; + ui_translation.scaleVec(ui_scale); + S32 index = 0; + S32 scaled_width = llround(width * ui_scale.mV[VX]); + S32 scaled_height = llround(height * ui_scale.mV[VY]); + + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); + pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); + pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); + index++; + + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); + } + else + { + gGL.pushUIMatrix(); + gGL.translateUI((F32)x, (F32)y, 0.f); + + F32 offset_x = F32(width/2); + F32 offset_y = F32(height/2); + + gGL.translateUI(offset_x, offset_y, 0.f); + + LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + gGL.begin(LLRender::QUADS); + { + LLVector3 v; + + v = LLVector3(offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(-offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(-offset_x, -offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(offset_x, -offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); + gGL.vertex2f(v.mV[0], v.mV[1] ); + } + gGL.end(); + gGL.popUIMatrix(); + } +} + + +void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) +{ + phase = fmod(phase, 1.f); + + S32 shift = S32(phase * 4.f) % 4; + + // Stippled line + LLGLEnable stipple(GL_LINE_STIPPLE); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); + + gGL.flush(); + glLineWidth(2.5f); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(2, 0x3333 << shift); + } + + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv( start.mV ); + gGL.vertex3fv( end.mV ); + } + gGL.end(); + + LLRender2D::setLineWidth(1.f); +} + +void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle) +{ + if (end_angle < start_angle) + { + end_angle += F_TWO_PI; + } + + gGL.pushUIMatrix(); + { + gGL.translateUI(center_x, center_y, 0.f); + + // Inexact, but reasonably fast. + F32 delta = (end_angle - start_angle) / steps; + F32 sin_delta = sin( delta ); + F32 cos_delta = cos( delta ); + F32 x = cosf(start_angle) * radius; + F32 y = sinf(start_angle) * radius; + + if (filled) + { + gGL.begin(LLRender::TRIANGLE_FAN); + gGL.vertex2f(0.f, 0.f); + // make sure circle is complete + steps += 1; + } + else + { + gGL.begin(LLRender::LINE_STRIP); + } + + while( steps-- ) + { + // Successive rotations + gGL.vertex2f( x, y ); + F32 x_new = x * cos_delta - y * sin_delta; + y = x * sin_delta + y * cos_delta; + x = x_new; + } + gGL.end(); + } + gGL.popUIMatrix(); +} + +void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled) +{ + gGL.pushUIMatrix(); + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.translateUI(center_x, center_y, 0.f); + + // Inexact, but reasonably fast. + F32 delta = F_TWO_PI / steps; + F32 sin_delta = sin( delta ); + F32 cos_delta = cos( delta ); + F32 x = radius; + F32 y = 0.f; + + if (filled) + { + gGL.begin(LLRender::TRIANGLE_FAN); + gGL.vertex2f(0.f, 0.f); + // make sure circle is complete + steps += 1; + } + else + { + gGL.begin(LLRender::LINE_LOOP); + } + + while( steps-- ) + { + // Successive rotations + gGL.vertex2f( x, y ); + F32 x_new = x * cos_delta - y * sin_delta; + y = x * sin_delta + y * cos_delta; + x = x_new; + } + gGL.end(); + } + gGL.popUIMatrix(); +} + +// Renders a ring with sides (tube shape) +void gl_deep_circle( F32 radius, F32 depth, S32 steps ) +{ + F32 x = radius; + F32 y = 0.f; + F32 angle_delta = F_TWO_PI / (F32)steps; + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + S32 step = steps + 1; // An extra step to close the circle. + while( step-- ) + { + gGL.vertex3f( x, y, depth ); + gGL.vertex3f( x, y, 0.f ); + + F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta); + y = x * sinf(angle_delta) + y * cosf(angle_delta); + x = x_new; + } + } + gGL.end(); +} + +void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ) +{ + gGL.pushUIMatrix(); + { + gGL.translateUI(0.f, 0.f, -width / 2); + if( render_center ) + { + gGL.color4fv(center_color.mV); + gGL.diffuseColor4fv(center_color.mV); + gl_deep_circle( radius, width, steps ); + } + else + { + gGL.diffuseColor4fv(side_color.mV); + gl_washer_2d(radius, radius - width, steps, side_color, side_color); + gGL.translateUI(0.f, 0.f, width); + gl_washer_2d(radius - width, radius, steps, side_color, side_color); + } + } + gGL.popUIMatrix(); +} + +// Draw gray and white checkerboard with black border +void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) +{ + if (!LLGLSLShader::sNoFixedFunction) + { + // Initialize the first time this is called. + const S32 PIXELS = 32; + static GLubyte checkerboard[PIXELS * PIXELS]; + static BOOL first = TRUE; + if( first ) + { + for( S32 i = 0; i < PIXELS; i++ ) + { + for( S32 j = 0; j < PIXELS; j++ ) + { + checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; + } + } + first = FALSE; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // ...white squares + gGL.color4f( 1.f, 1.f, 1.f, alpha ); + gl_rect_2d(rect); + + // ...gray squares + gGL.color4f( .7f, .7f, .7f, alpha ); + gGL.flush(); + + glPolygonStipple( checkerboard ); + + LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); + gl_rect_2d(rect); + } + else + { //polygon stipple is deprecated, use "Checker" texture + LLPointer<LLUIImage> img = LLRender2D::getUIImage("Checker"); + gGL.getTexUnit(0)->bind(img->getImage()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + + LLColor4 color(1.f, 1.f, 1.f, alpha); + LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); + + gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), + img->getImage(), color, uv_rect); + } + + gGL.flush(); +} + + +// Draws the area between two concentric circles, like +// a doughnut or washer. +void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) +{ + const F32 DELTA = F_TWO_PI / steps; + const F32 SIN_DELTA = sin( DELTA ); + const F32 COS_DELTA = cos( DELTA ); + + F32 x1 = outer_radius; + F32 y1 = 0.f; + F32 x2 = inner_radius; + F32 y2 = 0.f; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + steps += 1; // An extra step to close the circle. + while( steps-- ) + { + gGL.color4fv(outer_color.mV); + gGL.vertex2f( x1, y1 ); + gGL.color4fv(inner_color.mV); + gGL.vertex2f( x2, y2 ); + + F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; + y1 = x1 * SIN_DELTA + y1 * COS_DELTA; + x1 = x1_new; + + F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; + y2 = x2 * SIN_DELTA + y2 * COS_DELTA; + x2 = x2_new; + } + } + gGL.end(); +} + +// Draws the area between two concentric circles, like +// a doughnut or washer. +void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) +{ + const F32 DELTA = (end_radians - start_radians) / steps; + const F32 SIN_DELTA = sin( DELTA ); + const F32 COS_DELTA = cos( DELTA ); + + F32 x1 = outer_radius * cos( start_radians ); + F32 y1 = outer_radius * sin( start_radians ); + F32 x2 = inner_radius * cos( start_radians ); + F32 y2 = inner_radius * sin( start_radians ); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + steps += 1; // An extra step to close the circle. + while( steps-- ) + { + gGL.color4fv(outer_color.mV); + gGL.vertex2f( x1, y1 ); + gGL.color4fv(inner_color.mV); + gGL.vertex2f( x2, y2 ); + + F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; + y1 = x1 * SIN_DELTA + y1 * COS_DELTA; + x1 = x1_new; + + F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; + y2 = x2 * SIN_DELTA + y2 * COS_DELTA; + x2 = x2_new; + } + } + gGL.end(); +} + +void gl_rect_2d_simple_tex( S32 width, S32 height ) +{ + gGL.begin( LLRender::QUADS ); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(width, height); + + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2i(0, height); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); + + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(width, 0); + + gGL.end(); +} + +void gl_rect_2d_simple( S32 width, S32 height ) +{ + gGL.begin( LLRender::QUADS ); + gGL.vertex2i(width, height); + gGL.vertex2i(0, height); + gGL.vertex2i(0, 0); + gGL.vertex2i(width, 0); + gGL.end(); +} + +void gl_segmented_rect_2d_tex(const S32 left, + const S32 top, + const S32 right, + const S32 bottom, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const U32 edges) +{ + S32 width = llabs(right - left); + S32 height = llabs(top - bottom); + + gGL.pushUIMatrix(); + + gGL.translateUI((F32)left, (F32)bottom, 0.f); + LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); + + if (border_uv_scale.mV[VX] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; + } + if (border_uv_scale.mV[VY] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; + } + + F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); + LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 width_vec((F32)width, 0.f); + LLVector2 height_vec(0.f, (F32)height); + + gGL.begin(LLRender::QUADS); + { + // draw bottom left + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(0.f, 0.f); + + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + // draw bottom middle + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + // draw bottom right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2fv(width_vec.mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + // draw left + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + // draw middle + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + // draw right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + // draw top left + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2fv((height_vec).mV); + + // draw top middle + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + + // draw top right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2fv((width_vec + height_vec).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + } + gGL.end(); + + gGL.popUIMatrix(); +} + +//FIXME: rewrite to use scissor? +void gl_segmented_rect_2d_fragment_tex(const S32 left, + const S32 top, + const S32 right, + const S32 bottom, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const F32 start_fragment, + const F32 end_fragment, + const U32 edges) +{ + S32 width = llabs(right - left); + S32 height = llabs(top - bottom); + + gGL.pushUIMatrix(); + + gGL.translateUI((F32)left, (F32)bottom, 0.f); + LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); + + if (border_uv_scale.mV[VX] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; + } + if (border_uv_scale.mV[VY] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; + } + + F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); + LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 width_vec((F32)width, 0.f); + LLVector2 height_vec(0.f, (F32)height); + + F32 middle_start = border_scale / (F32)width; + F32 middle_end = 1.f - middle_start; + + F32 u_min; + F32 u_max; + LLVector2 x_min; + LLVector2 x_max; + + gGL.begin(LLRender::QUADS); + { + if (start_fragment < middle_start) + { + u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; + u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; + x_min = (start_fragment / middle_start) * border_width_left; + x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; + + // draw bottom left + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_max.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw left + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top left + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(u_min, 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + + if (end_fragment > middle_start || start_fragment < middle_end) + { + x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; + x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; + + // draw bottom middle + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((x_max).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw middle + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top middle + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + + if (end_fragment > middle_end) + { + u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; + u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; + x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); + x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); + + // draw bottom right + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv((x_min).mV); + + gGL.texCoord2f(u_max, 0.f); + gGL.vertex2fv(x_max.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw right + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top right + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(u_min, 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + } + gGL.end(); + + gGL.popUIMatrix(); +} + +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, + const LLVector3& width_vec, const LLVector3& height_vec) +{ + gGL.begin(LLRender::QUADS); + { + // draw bottom left + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); + gGL.vertex3f(0.f, 0.f, 0.f); + + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); + + // draw bottom middle + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + // draw bottom right + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv(width_vec.mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + + // draw left + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); + + // draw middle + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + + // draw right + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + + // draw top left + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); + + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((height_vec).mV); + + // draw top middle + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); + + // draw top right + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((width_vec + height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); + } + gGL.end(); + +} + +// static +void LLRender2D::initClass(LLImageProviderInterface* image_provider, + const LLVector2* scale_factor) +{ + sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; + sImageProvider = image_provider; +} + +// static +void LLRender2D::cleanupClass() +{ + if(sImageProvider) + { + sImageProvider->cleanUp(); + } +} + + +//static +void LLRender2D::translate(F32 x, F32 y, F32 z) +{ + gGL.translateUI(x,y,z); + LLFontGL::sCurOrigin.mX += (S32) x; + LLFontGL::sCurOrigin.mY += (S32) y; + LLFontGL::sCurDepth += z; +} + +//static +void LLRender2D::pushMatrix() +{ + gGL.pushUIMatrix(); + LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); +} + +//static +void LLRender2D::popMatrix() +{ + gGL.popUIMatrix(); + LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; + LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; + LLFontGL::sOriginStack.pop_back(); +} + +//static +void LLRender2D::loadIdentity() +{ + gGL.loadUIIdentity(); + LLFontGL::sCurOrigin.mX = 0; + LLFontGL::sCurOrigin.mY = 0; + LLFontGL::sCurDepth = 0.f; +} + +//static +void LLRender2D::setScaleFactor(const LLVector2 &scale_factor) +{ + sGLScaleFactor = scale_factor; +} + +//static +void LLRender2D::setLineWidth(F32 width) +{ + gGL.flush(); + glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); +} + +//static +LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority) +{ + if (sImageProvider) + { + return sImageProvider->getUIImageByID(image_id, priority); + } + else + { + return NULL; + } +} + +//static +LLPointer<LLUIImage> LLRender2D::getUIImage(const std::string& name, S32 priority) +{ + if (!name.empty() && sImageProvider) + return sImageProvider->getUIImage(name, priority); + else + return NULL; +} + diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h new file mode 100644 index 0000000000..4884422c58 --- /dev/null +++ b/indra/llrender/llrender2dutils.h @@ -0,0 +1,163 @@ +/** + * @file llrender2dutils.h + * @brief GL function declarations for immediate-mode gl drawing. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// All immediate-mode gl drawing should happen here. + + +#ifndef LL_RENDER2DUTILS_H +#define LL_RENDER2DUTILS_H + +#include "llpointer.h" // LLPointer<> +#include "llrect.h" +#include "llglslshader.h" + +class LLColor4; +class LLVector3; +class LLVector2; +class LLUIImage; +class LLUUID; + +extern const LLColor4 UI_VERTEX_COLOR; + +BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom); +void gl_state_for_2d(S32 width, S32 height); + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2); +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ); +void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled); +void gl_rect_2d_simple( S32 width, S32 height ); + +void gl_draw_x(const LLRect& rect, const LLColor4& color); + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE ); +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE ); +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE ); +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE ); +void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE ); +void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE ); +void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f); + +void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines); + +void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled); +void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle); +void gl_deep_circle( F32 radius, F32 depth ); +void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ); +void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac); +void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); +void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); + +void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); + +void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); + +void gl_rect_2d_simple_tex( S32 width, S32 height ); + +// segmented rectangles + +/* + TL |______TOP_________| TR + /| |\ + _/_|__________________|_\_ + L| | MIDDLE | |R + _|_|__________________|_|_ + \ | BOTTOM | / + BL\|__________________|/ BR + | | +*/ + +typedef enum e_rounded_edge +{ + ROUNDED_RECT_LEFT = 0x1, + ROUNDED_RECT_TOP = 0x2, + ROUNDED_RECT_RIGHT = 0x4, + ROUNDED_RECT_BOTTOM = 0x8, + ROUNDED_RECT_ALL = 0xf +}ERoundedEdge; + + +void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); + +inline void gl_rect_2d( const LLRect& rect, BOOL filled ) +{ + gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); +} + +inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled) +{ + gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); +} + +class LLImageProviderInterface; + +class LLRender2D +{ + LOG_CLASS(LLRender2D); +public: + static void initClass(LLImageProviderInterface* image_provider, + const LLVector2* scale_factor); + static void cleanupClass(); + + static void pushMatrix(); + static void popMatrix(); + static void loadIdentity(); + static void translate(F32 x, F32 y, F32 z = 0.0f); + + static void setLineWidth(F32 width); + static void setScaleFactor(const LLVector2& scale_factor); + + static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0); + static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0); + + static LLVector2 sGLScaleFactor; +private: + static LLImageProviderInterface* sImageProvider; +}; + +class LLImageProviderInterface +{ +protected: + LLImageProviderInterface() {}; + virtual ~LLImageProviderInterface() {}; +public: + virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0; + virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0; + virtual void cleanUp() = 0; +}; + + +extern LLGLSLShader gSolidColorProgram; +extern LLGLSLShader gUIProgram; + +#endif // LL_RENDER2DUTILS_H + diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index c1b96a43da..5fb4fc8e52 100755 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -579,3 +579,5 @@ void LLRenderTarget::getViewport(S32* viewport) viewport[3] = mResY; } + + diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index cf15f66d31..765a727b5b 100755 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -28,7 +28,6 @@ #define LL_LLRENDERTARGET_H // LLRenderTarget is unavailible on the mapserver since it uses FBOs. -#if !LL_MESA_HEADLESS #include "llgl.h" #include "llrender.h" @@ -156,7 +155,5 @@ protected: static LLRenderTarget* sBoundTarget; }; -#endif //!LL_MESA_HEADLESS - #endif diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 569a65c2e0..093bac20d1 100755 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -38,10 +38,9 @@ class LLTexUnit ; class LLFontGL ; // -//this is an abstract class as the parent for the class LLViewerTexture -//through the following virtual functions, the class LLViewerTexture can be reached from /llrender. +//this is an abstract class as the parent for the class LLGLTexture // -class LLTexture : public LLRefCount +class LLTexture : public virtual LLRefCount { friend class LLTexUnit ; friend class LLFontGL ; @@ -53,7 +52,7 @@ public: LLTexture(){} // - //interfaces to access LLViewerTexture + //interfaces to access LLGLTexture // virtual S8 getType() const = 0 ; virtual void setKnownDrawSize(S32 width, S32 height) = 0 ; diff --git a/indra/llui/lluiimage.cpp b/indra/llrender/lluiimage.cpp index 9ed98f941f..b954b66350 100755..100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -31,7 +31,7 @@ // Project includes #include "lluiimage.h" -#include "llui.h" +#include "llrender2dutils.h" LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image) : mName(name), @@ -130,10 +130,10 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c } } - LLUI::pushMatrix(); + LLRender2D::pushMatrix(); { LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); - LLUI::translate(rect_origin.mV[VX], + LLRender2D::translate(rect_origin.mV[VX], rect_origin.mV[VY], rect_origin.mV[VZ]); gGL.getTexUnit(0)->bind(getImage()); @@ -152,7 +152,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c rect.getWidth() * x_axis, rect.getHeight() * y_axis); - } LLUI::popMatrix(); + } LLRender2D::popMatrix(); } @@ -209,7 +209,7 @@ namespace LLInitParam return; } - LLUIImage* imagep = LLUI::getUIImage(name()); + LLUIImage* imagep = LLRender2D::getUIImage(name()); if (imagep) { updateValue(imagep); diff --git a/indra/llui/lluiimage.h b/indra/llrender/lluiimage.h index 7817ba1c7b..7817ba1c7b 100755..100644 --- a/indra/llui/lluiimage.h +++ b/indra/llrender/lluiimage.h diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index dfbd8cd4ee..4909b43e8a 100755 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -402,7 +402,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { if (sLastMask != data_mask) { - bool error = false; if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30) { @@ -469,7 +468,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { if (gDebugSession) { - error = true; gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; } else @@ -489,7 +487,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) if (gDebugSession) { - error = true; gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; } else @@ -548,8 +545,10 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } //static +static LLFastTimer::DeclareTimer FTM_VB_DRAW_ARRAYS("drawArrays"); void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) { + LLFastTimer t(FTM_VB_DRAW_ARRAYS); llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); gGL.syncMatrices(); @@ -784,6 +783,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const placeFence(); } +static LLFastTimer::DeclareTimer FTM_GL_DRAW_ARRAYS("GL draw arrays"); void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); @@ -818,8 +818,11 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const return; } - stop_glerror(); - glDrawArrays(sGLMode[mode], first, count); + { + LLFastTimer t2(FTM_GL_DRAW_ARRAYS); + stop_glerror(); + glDrawArrays(sGLMode[mode], first, count); + } stop_glerror(); placeFence(); } @@ -1565,8 +1568,10 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo { if (map_range) { +#ifndef LL_MESA_HEADLESS glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); +#endif src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } else @@ -1740,8 +1745,10 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range { if (map_range) { +#ifndef LL_MESA_HEADLESS glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); +#endif src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } else @@ -1868,7 +1875,9 @@ void LLVertexBuffer::unmapBuffer() } else if (gGLManager.mHasFlushBufferRange) { +#ifndef LL_MESA_HEADLESS glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length); +#endif } stop_glerror(); } @@ -1934,8 +1943,10 @@ void LLVertexBuffer::unmapBuffer() else if (gGLManager.mHasFlushBufferRange) { #ifdef GL_APPLE_flush_buffer_range +#ifndef LL_MESA_HEADLESS glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); #endif +#endif } stop_glerror(); } @@ -2209,7 +2220,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask) setup = setup || bindBuffer || bindIndices; } - bool error = false; if (gDebugGL && !mGLArray) { GLint buff; @@ -2218,7 +2228,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { if (gDebugSession) { - error = true; gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl; } else @@ -2234,7 +2243,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { if (gDebugSession) { - error = true; gFailLog << "Invalid GL index buffer bound: " << buff << std::endl; } else diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 9c961d67d6..34a08603fa 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -25,6 +25,10 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LIBS_PREBUILD_DIR}/include/hunspell ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llui_SOURCE_FILES llaccordionctrl.cpp @@ -113,7 +117,6 @@ set(llui_SOURCE_FILES lluicolortable.cpp lluictrl.cpp lluictrlfactory.cpp - lluiimage.cpp lluistring.cpp llundo.cpp llurlaction.cpp @@ -227,7 +230,6 @@ set(llui_HEADER_FILES lluifwd.h llui.h lluicolor.h - lluiimage.h lluistring.h llundo.h llurlaction.h diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 9e48dcde7e..6a1b48a08a 100755 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -25,6 +25,7 @@ */ #include "linden_common.h" +#include "llscrollcontainer.h" #include "llchatentry.h" @@ -42,7 +43,9 @@ LLChatEntry::LLChatEntry(const Params& p) mHasHistory(p.has_history), mIsExpandable(p.is_expandable), mExpandLinesCount(p.expand_lines_count), - mPrevLinesCount(0) + mPrevLinesCount(0), + mSingleLineMode(false), + mPrevExpandedLineCount(S32_MAX) { // Initialize current history line iterator mCurrentHistoryLine = mLineHistory.begin(); @@ -82,20 +85,23 @@ boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_si void LLChatEntry::expandText() { + S32 line_count = mSingleLineMode ? 1 : mExpandLinesCount; + int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second); - bool can_expand = getLineCount() <= mExpandLinesCount; + bool can_changed = getLineCount() <= line_count || line_count < mPrevExpandedLineCount ; + mPrevExpandedLineCount = line_count; // true if pasted text has more lines than expand height limit and expand limit is not reached yet - bool text_pasted = (getLineCount() > mExpandLinesCount) && (visible_lines_count < mExpandLinesCount); + bool text_pasted = (getLineCount() > line_count) && (visible_lines_count < line_count); - if (mIsExpandable && (can_expand || text_pasted) && getLineCount() != mPrevLinesCount) + if (mIsExpandable && (can_changed || text_pasted || mSingleLineMode) && getLineCount() != mPrevLinesCount) { int lines_height = 0; if (text_pasted) { // text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty, - // so lines_height is the sum of the last 'mExpandLinesCount' lines height - lines_height = (mLineInfoList.end() - mExpandLinesCount)->mRect.mTop - mLineInfoList.back().mRect.mBottom; + // so lines_height is the sum of the last 'expanded_line_count' lines height + lines_height = (mLineInfoList.end() - line_count)->mRect.mTop - mLineInfoList.back().mRect.mBottom; } else { @@ -114,6 +120,8 @@ void LLChatEntry::expandText() { (*mTextExpandedSignal)(this, LLSD() ); } + + needsReflow(); } } @@ -235,3 +243,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) return handled; } + +void LLChatEntry::enableSingleLineMode(bool single_line_mode) +{ + if (mScroller) + { + mScroller->setSize(single_line_mode ? 0 : -1); + } + + mSingleLineMode = single_line_mode; + mPrevLinesCount = -1; + setWordWrap(!single_line_mode); +} diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 49181c8d78..49c8d21450 100755 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -65,6 +65,7 @@ public: /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); + void enableSingleLineMode(bool single_line_mode); boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); private: @@ -95,9 +96,11 @@ private: line_history_t mLineHistory; // line history storage bool mHasHistory; // flag for enabled/disabled line history bool mIsExpandable; + bool mSingleLineMode; - int mExpandLinesCount; - int mPrevLinesCount; + S32 mExpandLinesCount; + S32 mPrevLinesCount; + S32 mPrevExpandedLineCount; }; #endif /* LLCHATENTRY_H_ */ diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 41e5d74042..d4e14d9419 100755 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -551,7 +551,7 @@ void LLComboBox::showList() LLCoordWindow window_size; getWindow()->getSize(&window_size); //HACK: shouldn't have to know about scale here - mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); + mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); // Make sure that we can see the whole list LLRect root_view_local; diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 161496b1f5..c216d593a2 100755 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -243,7 +243,6 @@ void LLConsole::draw() void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) { LLSD paragraph_color_segments; - LLColor4 lcolor=color; paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); LLSD color_sd = color.getValue(); diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8feaf654f0..8aa1eb7cd5 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1055,12 +1055,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) LLMenuGL::sMenuContainer->hideMenus(); } - LLView *item = NULL; - if (getChildCount() > 0) - { - item = *(getChildList()->begin()); - } - switch( key ) { case KEY_F2: diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 899cc3a326..beac212441 100755 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -69,7 +69,6 @@ public: bool registerFunctor(const std::string& name, ResponseFunctor f) { bool retval = true; - typename FunctorMap::iterator it = mMap.find(name); if (mMap.count(name) == 0) { mMap[name] = f; @@ -96,7 +95,6 @@ public: FUNCTOR_TYPE getFunctor(const std::string& name) { - typename FunctorMap::iterator it = mMap.find(name); if (mMap.count(name) != 0) { return mMap[name]; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index c1cd04186b..795dacdbb0 100755 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -367,7 +367,6 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW const llwchar* base = wtext.c_str(); const llwchar* cur = base; - const llwchar* line = NULL; while( *cur ) { @@ -385,9 +384,6 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } } - // Start of a new line - line = cur; - // Skip white space while( *cur && isspace(*cur) && (*cur != '\n') ) { diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e642883991..e33ac1d5c2 100755 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -476,7 +476,6 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) if (lp->mResizeBar == NULL) { LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; - LLRect resize_bar_rect = getRect(); LLResizeBar::Params resize_params; resize_params.name("resize"); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 6976b06a92..5478e85e13 100755 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2023,8 +2023,8 @@ void LLLineEditor::draw() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } @@ -2571,7 +2571,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length) S32 LLLineEditor::getPreeditFontSize() const { - return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace) diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index 6841301219..0620e0f52d 100755 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -33,7 +33,7 @@ LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) -: mScissorState(GL_SCISSOR_TEST), + : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled) { if (mEnabled) @@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion() LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; - x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); - y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); - w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; - h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; + x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); + y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); + w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; + h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; glScissor( x,y,w,h ); stop_glerror(); } @@ -100,10 +100,10 @@ void LLScreenClipRect::updateScissorRegion() // LLLocalClipRect //--------------------------------------------------------------------------- LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */) -: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX, - rect.mTop + LLFontGL::sCurOrigin.mY, - rect.mRight + LLFontGL::sCurOrigin.mX, - rect.mBottom + LLFontGL::sCurOrigin.mY), enabled) + : LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX, + rect.mTop + LLFontGL::sCurOrigin.mY, + rect.mRight + LLFontGL::sCurOrigin.mX, + rect.mBottom + LLFontGL::sCurOrigin.mY), enabled) {} LLLocalClipRect::~LLLocalClipRect() diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 5d3bf7a670..13887cbe73 100755 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -642,3 +642,8 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data ) { changeLine( mStepSize, TRUE ); } + +void LLScrollbar::setThickness(S32 thickness) +{ + mThickness = thickness < 0 ? LLUI::sSettingGroups["config"]->getS32("UIScrollbarSize") : thickness; +} diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index ff74f753b9..21fd2d631e 100755 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -124,6 +124,9 @@ public: void onLineUpBtnPressed(const LLSD& data); void onLineDownBtnPressed(const LLSD& data); + + S32 getThickness() const { return mThickness; } + void setThickness(S32 thickness); private: void updateThumbRect(); diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 2fd187a526..cbcce0ece5 100755 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -73,7 +73,8 @@ LLScrollContainer::Params::Params() hide_scrollbar("hide_scrollbar"), min_auto_scroll_rate("min_auto_scroll_rate", 100), max_auto_scroll_rate("max_auto_scroll_rate", 1000), - reserve_scroll_corner("reserve_scroll_corner", false) + reserve_scroll_corner("reserve_scroll_corner", false), + size("size", -1) {} @@ -88,9 +89,12 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mReserveScrollCorner(p.reserve_scroll_corner), mMinAutoScrollRate(p.min_auto_scroll_rate), mMaxAutoScrollRate(p.max_auto_scroll_rate), - mScrolledView(NULL) + mScrolledView(NULL), + mSize(p.size) { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0); + S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize); + LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); LLViewBorder::Params params; params.name("scroll border"); @@ -276,7 +280,6 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); // Scroll folder view if needed. Never accepts a drag or drop. *accept = ACCEPT_NO; BOOL handled = autoScroll(x, y); @@ -292,7 +295,8 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, bool LLScrollContainer::autoScroll(S32 x, S32 y) { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0); + S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize); bool scrolling = false; if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() ) @@ -365,7 +369,9 @@ bool LLScrollContainer::autoScroll(S32 x, S32 y) void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const { const LLRect& doc_rect = getScrolledViewRect(); - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0); + S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize); + S32 doc_width = doc_rect.getWidth(); S32 doc_height = doc_rect.getHeight(); @@ -406,7 +412,9 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height void LLScrollContainer::draw() { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0); + S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize); + if (mAutoScrolling) { // add acceleration to autoscroll @@ -515,7 +523,9 @@ void LLScrollContainer::updateScroll() { return; } - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0); + S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize); + LLRect doc_rect = mScrolledView->getRect(); S32 doc_width = doc_rect.getWidth(); S32 doc_height = doc_rect.getHeight(); @@ -716,3 +726,9 @@ S32 LLScrollContainer::getBorderWidth() const return 0; } +void LLScrollContainer::setSize(S32 size) +{ + mSize = size; + mScrollbar[VERTICAL]->setThickness(size); + mScrollbar[HORIZONTAL]->setThickness(size); +} diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index d87c95b3d7..4eb43539b8 100755 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -68,6 +68,7 @@ public: max_auto_scroll_rate; Optional<LLUIColor> bg_color; Optional<LLScrollbar::callback_t> scroll_callback; + Optional<S32> size; Params(); }; @@ -116,6 +117,9 @@ public: bool autoScroll(S32 x, S32 y); + S32 getSize() const { return mSize; } + void setSize(S32 thickness); + protected: LLView* mScrolledView; diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index a189375fbe..250372da5b 100755 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -145,10 +145,14 @@ void LLSpellChecker::refreshDictionaryMap() // Load dictionary information (file name, friendly name, ...) llifstream user_file(user_path + DICT_FILE_MAIN, std::ios::binary); - if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) ) + if ( (!user_file.is_open()) + || (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) + || (0 == sDictMap.size()) ) { llifstream app_file(app_path + DICT_FILE_MAIN, std::ios::binary); - if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) ) + if ( (!app_file.is_open()) + || (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) + || (0 == sDictMap.size()) ) { return; } diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 6f895ed939..fd98155704 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1215,9 +1215,11 @@ void LLTabContainer::removeTabPanel(LLPanel* child) removeChild( tuple->mButton ); } delete tuple->mButton; + tuple->mButton = NULL; removeChild( tuple->mTabPanel ); // delete tuple->mTabPanel; + tuple->mTabPanel = NULL; mTabList.erase( iter ); delete tuple; @@ -1279,9 +1281,11 @@ void LLTabContainer::deleteAllTabs() removeChild( tuple->mButton ); delete tuple->mButton; + tuple->mButton = NULL; removeChild( tuple->mTabPanel ); // delete tuple->mTabPanel; + tuple->mTabPanel = NULL; } // Actually delete the tuples themselves @@ -1484,9 +1488,8 @@ BOOL LLTabContainer::setTab(S32 which) { LLTabTuple* tuple = *iter; BOOL is_selected = ( tuple == selected_tuple ); - // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list - if (tuple->mButton) + if (tuple && tuple->mButton) { tuple->mButton->setUseEllipses(mUseTabEllipses); tuple->mButton->setHAlign(mFontHalign); @@ -1494,7 +1497,7 @@ BOOL LLTabContainer::setTab(S32 which) // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs tuple->mButton->setTabStop( is_selected ); } - if (tuple->mTabPanel) + if (tuple && tuple->mTabPanel) { tuple->mTabPanel->setVisible( is_selected ); //tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here. @@ -1525,7 +1528,7 @@ BOOL LLTabContainer::setTab(S32 which) else { S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1); - S32 running_tab_width = tuple->mButton->getRect().getWidth(); + S32 running_tab_width = (tuple && tuple->mButton ? tuple->mButton->getRect().getWidth() : 0); S32 j = i - 1; S32 min_scroll_pos = i; if (running_tab_width < available_width_with_arrows) @@ -1533,7 +1536,7 @@ BOOL LLTabContainer::setTab(S32 which) while (j >= 0) { LLTabTuple* other_tuple = getTab(j); - running_tab_width += other_tuple->mButton->getRect().getWidth(); + running_tab_width += (other_tuple && other_tuple->mButton ? other_tuple->mButton->getRect().getWidth() : 0); if (running_tab_width > available_width_with_arrows) { break; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 270d5294f9..e70992129a 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -443,6 +443,7 @@ void LLTextBase::drawSelectionBackground() ++rect_it) { LLRect selection_rect = *rect_it; + selection_rect = *rect_it; selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); gl_rect_2d(selection_rect, selection_color); } @@ -520,8 +521,8 @@ void LLTextBase::drawCursor() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } @@ -1917,7 +1918,6 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); - registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); @@ -3490,3 +3490,7 @@ F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 select return 0.0; } +void LLTextBase::setWordWrap(bool wrap) +{ + mWordWrap = wrap; +} diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index ad566a36d3..20a73387b5 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -41,6 +41,7 @@ #include <boost/signals2.hpp> +class LLScrollContainer; class LLContextMenu; class LLUrlMatch; @@ -434,6 +435,9 @@ public: virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); + void setWordWrap(bool wrap); + LLScrollContainer* getScrollContainer() const { return mScroller; } + protected: // helper structs struct compare_bottom; @@ -634,7 +638,7 @@ protected: // support widgets LLContextMenu* mPopupMenu; LLView* mDocumentView; - class LLScrollContainer* mScroller; + LLScrollContainer* mScroller; // transient state S32 mReflowIndex; // index at which to start reflow. S32_MAX indicates no reflow needed. diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d5e08fa29b..834f213097 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -956,12 +956,18 @@ S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op) { S32 end_pos = getEditableIndex(pos + length, true); + BOOL removedChar = FALSE; segment_vec_t segments_to_remove; // store text segments getSegmentsInRange(segments_to_remove, pos, pos + length, false); + + if(pos <= end_pos) + { + removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) ); + } - return execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) ); + return removedChar; } S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc) @@ -2911,7 +2917,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 1c74395c66..3d9f5cbbc2 100755 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -653,7 +653,6 @@ void LLToolBar::updateLayoutAsNeeded() S32 max_row_length = 0; S32 max_length; - S32 max_total_girth; S32 cur_start; S32 cur_row ; S32 row_pad_start; @@ -664,7 +663,6 @@ void LLToolBar::updateLayoutAsNeeded() if (orientation == LLLayoutStack::HORIZONTAL) { max_length = getRect().getWidth() - mPadLeft - mPadRight; - max_total_girth = getRect().getHeight() - mPadTop - mPadBottom; row_pad_start = mPadLeft; row_pad_end = mPadRight; cur_row = mPadTop; @@ -673,7 +671,6 @@ void LLToolBar::updateLayoutAsNeeded() else // VERTICAL { max_length = getRect().getHeight() - mPadTop - mPadBottom; - max_total_girth = getRect().getWidth() - mPadLeft - mPadRight; row_pad_start = mPadTop; row_pad_end = mPadBottom; cur_row = mPadLeft; @@ -841,7 +838,6 @@ void LLToolBar::draw() if (mDragAndDropTarget && !mButtonCommands.empty()) { LLRect caret_rect = caret->getRect(); - LLRect toolbar_rect = getRect(); if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL) { caret->setRect(LLRect(mDragx-caret_rect.getWidth()/2+1, diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 2a774d54a3..0ddb149738 100755 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -39,6 +39,7 @@ #include "llrect.h" #include "lldir.h" #include "llgl.h" +#include "llsd.h" // Project includes #include "llcommandmanager.h" @@ -69,16 +70,13 @@ // // Globals // -const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); // Language for UI construction std::map<std::string, std::string> gTranslation; std::list<std::string> gUntranslated; /*static*/ LLUI::settings_map_t LLUI::sSettingGroups; -/*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL; /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL; /*static*/ LLUIAudioCallback LLUI::sDeferredAudioCallback = NULL; -/*static*/ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f); /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLView* LLUI::sRootView = NULL; /*static*/ BOOL LLUI::sDirty = FALSE; @@ -158,1474 +156,6 @@ void make_ui_sound_deferred(const char* namep) } } -BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) -{ - if (x < left || right < x) return FALSE; - if (y < bottom || top < y) return FALSE; - return TRUE; -} - - -// Puts GL into 2D drawing mode by turning off lighting, setting to an -// orthographic projection, etc. -void gl_state_for_2d(S32 width, S32 height) -{ - stop_glerror(); - F32 window_width = (F32) width;//gViewerWindow->getWindowWidth(); - F32 window_height = (F32) height;//gViewerWindow->getWindowHeight(); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadIdentity(); - gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadIdentity(); - stop_glerror(); -} - - -void gl_draw_x(const LLRect& rect, const LLColor4& color) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin( LLRender::LINES ); - gGL.vertex2i( rect.mLeft, rect.mTop ); - gGL.vertex2i( rect.mRight, rect.mBottom ); - gGL.vertex2i( rect.mLeft, rect.mBottom ); - gGL.vertex2i( rect.mRight, rect.mTop ); - gGL.end(); -} - - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled) -{ - gGL.color4fv(color.mV); - gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled); -} - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled) -{ - gGL.pushUIMatrix(); - left += LLFontGL::sCurOrigin.mX; - right += LLFontGL::sCurOrigin.mX; - bottom += LLFontGL::sCurOrigin.mY; - top += LLFontGL::sCurOrigin.mY; - - gGL.loadUIIdentity(); - gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset, - llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset, - llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset, - llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset, - filled); - gGL.popUIMatrix(); -} - - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Counterclockwise quad will face the viewer - if( filled ) - { - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - if( gGLManager.mATIOffsetVerticalLines ) - { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - gGL.begin( LLRender::LINES ); - - // Verticals - gGL.vertex2i(left + 1, top); - gGL.vertex2i(left + 1, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - - // Horizontals - top--; - right--; - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - - gGL.vertex2i(left, top); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - top--; - right--; - gGL.begin( LLRender::LINE_STRIP ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.vertex2i(left, top); - gGL.end(); - } - } - stop_glerror(); -} - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( left, top, right, bottom, filled ); -} - - -void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -// Given a rectangle on the screen, draws a drop shadow _outside_ -// the right and bottom edges of it. Along the right it has width "lines" -// and along the bottom it has height "lines". -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // HACK: Overlap with the rectangle by a single pixel. - right--; - bottom++; - lines++; - - LLColor4 end_color = start_color; - end_color.mV[VALPHA] = 0.f; - - gGL.begin(LLRender::QUADS); - - // Right edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right+lines, bottom); - gGL.vertex2i(right+lines, top-lines); - - // Bottom edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); - - // bottom left Corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); - // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); - - // bottom right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); - // make the rightmost corner not sharp - gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); - - // top right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); - gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); - // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); - - gGL.end(); - stop_glerror(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv(color.mV); - - if (filled) - { - gGL.begin(LLRender::TRIANGLES); - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.vertex2i(x3, y3); - gGL.end(); -} - -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - length = llmin((S32)(max_frac*(right - left)), length); - length = llmin((S32)(max_frac*(top - bottom)), length); - gGL.begin(LLRender::LINES); - gGL.vertex2i(left, top); - gGL.vertex2i(left + length, top); - - gGL.vertex2i(left, top); - gGL.vertex2i(left, top - length); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left + length, bottom); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left, bottom + length); - - gGL.vertex2i(right, top); - gGL.vertex2i(right - length, top); - - gGL.vertex2i(right, top); - gGL.vertex2i(right, top - length); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right - length, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, bottom + length); - gGL.end(); -} - - -void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect ) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // scale screen size of borders down - F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); - F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); - - LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); - gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) -{ - stop_glerror(); - - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // add in offset of current image to current UI translation - const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - - F32 uv_width = uv_outer_rect.getWidth(); - F32 uv_height = uv_outer_rect.getHeight(); - - // shrink scaling region to be proportional to clipped image region - LLRectf uv_center_rect( - uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), - uv_outer_rect.mBottom + (center_rect.mTop * uv_height), - uv_outer_rect.mLeft + (center_rect.mRight * uv_width), - uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); - - S32 image_natural_width = llround(image_width * uv_width); - S32 image_natural_height = llround(image_height * uv_height); - - LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, - uv_center_rect.mTop * image_height, - uv_center_rect.mRight * image_width, - uv_center_rect.mBottom * image_height); - - { // scale fixed region of image to drawn region - draw_center_rect.mRight += width - image_natural_width; - draw_center_rect.mTop += height - image_natural_height; - - F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); - F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); - - F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); - F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); - - F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); - - draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); - draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); - draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); - draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); - } - - LLRectf draw_outer_rect(ui_translation.mV[VX], - ui_translation.mV[VY] + height * ui_scale.mV[VY], - ui_translation.mV[VX] + width * ui_scale.mV[VX], - ui_translation.mV[VY]); - - LLGLSUIDefault gls_ui; - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gSolidColorProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - } - } - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - const S32 NUM_VERTICES = 9 * 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - S32 index = 0; - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom right - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - // draw left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - // draw top left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - } -} - -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); -} - -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - LLGLSUIDefault gls_ui; - - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - if (degrees == 0.f) - { - const S32 NUM_VERTICES = 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - gGL.begin(LLRender::QUADS); - { - LLVector3 ui_scale = gGL.getUIScale(); - LLVector3 ui_translation = gGL.getUITranslation(); - ui_translation.mV[VX] += x; - ui_translation.mV[VY] += y; - ui_translation.scaleVec(ui_scale); - S32 index = 0; - S32 scaled_width = llround(width * ui_scale.mV[VX]); - S32 scaled_height = llround(height * ui_scale.mV[VY]); - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - } - else - { - gGL.pushUIMatrix(); - gGL.translateUI((F32)x, (F32)y, 0.f); - - F32 offset_x = F32(width/2); - F32 offset_y = F32(height/2); - - gGL.translateUI(offset_x, offset_y, 0.f); - - LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - gGL.begin(LLRender::QUADS); - { - LLVector3 v; - - v = LLVector3(offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - } - gGL.end(); - gGL.popUIMatrix(); - } -} - - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) -{ - phase = fmod(phase, 1.f); - - S32 shift = S32(phase * 4.f) % 4; - - // Stippled line - LLGLEnable stipple(GL_LINE_STIPPLE); - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - - gGL.flush(); - glLineWidth(2.5f); - - if (!LLGLSLShader::sNoFixedFunction) - { - glLineStipple(2, 0x3333 << shift); - } - - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv( start.mV ); - gGL.vertex3fv( end.mV ); - } - gGL.end(); - - LLUI::setLineWidth(1.f); -} - -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle) -{ - if (end_angle < start_angle) - { - end_angle += F_TWO_PI; - } - - gGL.pushUIMatrix(); - { - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = (end_angle - start_angle) / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = cosf(start_angle) * radius; - F32 y = sinf(start_angle) * radius; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_STRIP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled) -{ - gGL.pushUIMatrix(); - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = F_TWO_PI / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = radius; - F32 y = 0.f; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -// Renders a ring with sides (tube shape) -void gl_deep_circle( F32 radius, F32 depth, S32 steps ) -{ - F32 x = radius; - F32 y = 0.f; - F32 angle_delta = F_TWO_PI / (F32)steps; - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - S32 step = steps + 1; // An extra step to close the circle. - while( step-- ) - { - gGL.vertex3f( x, y, depth ); - gGL.vertex3f( x, y, 0.f ); - - F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta); - y = x * sinf(angle_delta) + y * cosf(angle_delta); - x = x_new; - } - } - gGL.end(); -} - -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ) -{ - gGL.pushUIMatrix(); - { - gGL.translateUI(0.f, 0.f, -width / 2); - if( render_center ) - { - gGL.color4fv(center_color.mV); - gGL.diffuseColor4fv(center_color.mV); - gl_deep_circle( radius, width, steps ); - } - else - { - gGL.diffuseColor4fv(side_color.mV); - gl_washer_2d(radius, radius - width, steps, side_color, side_color); - gGL.translateUI(0.f, 0.f, width); - gl_washer_2d(radius - width, radius, steps, side_color, side_color); - } - } - gGL.popUIMatrix(); -} - -// Draw gray and white checkerboard with black border -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) -{ - if (!LLGLSLShader::sNoFixedFunction) - { - // Initialize the first time this is called. - const S32 PIXELS = 32; - static GLubyte checkerboard[PIXELS * PIXELS]; - static BOOL first = TRUE; - if( first ) - { - for( S32 i = 0; i < PIXELS; i++ ) - { - for( S32 j = 0; j < PIXELS; j++ ) - { - checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; - } - } - first = FALSE; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // ...white squares - gGL.color4f( 1.f, 1.f, 1.f, alpha ); - gl_rect_2d(rect); - - // ...gray squares - gGL.color4f( .7f, .7f, .7f, alpha ); - gGL.flush(); - - glPolygonStipple( checkerboard ); - - LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); - gl_rect_2d(rect); - } - else - { //polygon stipple is deprecated, use "Checker" texture - LLPointer<LLUIImage> img = LLUI::getUIImage("Checker"); - gGL.getTexUnit(0)->bind(img->getImage()); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - - LLColor4 color(1.f, 1.f, 1.f, alpha); - LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); - - gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), - img->getImage(), color, uv_rect); - } - - gGL.flush(); -} - - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = F_TWO_PI / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius; - F32 y1 = 0.f; - F32 x2 = inner_radius; - F32 y2 = 0.f; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = (end_radians - start_radians) / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius * cos( start_radians ); - F32 y1 = outer_radius * sin( start_radians ); - F32 x2 = inner_radius * cos( start_radians ); - F32 y2 = inner_radius * sin( start_radians ); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -void gl_rect_2d_simple_tex( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(width, height); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(0, height); - - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(0, 0); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(width, 0); - - gGL.end(); -} - -void gl_rect_2d_simple( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(width, height); - gGL.vertex2i(0, height); - gGL.vertex2i(0, 0); - gGL.vertex2i(width, 0); - gGL.end(); -} - -void gl_segmented_rect_2d_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const U32 edges) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2f(0.f, 0.f); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - // draw bottom right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2fv(width_vec.mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - // draw right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - // draw top right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2fv((width_vec + height_vec).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - } - gGL.end(); - - gGL.popUIMatrix(); -} - -//FIXME: rewrite to use scissor? -void gl_segmented_rect_2d_fragment_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const F32 start_fragment, - const F32 end_fragment, - const U32 edges) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - F32 middle_start = border_scale / (F32)width; - F32 middle_end = 1.f - middle_start; - - F32 u_min; - F32 u_max; - LLVector2 x_min; - LLVector2 x_max; - - gGL.begin(LLRender::QUADS); - { - if (start_fragment < middle_start) - { - u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; - u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; - x_min = (start_fragment / middle_start) * border_width_left; - x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; - - // draw bottom left - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_start || start_fragment < middle_end) - { - x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; - x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((x_max).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_end) - { - u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; - u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; - x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); - x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); - - // draw bottom right - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv((x_min).mV); - - gGL.texCoord2f(u_max, 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw right - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top right - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - } - gGL.end(); - - gGL.popUIMatrix(); -} - -void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, - const LLVector3& width_vec, const LLVector3& height_vec) -{ - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); - gGL.vertex3f(0.f, 0.f, 0.f); - - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - - // draw bottom middle - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - - // draw bottom right - gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); - gGL.vertex3fv(width_vec.mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - - // draw left - gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - - // draw middle - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - - // draw right - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); - gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - - // draw top left - gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - - gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); - gGL.vertex3fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - - // draw top right - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - - gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); - gGL.vertex3fv((width_vec + height_vec).mV); - - gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); - } - gGL.end(); - -} - - void LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback, @@ -1633,6 +163,7 @@ void LLUI::initClass(const settings_map_t& settings, const LLVector2* scale_factor, const std::string& language) { + LLRender2D::initClass(image_provider,scale_factor); sSettingGroups = settings; if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) || @@ -1642,10 +173,8 @@ void LLUI::initClass(const settings_map_t& settings, llerrs << "Failure to initialize configuration groups" << llendl; } - sImageProvider = image_provider; sAudioCallback = audio_callback; sDeferredAudioCallback = deferred_audio_callback; - sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; sWindow = NULL; // set later in startup LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow"); @@ -1679,10 +208,7 @@ void LLUI::initClass(const settings_map_t& settings, void LLUI::cleanupClass() { - if(sImageProvider) - { - sImageProvider->cleanUp(); -} + LLRender2D::cleanupClass(); } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) @@ -1706,60 +232,12 @@ void LLUI::dirtyRect(LLRect rect) } } - -//static -void LLUI::translate(F32 x, F32 y, F32 z) -{ - gGL.translateUI(x,y,z); - LLFontGL::sCurOrigin.mX += (S32) x; - LLFontGL::sCurOrigin.mY += (S32) y; - LLFontGL::sCurDepth += z; -} - -//static -void LLUI::pushMatrix() -{ - gGL.pushUIMatrix(); - LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); -} - -//static -void LLUI::popMatrix() -{ - gGL.popUIMatrix(); - LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; - LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; - LLFontGL::sOriginStack.pop_back(); -} - -//static -void LLUI::loadIdentity() -{ - gGL.loadUIIdentity(); - LLFontGL::sCurOrigin.mX = 0; - LLFontGL::sCurOrigin.mY = 0; - LLFontGL::sCurDepth = 0.f; -} - -//static -void LLUI::setScaleFactor(const LLVector2 &scale_factor) -{ - sGLScaleFactor = scale_factor; -} - -//static -void LLUI::setLineWidth(F32 width) -{ - gGL.flush(); - glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); -} - //static void LLUI::setMousePositionScreen(S32 x, S32 y) { S32 screen_x, screen_y; - screen_x = llround((F32)x * sGLScaleFactor.mV[VX]); - screen_y = llround((F32)y * sGLScaleFactor.mV[VY]); + screen_x = llround((F32)x * getScaleFactor().mV[VX]); + screen_y = llround((F32)y * getScaleFactor().mV[VY]); LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } @@ -1770,8 +248,8 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); - *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]); - *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]); + *x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); + *y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]); } //static @@ -1885,21 +363,21 @@ LLVector2 LLUI::getWindowSize() LLCoordWindow window_rect; sWindow->getSize(&window_rect); - return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]); + return LLVector2(window_rect.mX / getScaleFactor().mV[VX], window_rect.mY / getScaleFactor().mV[VY]); } //static void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y) { - *gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]); - *gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]); + *gl_x = llround((F32)screen_x * getScaleFactor().mV[VX]); + *gl_y = llround((F32)screen_y * getScaleFactor().mV[VY]); } //static void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y) { - *screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]); - *screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]); + *screen_x = llround((F32)gl_x / getScaleFactor().mV[VX]); + *screen_y = llround((F32)gl_y / getScaleFactor().mV[VY]); } //static @@ -1916,27 +394,6 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen) glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom); } -//static -LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority) -{ - if (sImageProvider) - { - return sImageProvider->getUIImageByID(image_id, priority); - } - else - { - return NULL; - } -} - -//static -LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority) -{ - if (!name.empty() && sImageProvider) - return sImageProvider->getUIImage(name, priority); - else - return NULL; -} LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 4c1703392a..0a0e0e164e 100755 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -1,6 +1,6 @@ /** * @file llui.h - * @brief GL function declarations and other general static UI services. + * @brief General static UI services. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,122 +24,38 @@ * $/LicenseInfo$ */ -// All immediate-mode gl drawing should happen here. #ifndef LL_LLUI_H #define LL_LLUI_H -#include "llpointer.h" // LLPointer<> #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" -#include "llglslshader.h" +#include "v2math.h" #include "llinitparam.h" #include "llregistry.h" +#include "llrender2dutils.h" +#include "llpointer.h" #include "lluicolor.h" #include "lluicolortable.h" +#include "lluiimage.h" #include <boost/signals2.hpp> #include "lllazyvalue.h" #include "llframetimer.h" #include <limits> -// LLUIFactory -#include "llsd.h" - // for initparam specialization #include "llfontgl.h" -class LLColor4; -class LLVector3; -class LLVector2; -class LLUIImage; class LLUUID; class LLWindow; class LLView; class LLHelp; -// UI colors -extern const LLColor4 UI_VERTEX_COLOR; void make_ui_sound(const char* name); void make_ui_sound_deferred(const char * name); -BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom); -void gl_state_for_2d(S32 width, S32 height); - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2); -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ); -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled); -void gl_rect_2d_simple( S32 width, S32 height ); - -void gl_draw_x(const LLRect& rect, const LLColor4& color); - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE ); -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE ); -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f); - -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines); - -void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled); -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle); -void gl_deep_circle( F32 radius, F32 depth ); -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ); -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac); -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); - -void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); - -void gl_rect_2d_simple_tex( S32 width, S32 height ); - -// segmented rectangles - -/* - TL |______TOP_________| TR - /| |\ - _/_|__________________|_\_ - L| | MIDDLE | |R - _|_|__________________|_|_ - \ | BOTTOM | / - BL\|__________________|/ BR - | | -*/ - -typedef enum e_rounded_edge -{ - ROUNDED_RECT_LEFT = 0x1, - ROUNDED_RECT_TOP = 0x2, - ROUNDED_RECT_RIGHT = 0x4, - ROUNDED_RECT_BOTTOM = 0x8, - ROUNDED_RECT_ALL = 0xf -}ERoundedEdge; - - -void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); - -inline void gl_rect_2d( const LLRect& rect, BOOL filled ) -{ - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled) -{ - gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); -} - class LLImageProviderInterface; typedef void (*LLUIAudioCallback)(const LLUUID& uuid); @@ -281,10 +197,10 @@ public: static void cleanupClass(); static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& ); - static void pushMatrix(); - static void popMatrix(); - static void loadIdentity(); - static void translate(F32 x, F32 y, F32 z = 0.0f); + static void pushMatrix() { LLRender2D::pushMatrix(); } + static void popMatrix() { LLRender2D::popMatrix(); } + static void loadIdentity() { LLRender2D::loadIdentity(); } + static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); } static LLRect sDirtyRect; static BOOL sDirty; @@ -329,10 +245,13 @@ public: static void getMousePositionScreen(S32 *x, S32 *y); static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y); static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y); - static void setScaleFactor(const LLVector2& scale_factor); - static void setLineWidth(F32 width); - static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0); - static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0); + static LLVector2& getScaleFactor() { return LLRender2D::sGLScaleFactor; } + static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::setScaleFactor(scale_factor); } + static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); } + static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0) + { return LLRender2D::getUIImageByID(image_id, priority); } + static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0) + { return LLRender2D::getUIImage(name, priority); } static LLVector2 getWindowSize(); static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y); static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y); @@ -362,12 +281,10 @@ public: static settings_map_t sSettingGroups; static LLUIAudioCallback sAudioCallback; static LLUIAudioCallback sDeferredAudioCallback; - static LLVector2 sGLScaleFactor; static LLWindow* sWindow; static LLView* sRootView; static LLHelp* sHelpImpl; private: - static LLImageProviderInterface* sImageProvider; static std::vector<std::string> sXUIPaths; static LLFrameTimer sMouseIdleTimer; static add_popup_t sAddPopupFunc; @@ -378,18 +295,6 @@ private: // Moved LLLocalClipRect to lllocalcliprect.h -//RN: maybe this needs to moved elsewhere? -class LLImageProviderInterface -{ -protected: - LLImageProviderInterface() {}; - virtual ~LLImageProviderInterface() {}; -public: - virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0; - virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0; - virtual void cleanUp() = 0; -}; - class LLCallbackRegistry { public: @@ -438,10 +343,11 @@ public: // this avoids a MSVC bug where non-referenced static members are "optimized" away // even if their constructors have side effects - void reference() + S32 reference() { S32 dummy; dummy = 0; + return dummy; } }; @@ -600,7 +506,4 @@ namespace LLInitParam }; } -extern LLGLSLShader gSolidColorProgram; -extern LLGLSLShader gUIProgram; - #endif diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 8f0a48018f..c3f0e92cb0 100755 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -31,7 +31,7 @@ #include "llurlentry_stub.cpp" #include "lltut.h" #include "../lluicolortable.h" -#include "../lluiimage.h" +#include "../llrender/lluiimage.h" #include <boost/regex.hpp> diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 109d3ca7bb..55c1efefef 100755 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -28,7 +28,7 @@ #include "linden_common.h" #include "../llurlmatch.h" -#include "../lluiimage.h" +#include "../llrender/lluiimage.h" #include "lltut.h" // link seams diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index 3c68b279f7..67dce8c073 100755 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -8,6 +8,7 @@ include(UnixInstall) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ) set(llvfs_SOURCE_FILES @@ -44,12 +45,12 @@ if (LINUX) LIST(APPEND llvfs_SOURCE_FILES lldir_linux.cpp) LIST(APPEND llvfs_HEADER_FILES lldir_linux.h) - if (VIEWER AND INSTALL) + if (INSTALL) set_source_files_properties(lldir_linux.cpp PROPERTIES COMPILE_FLAGS "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\"" ) - endif (VIEWER AND INSTALL) + endif (INSTALL) endif (LINUX) if (WINDOWS) @@ -70,6 +71,7 @@ set(vfs_BOOST_LIBRARIES ) target_link_libraries(llvfs + ${LLCOMMON_LIBRARIES} ${vfs_BOOST_LIBRARIES} ) diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index ca749c5eaf..03d2cc25e3 100755 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -32,6 +32,7 @@ #include "llthread.h" #include "llstat.h" #include "llvfs.h" +#include "llmemory.h" const S32 LLVFile::READ = 0x00000001; const S32 LLVFile::WRITE = 0x00000002; @@ -134,13 +135,13 @@ U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S data = NULL; } else - { - data = new U8[file_size]; + { + data = (U8*) ll_aligned_malloc_16(file_size); file.read(data, file_size); /* Flawfinder: ignore */ if (file.getLastBytesRead() != (S32)file_size) { - delete[] data; + ll_aligned_free(data); data = NULL; file_size = 0; } diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 341bddfffd..ad010164eb 100755 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -32,12 +32,17 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${DIRECTX_INCLUDE_DIR} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(llwindow_SOURCE_FILES llkeyboard.cpp llkeyboardheadless.cpp llwindowheadless.cpp llwindowcallbacks.cpp + llwindow.cpp ) set(llwindow_HEADER_FILES @@ -50,7 +55,6 @@ set(llwindow_HEADER_FILES ) set(viewer_SOURCE_FILES - llwindow.cpp llmousehandler.cpp ) @@ -62,13 +66,43 @@ set(viewer_HEADER_FILES # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level -if (LINUX AND VIEWER) +if (LINUX) set(llwindow_LINK_LIBRARIES + ${LLCOMMON_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLRENDER_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLWINDOW_LIBRARIES} + ${LLXML_LIBRARIES} ${UI_LIBRARIES} # for GTK ${SDL_LIBRARY} fontconfig # For FCInit and other FC* functions. ) -endif (LINUX AND VIEWER) + + list(APPEND viewer_SOURCE_FILES + llkeyboardsdl.cpp + llwindowsdl.cpp + ) + list(APPEND viewer_HEADER_FILES + llkeyboardsdl.h + llwindowsdl.h + ) + + if (BUILD_HEADLESS) + set(llwindowheadless_LINK_LIBRARIES + ${LLCOMMON_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLRENDER_HEADLESS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLWINDOW_HEADLESS_LIBRARIES} + ${LLXML_LIBRARIES} + fontconfig # For FCInit and other FC* functions. + ) + endif (BUILD_HEADLESS) + +endif (LINUX) if (DARWIN) list(APPEND llwindow_SOURCE_FILES @@ -91,16 +125,6 @@ if (DARWIN) ) endif (DARWIN) -if (LINUX AND VIEWER) - list(APPEND viewer_SOURCE_FILES - llkeyboardsdl.cpp - llwindowsdl.cpp - ) - list(APPEND viewer_HEADER_FILES - llkeyboardsdl.h - llwindowsdl.h - ) -endif (LINUX AND VIEWER) if (WINDOWS) list(APPEND llwindow_SOURCE_FILES @@ -133,40 +157,41 @@ endif (SOLARIS) set_source_files_properties(${llwindow_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) -if (SERVER AND NOT WINDOWS AND NOT DARWIN) - set(server_SOURCE_FILES +if (BUILD_HEADLESS) + set(llwindowheadless_SOURCE_FILES llwindowmesaheadless.cpp + llmousehandler.cpp ) - set(server_HEADER_FILES + set(llwindowheadless_HEADER_FILES llwindowmesaheadless.h + llmousehandler.h ) - copy_server_sources( - llwindow - ) - - - set_source_files_properties( - ${server_SOURCE_FILES} - PROPERTIES - COMPILE_FLAGS "-DLL_MESA=1 -DLL_MESA_HEADLESS=1" - ) add_library (llwindowheadless ${llwindow_SOURCE_FILES} - ${server_SOURCE_FILES} + ${llwindowheadless_SOURCE_FILES} ) - target_link_libraries (llwindowheadless ${llwindow_LINK_LIBRARIES}) -endif (SERVER AND NOT WINDOWS AND NOT DARWIN) + set_property(TARGET llwindowheadless + PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1 + ) + target_link_libraries (llwindowheadless ${llwindowheadless_LINK_LIBRARIES} dl) +endif (BUILD_HEADLESS) if (llwindow_HEADER_FILES) list(APPEND llwindow_SOURCE_FILES ${llwindow_HEADER_FILES}) endif (llwindow_HEADER_FILES) - list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) -if (VIEWER) - add_library (llwindow - ${llwindow_SOURCE_FILES} - ${viewer_SOURCE_FILES} +list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) + +add_library (llwindow + ${llwindow_SOURCE_FILES} + ${viewer_SOURCE_FILES} + ) + +if (SDL_FOUND) + set_property(TARGET llwindow + PROPERTY COMPILE_DEFINITIONS LL_SDL=1 ) - target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) -endif (VIEWER) +endif (SDL_FOUND) + +target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) diff --git a/indra/llwindow/GL/glh_extensions.h b/indra/llwindow/GL/glh_extensions.h index d89d85930b..554cb1731f 100755 --- a/indra/llwindow/GL/glh_extensions.h +++ b/indra/llwindow/GL/glh_extensions.h @@ -113,7 +113,7 @@ static const char* EatNonWhiteSpace(const char *str) int glh_init_extensions(const char *origReqExts) { // Length of requested extensions string - unsigned reqExtsLen; + //unsigned reqExtsLen; char *reqExts; // Ptr for individual extensions within reqExts char *reqExt; @@ -155,8 +155,8 @@ int glh_init_extensions(const char *origReqExts) return TRUE; } reqExts = strdup(origReqExts); - reqExtsLen = (S32)strlen(reqExts); /* + reqExtsLen = (S32)strlen(reqExts); if (NULL == gGLHExts.mUnsupportedExts) { gGLHExts.mUnsupportedExts = (char*)malloc(reqExtsLen + 1); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index a15114cb9b..205466e936 100755 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -1636,35 +1636,53 @@ void check_vm_bloat() { #if LL_LINUX // watch our own VM and RSS sizes, warn if we bloated rapidly - FILE *fp = fopen("/proc/self/stat", "r"); + static const std::string STATS_FILE = "/proc/self/stat"; + FILE *fp = fopen(STATS_FILE.c_str(), "r"); if (fp) { static long long last_vm_size = 0; static long long last_rss_size = 0; const long long significant_vm_difference = 250 * 1024*1024; const long long significant_rss_difference = 50 * 1024*1024; + long long this_vm_size = 0; + long long this_rss_size = 0; ssize_t res; size_t dummy; - char *ptr; + char *ptr = NULL; for (int i=0; i<22; ++i) // parse past the values we don't want { - ptr = NULL; res = getdelim(&ptr, &dummy, ' ', fp); + if (-1 == res) + { + llwarns << "Unable to parse " << STATS_FILE << llendl; + goto finally; + } free(ptr); + ptr = NULL; } // 23rd space-delimited entry is vsize - ptr = NULL; res = getdelim(&ptr, &dummy, ' ', fp); llassert(ptr); - long long this_vm_size = atoll(ptr); + if (-1 == res) + { + llwarns << "Unable to parse " << STATS_FILE << llendl; + goto finally; + } + this_vm_size = atoll(ptr); free(ptr); - // 24th space-delimited entry is RSS ptr = NULL; + // 24th space-delimited entry is RSS res = getdelim(&ptr, &dummy, ' ', fp); llassert(ptr); - long long this_rss_size = getpagesize() * atoll(ptr); + if (-1 == res) + { + llwarns << "Unable to parse " << STATS_FILE << llendl; + goto finally; + } + this_rss_size = getpagesize() * atoll(ptr); free(ptr); + ptr = NULL; llinfos << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << llendl; @@ -1697,6 +1715,12 @@ void check_vm_bloat() last_rss_size = this_rss_size; last_vm_size = this_vm_size; +finally: + if (NULL != ptr) + { + free(ptr); + ptr = NULL; + } fclose(fp); } #endif // LL_LINUX diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt index beefcda361..cf96f26a77 100755 --- a/indra/llxml/CMakeLists.txt +++ b/indra/llxml/CMakeLists.txt @@ -13,6 +13,9 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ) +include_directories( + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) set(llxml_SOURCE_FILES llcontrol.cpp @@ -39,9 +42,10 @@ list(APPEND llxml_SOURCE_FILES ${llxml_HEADER_FILES}) add_library (llxml ${llxml_SOURCE_FILES}) # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level -target_link_libraries( llxml - llvfs - llmath +target_link_libraries(llxml + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} ${EXPAT_LIBRARIES} ) diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 53d9380f4f..666c03e9ff 100755 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -850,12 +850,10 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v return 0; } - S32 ret = LLSDSerialize::fromXML(settings, infile); - - if (ret <= 0) + if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(settings, infile)) { infile.close(); - llwarns << "Unable to open LLSD control file " << filename << ". Trying Legacy Method." << llendl; + llwarns << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << llendl; return loadFromFileLegacy(filename, TRUE, TYPE_STRING); } diff --git a/indra/lscript/lscript_compile/CMakeLists.txt b/indra/lscript/lscript_compile/CMakeLists.txt index 3ed2892e0e..07662005b9 100755 --- a/indra/lscript/lscript_compile/CMakeLists.txt +++ b/indra/lscript/lscript_compile/CMakeLists.txt @@ -45,6 +45,9 @@ include_directories( ${LLPRIMITIVE_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) set(lscript_generated_SOURCE_FILES indra.l.cpp @@ -95,6 +98,7 @@ add_custom_command( ${CMAKE_CURRENT_BINARY_DIR}/indra.l.cpp COMMAND ${FLEX} ARGS + -P indra_ -o${CMAKE_CURRENT_BINARY_DIR}/indra.l.cpp ${CMAKE_CURRENT_SOURCE_DIR}/indra.l DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/indra.l @@ -112,8 +116,10 @@ if (WINDOWS) ${CMAKE_CURRENT_BINARY_DIR}/indra.y.cpp ${CMAKE_CURRENT_BINARY_DIR}/indra.y.hpp COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bison.bat + ARGS ${BISON} ${M4_PATH} - ${CMAKE_CURRENT_BINARY_DIR}/indra.y.cpp + -p indra_ + -d -o ${CMAKE_CURRENT_BINARY_DIR}/indra.y.cpp ${CMAKE_CURRENT_SOURCE_DIR}/indra.y DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bison.bat @@ -128,6 +134,7 @@ else (WINDOWS) COMMAND ${BISON} ARGS + -p indra_ -d -o ${CMAKE_CURRENT_BINARY_DIR}/indra.y.cpp ${CMAKE_CURRENT_SOURCE_DIR}/indra.y DEPENDS diff --git a/indra/lscript/lscript_compile/bison.bat b/indra/lscript/lscript_compile/bison.bat index 0baff4e5ef..d40997225e 100644 --- a/indra/lscript/lscript_compile/bison.bat +++ b/indra/lscript/lscript_compile/bison.bat @@ -2,10 +2,11 @@ @REM find m4, even if neither program is present in PATH.
@set bison=%1
-set M4PATH=%2
+shift
+set M4PATH=%1
+shift
set M4=
-@set output=%3
-@set input=%4
set PATH=%M4PATH%;%PATH%
-%bison% -d -o %output% %input%
+@REM %* does not work with shift...
+%bison% %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 96b7e57e97..b2c49083cb 100755 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -56,6 +56,29 @@ void parse_string(); #define ECHO do { } while (0) +#define yyparse indra_parse +#define yyerror indra_error +#define yylval indra_lval +#define yy_create_buffer indra__create_buffer +#define yy_delete_buffer indra__delete_buffer +#define yy_flex_debug indra__flex_debug +#define yy_init_buffer indra__init_buffer +#define yy_flush_buffer indra__flush_buffer +#define yy_load_buffer_state indra__load_buffer_state +#define yy_switch_to_buffer indra__switch_to_buffer +#define yyin indra_in +#define yyleng indra_leng +#define yylex indra_lex +#define yylineno indra_lineno +#define yyout indra_out +#define yyrestart indra_restart +#define yytext indra_text +#define yywrap indra_wrap +#define yyalloc indra_alloc +#define yyrealloc indra_realloc +#define yyfree indra_free + + #if defined(__cplusplus) extern "C" { int yylex( void ); } extern "C" { int yyparse( void ); } diff --git a/indra/lscript/lscript_execute/CMakeLists.txt b/indra/lscript/lscript_execute/CMakeLists.txt index 3a16ffdc01..49605982a8 100755 --- a/indra/lscript/lscript_execute/CMakeLists.txt +++ b/indra/lscript/lscript_execute/CMakeLists.txt @@ -10,6 +10,9 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) set(lscript_execute_SOURCE_FILES llscriptresource.cpp diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index d79e9f8bde..b12d2e4a16 100755 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -806,16 +806,7 @@ void LLScriptExecute::runInstructions(BOOL b_print, const LLUUID &id, // is there a fault? // if yes, print out message and exit S32 value = getVersion(); - S32 major_version = 0; - if (value == LSL2_VERSION1_END_NUMBER) - { - major_version = 1; - } - else if (value == LSL2_VERSION_NUMBER) - { - major_version = 2; - } - else + if ( (value != LSL2_VERSION1_END_NUMBER) && (value != LSL2_VERSION_NUMBER) ) { setFault(LSRF_VERSION_MISMATCH); } diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index 35caa41ae1..8b41cb5a72 100755 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -123,7 +123,7 @@ void LLScriptLSOParse::printRegisters(LLFILE *fp) void LLScriptLSOParse::printGlobals(LLFILE *fp) { // print out registers first - S32 offset, varoffset; + S32 varoffset; S32 ivalue; F32 fpvalue; LLVector3 vvalue; @@ -144,7 +144,7 @@ void LLScriptLSOParse::printGlobals(LLFILE *fp) // get offset to skip past name varoffset = global_v_offset; - offset = bytestream2integer(mRawData, global_v_offset); + bytestream2integer(mRawData, global_v_offset); // get typeexport type = *(mRawData + global_v_offset++); @@ -262,8 +262,6 @@ void LLScriptLSOParse::printGlobalFunctions(LLFILE *fp) fprintf(fp, "[Function #%d] [0x%X] %s\n", function_number, orig_function_offset, name); fprintf(fp, "\tReturn Type: %s\n", LSCRIPTTypeNames[type]); type = *(mRawData + function_offset++); - S32 params; - params = 0; S32 pcount = 0; while (type) { @@ -347,7 +345,6 @@ void LLScriptLSOParse::printStates(LLFILE *fp) read_ahead = event_jump_table; S32 temp_end; - S32 dummy; opcode_end = worst_case_opcode_end; @@ -356,7 +353,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp) if (event_handlers & LSCRIPTStateBitField[k]) { temp_end = bytestream2integer(mRawData, read_ahead); - dummy = bytestream2integer(mRawData, read_ahead); + bytestream2integer(mRawData, read_ahead); if ( (temp_end < opcode_end) &&(temp_end > event_offset)) { diff --git a/indra/lscript/lscript_library/CMakeLists.txt b/indra/lscript/lscript_library/CMakeLists.txt index f6bc67a994..5af850c41b 100755 --- a/indra/lscript/lscript_library/CMakeLists.txt +++ b/indra/lscript/lscript_library/CMakeLists.txt @@ -28,5 +28,8 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) add_library (lscript_library ${lscript_library_SOURCE_FILES}) diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt index 3906a3bb8c..c59645bd70 100755 --- a/indra/mac_crash_logger/CMakeLists.txt +++ b/indra/mac_crash_logger/CMakeLists.txt @@ -19,6 +19,10 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(mac_crash_logger_SOURCE_FILES mac_crash_logger.cpp diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt index 00dcedecaa..a644984e58 100755 --- a/indra/mac_updater/CMakeLists.txt +++ b/indra/mac_updater/CMakeLists.txt @@ -7,6 +7,7 @@ include(OpenSSL) include(CURL) include(CARes) include(LLCommon) +include(LLMessage) include(LLVFS) include(Linking) @@ -52,6 +53,7 @@ set_target_properties(mac-updater ) target_link_libraries(mac-updater + ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt index 3ad94b0c64..7367b9e5e6 100755 --- a/indra/media_plugins/base/CMakeLists.txt +++ b/indra/media_plugins/base/CMakeLists.txt @@ -11,7 +11,7 @@ include(LLRender) include(LLWindow) include(Linking) include(PluginAPI) -include(FindOpenGL) +include(OpenGL) include_directories( ${LLPLUGIN_INCLUDE_DIRS} @@ -21,6 +21,9 @@ include_directories( ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) ### media_plugin_base diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt index 54dc5de1ea..171645ef04 100755 --- a/indra/media_plugins/example/CMakeLists.txt +++ b/indra/media_plugins/example/CMakeLists.txt @@ -12,7 +12,7 @@ include(LLWindow) include(Linking) include(PluginAPI) include(MediaPluginBase) -include(FindOpenGL) +include(OpenGL) include(ExamplePlugin) @@ -25,6 +25,9 @@ include_directories( ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) ### media_plugin_example diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt index 5786bd1e25..447f6e0689 100755 --- a/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -12,7 +12,7 @@ include(LLWindow) include(Linking) include(PluginAPI) include(MediaPluginBase) -include(FindOpenGL) +include(OpenGL) include(GStreamer010Plugin) @@ -27,6 +27,9 @@ include_directories( ${GSTREAMER010_INCLUDE_DIRS} ${GSTREAMER010_PLUGINS_BASE_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) ### media_plugin_gstreamer010 diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index cdb7f4faeb..932aaffa1b 100755 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -278,10 +278,9 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) static gboolean gst_slvideo_start (GstBaseSink * bsink) { - GstSLVideo *slvideo; gboolean ret = TRUE; - slvideo = GST_SLVIDEO(bsink); + GST_SLVIDEO(bsink); return ret; } diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt index f0b8f0d167..58391007ff 100755 --- a/indra/media_plugins/quicktime/CMakeLists.txt +++ b/indra/media_plugins/quicktime/CMakeLists.txt @@ -12,7 +12,7 @@ include(LLWindow) include(Linking) include(PluginAPI) include(MediaPluginBase) -include(FindOpenGL) +include(OpenGL) include(QuickTimePlugin) include_directories( @@ -24,6 +24,9 @@ include_directories( ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) if (DARWIN) include(CMakeFindFrameworks) diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt index b36291f0e8..0c1c3d800e 100755 --- a/indra/media_plugins/webkit/CMakeLists.txt +++ b/indra/media_plugins/webkit/CMakeLists.txt @@ -13,7 +13,7 @@ include(UI) include(Linking) include(PluginAPI) include(MediaPluginBase) -include(FindOpenGL) +include(OpenGL) include(PulseAudio) include(WebKitLibPlugin) @@ -29,6 +29,9 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLQTWEBKIT_INCLUDE_DIR} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) ### media_plugin_webkit diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bd0169fb2f..fae02c0b30 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -10,9 +10,9 @@ include(DirectX) include(OpenSSL) include(DragDrop) include(EXPAT) -include(FMOD) +include(FMODEX) include(OPENAL) -include(FindOpenGL) +include(OpenGL) include(Hunspell) include(JsonCpp) include(LLAudio) @@ -46,12 +46,17 @@ include(LLLogin) include(VisualLeakDetector) include(GLOD) include(CMakeCopyIfDifferent) +include(LLAppearance) if (NOT HAVOK_TPV) # When using HAVOK_TPV, the library is precompiled, so no need for this add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions) endif (NOT HAVOK_TPV) +if(FMODEX) + include_directories(${FMODEX_INCLUDE_DIR}) +endif(FMODEX) + include_directories( ${DBUSGLIB_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIR} @@ -61,13 +66,11 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLCOREHTTP_INCLUDE_DIRS} ${LLPHYSICS_INCLUDE_DIRS} - ${FMOD_INCLUDE_DIR} ${LLIMAGE_INCLUDE_DIRS} ${LLKDU_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${LLPLUGIN_INCLUDE_DIRS} ${LLPRIMITIVE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} @@ -83,6 +86,13 @@ include_directories( ${LIBS_PREBUILD_DIR}/include/hunspell ${OPENAL_LIB_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada/1.4 + ${LLAPPEARANCE_INCLUDE_DIRS} + ) + +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ) set(viewer_SOURCE_FILES @@ -169,7 +179,6 @@ set(viewer_SOURCE_FILES lldrawpooltree.cpp lldrawpoolwater.cpp lldrawpoolwlsky.cpp - lldriverparam.cpp lldynamictexture.cpp llemote.cpp llenvmanager.cpp @@ -334,7 +343,6 @@ set(viewer_SOURCE_FILES lllistcontextmenu.cpp lllistview.cpp lllocalbitmaps.cpp - lllocaltextureobject.cpp lllocationhistory.cpp lllocationinputctrl.cpp lllogchat.cpp @@ -454,12 +462,11 @@ set(viewer_SOURCE_FILES llpersistentnotificationstorage.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp + llpipelinelistener.cpp llplacesinventorybridge.cpp llplacesinventorypanel.cpp llplacesfolderview.cpp llpopupview.cpp - llpolymesh.cpp - llpolymorph.cpp llpostcard.cpp llpreview.cpp llpreviewanim.cpp @@ -510,9 +517,6 @@ set(viewer_SOURCE_FILES llsyswellwindow.cpp llteleporthistory.cpp llteleporthistorystorage.cpp - lltexglobalcolor.cpp - lltexlayer.cpp - lltexlayerparams.cpp lltextureatlas.cpp lltextureatlasmanager.cpp lltexturecache.cpp @@ -610,18 +614,18 @@ set(viewer_SOURCE_FILES llviewershadermgr.cpp llviewerstats.cpp llviewerstatsrecorder.cpp + llviewertexlayer.cpp llviewertexteditor.cpp llviewertexture.cpp llviewertextureanim.cpp llviewertexturelist.cpp llviewerthrottle.cpp - llviewervisualparam.cpp + llviewerwearable.cpp llviewerwindow.cpp llviewerwindowlistener.cpp llvlcomposition.cpp llvlmanager.cpp llvoavatar.cpp - llvoavatardefines.cpp llvoavatarself.cpp llvocache.cpp llvograss.cpp @@ -642,10 +646,8 @@ set(viewer_SOURCE_FILES llwatchdog.cpp llwaterparammanager.cpp llwaterparamset.cpp - llwearable.cpp llwearableitemslist.cpp llwearablelist.cpp - llwearabletype.cpp llweb.cpp llwebprofile.cpp llwebsharing.cpp @@ -757,7 +759,6 @@ set(viewer_HEADER_FILES lldrawpooltree.h lldrawpoolwater.h lldrawpoolwlsky.h - lldriverparam.h lldynamictexture.h llemote.h llenvmanager.h @@ -921,7 +922,6 @@ set(viewer_HEADER_FILES lllistcontextmenu.h lllistview.h lllocalbitmaps.h - lllocaltextureobject.h lllocationhistory.h lllocationinputctrl.h lllogchat.h @@ -1030,11 +1030,10 @@ set(viewer_HEADER_FILES llpersistentnotificationstorage.h llphysicsmotion.h llphysicsshapebuilderutil.h + llpipelinelistener.h llplacesinventorybridge.h llplacesinventorypanel.h llplacesfolderview.h - llpolymesh.h - llpolymorph.h llpopupview.h llpostcard.h llpreview.h @@ -1088,9 +1087,6 @@ set(viewer_HEADER_FILES lltable.h llteleporthistory.h llteleporthistorystorage.h - lltexglobalcolor.h - lltexlayer.h - lltexlayerparams.h lltextureatlas.h lltextureatlasmanager.h lltexturecache.h @@ -1189,18 +1185,18 @@ set(viewer_HEADER_FILES llviewershadermgr.h llviewerstats.h llviewerstatsrecorder.h + llviewertexlayer.h llviewertexteditor.h llviewertexture.h llviewertextureanim.h llviewertexturelist.h llviewerthrottle.h - llviewervisualparam.h + llviewerwearable.h llviewerwindow.h llviewerwindowlistener.h llvlcomposition.h llvlmanager.h llvoavatar.h - llvoavatardefines.h llvoavatarself.h llvocache.h llvograss.h @@ -1221,10 +1217,8 @@ set(viewer_HEADER_FILES llwatchdog.h llwaterparammanager.h llwaterparamset.h - llwearable.h llwearableitemslist.h llwearablelist.h - llwearabletype.h llweb.h llwebprofile.h llwebsharing.h @@ -1542,29 +1536,12 @@ endif (WINDOWS) if (OPENAL) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") -endif (OPENAL) +endif (OPENAL) -if (FMOD) - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") - - if (DARWIN) - set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) - add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) - set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) - set_target_properties( - fmodwrapper - PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" - ) - set(FMODWRAPPER_LIBRARY fmodwrapper) - target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) - else (DARWIN) - # fmodwrapper unnecessary on linux or windows - set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) - endif (DARWIN) -endif (FMOD) +if (FMODEX) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") + set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) +endif (FMODEX) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") @@ -1579,6 +1556,12 @@ add_executable(${VIEWER_BINARY_NAME} ${viewer_SOURCE_FILES} ) +if (SDL_FOUND) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS LL_SDL=1 + ) +endif (SDL_FOUND) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1639,9 +1622,6 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll - ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll - ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll - ${SHARED_LIB_STAGING_DIR}/Debug/fmod.dll ${SHARED_LIB_STAGING_DIR}/Release/msvcr100.dll ${SHARED_LIB_STAGING_DIR}/Release/msvcp100.dll ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr100.dll @@ -1706,6 +1686,14 @@ if (WINDOWS) windows-updater ) + if (FMODEX) + list(APPEND COPY_INPUT_DEPENDENCIES + ${SHARED_LIB_STAGING_DIR}/Release/fmodex.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodex.dll + ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll + ) + endif (FMODEX) + add_custom_command( OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat COMMAND ${PYTHON_EXECUTABLE} @@ -1864,19 +1852,9 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${TCMALLOC_LIBRARIES} + ${LLAPPEARANCE_LIBRARIES} ) -if (USE_KDU) - target_link_libraries(${VIEWER_BINARY_NAME} - ${LLKDU_LIBRARIES} - ${KDU_LIBRARY} - ) -else (USE_KDU) - target_link_libraries(${VIEWER_BINARY_NAME} - ${LLIMAGEJ2COJ_LIBRARIES} - ) -endif (USE_KDU) - build_version(viewer) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH @@ -2096,6 +2074,15 @@ if (LL_TESTS) ) set_source_files_properties( + llworldmap.cpp + llworldmipmap.cpp + PROPERTIES + LL_TEST_ADDITIONAL_SOURCE_FILES + tests/llviewertexture_stub.cpp + #llviewertexturelist.cpp + ) + + set_source_files_properties( lltranslate.cpp PROPERTIES LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}" diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 5c7cacedec..1802e14703 100755 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.1.0.13828"; -CFBundleGetInfoString = "Second Life version 2.1.0.13828, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 3.4.1.264760"; +CFBundleGetInfoString = "Second Life version 3.4.1.264760, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index f7b11b217c..035d6cbe6c 100755 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -60,7 +60,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.1.0.13828</string> + <string>3.4.1.264760</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4c305e1d60..3281d347a7 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -291,6 +291,17 @@ <key>Value</key> <real>1.0</real> </map> + <key>AudioLevelUnderwaterRolloff</key> + <map> + <key>Comment</key> + <string>Controls the distance-based dropoff of audio volume underwater(fraction or multiple of default audio rolloff)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>5.0</real> + </map> <key>AudioLevelSFX</key> <map> <key>Comment</key> @@ -2004,6 +2015,39 @@ <key>Value</key> <string /> </map> + <key>DebugAvatarAppearanceMessage</key> + <map> + <key>Comment</key> + <string>Dump a bunch of XML files when handling appearance messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DebugAvatarExperimentalServerAppearanceUpdate</key> + <map> + <key>Comment</key> + <string>Experiment with sending full cof_contents instead of cof_version</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DebugAvatarAppearanceServiceURLOverride</key> + <map> + <key>Comment</key> + <string>URL to use for baked texture requests; overrides value returned by login server.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>DebugAvatarRezTime</key> <map> <key>Comment</key> @@ -2026,6 +2070,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>DebugAvatarCompositeBaked</key> + <map> + <key>Comment</key> + <string>Colorize avatar meshes based on baked/composite state.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DebugBeaconLineWidth</key> <map> <key>Comment</key> @@ -2037,6 +2092,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>DebugForceAppearanceRequestFailure</key> + <map> + <key>Comment</key> + <string>Request wrong cof version to test the failure path for server appearance update requests.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DebugHideEmptySystemFolders</key> <map> <key>Comment</key> @@ -4381,6 +4447,28 @@ <key>Value</key> <real>1.0</real> </map> + <key>InventoryDebugSimulateOpFailureRate</key> + <map> + <key>Comment</key> + <string>Rate at which we simulate failures of copy/link requests in some operations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + <key>InventoryDebugSimulateLateOpRate</key> + <map> + <key>Comment</key> + <string>Rate at which we simulate late-completing copy/link requests in some operations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> <key>InventoryDisplayInbox</key> <map> <key>Comment</key> @@ -8903,6 +8991,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>DisableAllRenderTypes</key> + <map> + <key>Comment</key> + <string>Disables all rendering types.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DisableAllRenderFeatures</key> + <map> + <key>Comment</key> + <string>Disables all rendering features.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderHUDInSnapshot</key> <map> <key>Comment</key> @@ -13340,6 +13450,28 @@ <key>Value</key> <integer>-1</integer> </map> + <key>MaxFPS</key> + <map> + <key>Comment</key> + <string>Yield some time to the local host if we reach a threshold framerate.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>-1.0</integer> + </map> + <key>ForcePeriodicRenderingTime</key> + <map> + <key>Comment</key> + <string>Periodically enable all rendering masks for a single frame.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>-1.0</integer> + </map> <key>ZoomDirect</key> <map> <key>Comment</key> @@ -14325,5 +14457,60 @@ <key>Value</key> <integer>0</integer> </map> + <key>DisablePrecacheDelayAfterTeleporting</key> + <map> + <key>Comment</key> + <string>Disables the artificial delay in the viewer that precaches some incoming assets</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FMODExProfilerEnable</key> + <map> + <key>Comment</key> + <string>Enable profiler tool if using FMOD Ex</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FMODExDecodeBufferSize</key> + <map> + <key>Comment</key> + <string>Sets the streaming decode buffer size (in milliseconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1000</integer> + </map> + <key>FMODExStreamBufferSize</key> + <map> + <key>Comment</key> + <string>Sets the streaming buffer size (in milliseconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>7000</integer> + </map> + <key>DisablePrecacheDelayAfterTeleporting</key> + <map> + <key>Comment</key> + <string>Disables the artificial delay in the viewer that precaches some incoming assets</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl index 99a6fe85fe..9c82056fd7 100755 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -31,7 +31,7 @@ out vec4 frag_color; uniform float minimum_alpha; -vec4 diffuseLookup(vec2 texcoord); +/* vec4 diffuseLookup(vec2 texcoord); */ vec3 fullbrightAtmosTransport(vec3 light); vec4 applyWaterFog(vec4 color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl index df182168f3..d3dacf9bc4 100755 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl @@ -32,7 +32,7 @@ out vec4 frag_color; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec4 diffuseLookup(vec2 texcoord); +/* vec4 diffuseLookup(vec2 texcoord); */ vec3 fullbrightAtmosTransport(vec3 light); vec4 applyWaterFog(vec4 color); diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index 99dbfcae51..284e9c44b2 100755 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -1084,6 +1084,23 @@ scale="0 0 .5" /> </param_skeleton> </param> + + <param + id="11001" + group="0" + name="Hover" + wearable="shape" + edit_group="shape_body" + edit_group_order="4" + label_min="Lower" + label_max="Higher" + value_min="-2" + value_max="2" + value_default="0" + camera_distance="2.5"> + <param_skeleton /> + </param> + </skeleton> <mesh @@ -12291,6 +12308,17 @@ render_pass="bump"> <param_driver /> </param> + <param + id="11000" + group="0" + name="AppearanceMessage_Version" + label="AppearanceMessage Version" + value_default="0" + value_min="0" + value_max="255"> + <param_driver /> + </param> + </driver_parameters> <morph_masks> diff --git a/indra/newview/fmod_hidden_symbols.exp b/indra/newview/fmod_hidden_symbols.exp deleted file mode 100755 index 1e790255bc..0000000000 --- a/indra/newview/fmod_hidden_symbols.exp +++ /dev/null @@ -1,240 +0,0 @@ -_CarbonSndPlayDoubleBuffer -_ConvertFromIeeeExtended -__book_maptype1_quantvals -__book_unquantize -__float32_pack -__float32_unpack -__ilog -__make_words -_lpc_clear -_lpc_init -__vorbis_block_alloc -__vorbis_block_ripcord -__vorbis_apply_window -__vorbis_window_get -_vorbis_analysis_blockout -_vorbis_analysis_buffer -_vorbis_analysis_wrote -_vorbis_block_clear -_vorbis_block_init -_vorbis_dsp_clear -_vorbis_synthesis_blockin -_vorbis_synthesis_init -_vorbis_synthesis_pcmout -_vorbis_synthesis_read -_vorbis_packet_blocksize -_vorbis_synthesis -_vorbis_book_clear -_vorbis_book_decode -_vorbis_book_decodev_add -_vorbis_book_decodev_set -_vorbis_book_decodevs_add -_vorbis_book_decodevv_add -_vorbis_book_init_decode -_vorbis_comment_add -_vorbis_comment_add_tag -_vorbis_comment_clear -_vorbis_comment_init -_vorbis_comment_query -_vorbis_comment_query_count -_vorbis_coslook -_vorbis_fromdBlook -_vorbis_info_blocksize -_vorbis_info_clear -_vorbis_info_init -_vorbis_invsq2explook -_vorbis_invsqlook -_vorbis_lpc_from_curve -_vorbis_lpc_from_data -_vorbis_lpc_predict -_vorbis_lsp_to_curve -_vorbis_staticbook_clear -_vorbis_staticbook_destroy -_vorbis_staticbook_unpack -_vorbis_synthesis_headerin -_vorbis_synthesis_lapout -_vorbis_synthesis_restart -_vorbis_synthesis_trackonly -_vorbis_window -_ogg_packet_clear -_ogg_page_bos -_ogg_page_checksum_set -_ogg_page_continued -_ogg_page_eos -_ogg_page_granulepos -_ogg_page_packets -_ogg_page_pageno -_ogg_page_serialno -_ogg_page_version -_ogg_stream_reset_serialno -_ogg_stream_clear -_ogg_stream_destroy -_ogg_stream_eos -_ogg_stream_flush -_ogg_stream_init -_ogg_stream_packetout -_ogg_stream_packetpeek -_ogg_stream_pagein -_ogg_stream_pageout -_ogg_stream_reset -_ogg_sync_buffer -_ogg_sync_clear -_ogg_sync_destroy -_ogg_sync_init -_ogg_sync_pageout -_ogg_sync_pageseek -_ogg_sync_reset -_ogg_sync_wrote -_ov_bitrate -_ov_bitrate_instant -_ov_clear -_ov_comment -_ov_info -_ov_open -_ov_open_callbacks -_ov_pcm_seek -_ov_pcm_seek_page -_ov_pcm_tell -_ov_pcm_total -_ov_raw_seek -_ov_raw_tell -_ov_raw_total -_ov_read -_ov_read_float -_ov_seekable -_ov_serialnumber -_ov_streams -_ov_test -_ov_test_callbacks -_ov_test_open -_ov_time_seek -_ov_time_seek_page -_ov_time_tell -_ov_time_total -_ogg_toupper -_oggpackB_adv -_oggpackB_adv1 -_oggpackB_bits -_oggpackB_bytes -_oggpackB_get_buffer -_oggpackB_look -_oggpackB_look1 -_oggpackB_read -_oggpackB_read1 -_oggpackB_readinit -_oggpackB_reset -_oggpack_adv -_oggpack_adv1 -_oggpack_bits -_oggpack_bytes -_oggpack_get_buffer -_oggpack_look -_oggpack_look1 -_oggpack_read -_oggpack_read1 -_oggpack_readinit -_oggpack_reset -_ov_crosslap -_ov_pcm_seek_lap -_ov_pcm_seek_page_lap -_ov_raw_seek_lap -_ov_time_seek_lap -_ov_time_seek_page_lap -_II_step_one -_II_step_two -_MyRecComp -_SampleRates -_Sinfo -_ValidStepIndex -__Z11fmodwrapperv -__Z11fmodwrapperv.eh -__floor_P -__mapping_P -__residue_P -__ve_envelope_clear -__ve_envelope_init -__ve_envelope_mark -__ve_envelope_search -__ve_envelope_shift -__vi_gpsy_free -__vi_psy_free -__vorbis_window_init -__vp_ampmax_decay -__vp_couple -__vp_global_free -__vp_global_look -__vp_noise_normalize -__vp_noise_normalize_sort -__vp_noisemask -__vp_offset_and_mix -__vp_psy_clear -__vp_psy_init -__vp_quantize_couple_memo -__vp_quantize_couple_sort -__vp_remove_floor -__vp_tonemask -_alloc_0 -_alloc_1 -_alloc_2 -_alloc_3 -_alloc_4 -_bandInfo -_cdcallback -_cdchannel -_cdmode -_cdnumtracks -_cdstream -_cdtrack -_drft_backward -_drft_clear -_drft_forward -_drft_init -_eatwhite -_floor0_exportbundle -_floor1_exportbundle -_gFreeList -_gNMRecBusy -_gNMRecPtr -_gSilenceOnes -_gSilenceTwos -_longLimit -_mapping0_exportbundle -_mdct_backward -_mdct_clear -_mdct_forward -_mdct_init -_muls -_mystrdup -_res0_free_info -_res0_free_look -_res0_inverse -_res0_look -_res0_unpack -_res1_class -_res1_inverse -_res2_inverse -_residue0_exportbundle -_residue1_exportbundle -_residue2_exportbundle -_scale -_shortLimit -_tabsel_123 -_F_Free -_F_Malloc -_F_ReAlloc -_F_memcmp -_F_memmove -_F_strcat -_F_strchr -_F_strcmp -_F_strcpy -_F_stricmp -_F_strlen -_F_strncat -_F_strncmp -_F_strncpy -_F_strnicmp -_F_strstr -_F_strupr -_F_tolower -_F_toupper diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 20936c6460..48b883e999 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,17 +4,17 @@ ## These options are for self-assisted troubleshooting during this beta ## testing phase; you should not usually need to touch them. +## - Avoids using any FMOD Ex audio driver. +#export LL_BAD_FMODEX_DRIVER=x ## - Avoids using any OpenAL audio driver. #export LL_BAD_OPENAL_DRIVER=x -## - Avoids using any FMOD audio driver. -#export LL_BAD_FMOD_DRIVER=x -## - Avoids using the FMOD ESD audio driver. -#export LL_BAD_FMOD_ESD=x -## - Avoids using the FMOD OSS audio driver. -#export LL_BAD_FMOD_OSS=x -## - Avoids using the FMOD ALSA audio driver. +## - Avoids using the FMOD Ex PulseAudio audio driver. +#export LL_BAD_FMOD_PULSEAUDIO=x +## - Avoids using the FMOD or FMOD Ex ALSA audio driver. #export LL_BAD_FMOD_ALSA=x +## - Avoids using the FMOD or FMOD Ex OSS audio driver. +#export LL_BAD_FMOD_OSS=x ## - Avoids the optional OpenGL extensions which have proven most problematic ## on some hardware. Disabling this option may cause BETTER PERFORMANCE but @@ -45,6 +45,7 @@ if [ "`uname -m`" = "x86_64" ]; then echo '64-bit Linux detected.' fi + ## Everything below this line is just for advanced troubleshooters. ##------------------------------------------------------------------- @@ -60,7 +61,15 @@ fi export SDL_VIDEO_X11_DGAMOUSE=0 ## - Works around a problem with misconfigured 64-bit systems not finding GL -export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}":/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri +I386_MULTIARCH="$(dpkg-architecture -ai386 -qDEB_HOST_MULTIARCH 2>/dev/null)" +MULTIARCH_ERR=$? +if [ $MULTIARCH_ERR -eq 0 ]; then + echo 'Multi-arch support detected.' + MULTIARCH_GL_DRIVERS="/usr/lib/${I386_MULTIARCH}/dri" + export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:${MULTIARCH_GL_DRIVERS}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri" +else + export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri" +fi ## - The 'scim' GTK IM module widely crashes the viewer. Avoid it. if [ "$GTK_IM_MODULE" = "scim" ]; then @@ -117,18 +126,32 @@ export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" # Simply embedding $(<etc/gridargs.dat) into a command line treats each of # Second, Life and Developer as separate args -- no good. We need bash to # process quotes using eval. -# First read it without scanning, then scan that string. Break quoted words +# First, check if we have been instructed to skip reading in gridargs.dat: +skip_gridargs=false +argnum=0 +for ARG in "$@"; do + if [ "--skip-gridargs" == "$ARG" ]; then + skip_gridargs=true + else + ARGS[$argnum]="$ARG" + argnum=$(($argnum+1)) + fi +done + +# Second, read it without scanning, then scan that string. Break quoted words # into a bash array. Note that if gridargs.dat is empty, or contains only # whitespace, the resulting gridargs array will be empty -- zero entries -- # therefore "${gridargs[@]}" entirely vanishes from the command line below, # just as we want. -eval gridargs=("$(<etc/gridargs.dat)") +if ! $skip_gridargs ; then + eval gridargs=("$(<etc/gridargs.dat)") +fi # Run the program. # Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the # command line. But DO quote "$@": preserve separate args as individually # quoted. Similar remarks about the contents of gridargs. -$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "$@" +$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "${ARGS[@]}" LL_RUN_ERR=$? # Handle any resulting errors diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 8767955fcb..7662a9689d 100755 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -56,9 +56,9 @@ public: } } - void error( U32 statusNum, const std::string& reason ) + void errorWithContent( U32 statusNum, const std::string& reason, const LLSD& content ) { - llwarns << "Transport error "<<reason<<llendl; + llwarns << "Transport error [status:" << statusNum << "]: " << content <<llendl; clearPendingRequests(); LLAccountingCostObserver* observer = mObserverHandle.get(); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 094d502078..8c42defa73 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -35,6 +35,7 @@ #include "llagentlistener.h" #include "llagentwearables.h" #include "llagentui.h" +#include "llappearancemgr.h" #include "llanimationstates.h" #include "llcallingcard.h" #include "llcapabilitylistener.h" @@ -91,7 +92,7 @@ #include "llworldmap.h" #include "stringize.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; extern LLMenuBarGL* gMenuBarView; @@ -808,6 +809,29 @@ void LLAgent::standUp() } +void LLAgent::handleServerBakeRegionTransition(const LLUUID& region_id) +{ + llinfos << "called" << llendl; + + + // Old-style appearance entering a server-bake region. + if (isAgentAvatarValid() && + !gAgentAvatarp->isUsingServerBakes() && + (mRegionp->getCentralBakeVersion()>0)) + { + llinfos << "update requested due to region transition" << llendl; + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } + // new-style appearance entering a non-bake region, + // need to check for existence of the baking service. + else if (isAgentAvatarValid() && + gAgentAvatarp->isUsingServerBakes() && + mRegionp->getCentralBakeVersion()==0) + { + gAgentAvatarp->checkForUnsupportedServerBakeAppearance(); + } +} + //----------------------------------------------------------------------------- // setRegion() //----------------------------------------------------------------------------- @@ -903,6 +927,19 @@ void LLAgent::setRegion(LLViewerRegion *regionp) { LLEnvManagerNew::instance().onRegionCrossing(); } + + // If the newly entered region is using server bakes, and our + // current appearance is non-baked, request appearance update from + // server. + if (mRegionp->capabilitiesReceived()) + { + handleServerBakeRegionTransition(mRegionp->getRegionID()); + } + else + { + // Need to handle via callback after caps arrive. + mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::handleServerBakeRegionTransition,this,_1)); + } } @@ -1685,13 +1722,11 @@ void LLAgent::autoPilot(F32 *delta_yaw) *delta_yaw = yaw; - // Compute when to start slowing down and when to stop - F32 stop_distance = mAutoPilotStopDistance; + // Compute when to start slowing down F32 slow_distance; if (getFlying()) { slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f); - stop_distance = llmax(2.f, mAutoPilotStopDistance); } else { @@ -2277,7 +2312,7 @@ void LLAgent::setStartPosition( U32 location_id ) if (isAgentAvatarValid()) { // the z height is at the agent's feet - agent_pos.mV[VZ] -= 0.5f * gAgentAvatarp->mBodySize.mV[VZ]; + agent_pos.mV[VZ] -= 0.5f * (gAgentAvatarp->mBodySize.mV[VZ] + gAgentAvatarp->mAvatarOffset.mV[VZ]); } agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET ); @@ -2496,7 +2531,7 @@ public: virtual ~LLMaturityPreferencesResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); protected: @@ -2534,11 +2569,11 @@ void LLMaturityPreferencesResponder::result(const LLSD &pContent) mAgent->handlePreferredMaturityResult(actualMaturity); } -void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason) +void LLMaturityPreferencesResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) { llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error because '" - << pReason << "' [status:" << pStatus << "]" << llendl; + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error with [status:" + << pStatus << "]: " << (pContent.isDefined() ? pContent : LLSD(pReason)) << llendl; mAgent->handlePreferredMaturityError(); } @@ -2698,7 +2733,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If we don't have a region, report it as an error if (getRegion() == NULL) { - responderPtr->error(0U, "region is not defined"); + responderPtr->errorWithContent(0U, "region is not defined", LLSD()); } else { @@ -2708,7 +2743,8 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If the capability is not defined, report it as an error if (url.empty()) { - responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); + responderPtr->errorWithContent(0U, + "capability 'UpdateAgentInformation' is not defined for region", LLSD()); } else { @@ -3576,7 +3612,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * return; } - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) { // ignore baked textures when in customize mode return; @@ -3600,7 +3636,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * if ((S32)texture_index < TEX_NUM_INDICES ) { - const LLVOAvatarDictionary::TextureEntry *texture_entry = LLVOAvatarDictionary::instance().getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index); if (texture_entry) { EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex; @@ -4207,27 +4243,82 @@ void LLAgent::requestLeaveGodMode() sendReliableMessage(); } +// For debugging, trace agent state at times appearance message are sent out. +void LLAgent::dumpSentAppearance(const std::string& dump_prefix) +{ + std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml"); + + LLAPRFile outfile; + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + outfile.open(fullpath, LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle(); + if (!file) + { + return; + } + else + { + LL_DEBUGS("Avatar") << "dumping sent appearance message to " << fullpath << llendl; + } + + LLVisualParam* appearance_version_param = gAgentAvatarp->getVisualParam(11000); + if (appearance_version_param) + { + F32 value = appearance_version_param->getWeight(); + dump_visual_param(file, appearance_version_param, value); + } + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (texture_dict->mIsBakedTexture) + { + LLTextureEntry* entry = gAgentAvatarp->getTE((U8) index); + const LLUUID& uuid = entry->getID(); + apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", index, uuid.asString().c_str()); + } + } +} + //----------------------------------------------------------------------------- // sendAgentSetAppearance() //----------------------------------------------------------------------------- void LLAgent::sendAgentSetAppearance() { - if (!isAgentAvatarValid()) return; - - if (gAgentQueryManager.mNumPendingQueries > 0 && (isAgentAvatarValid() && gAgentAvatarp->isUsingBakedTextures())) + if (gAgentQueryManager.mNumPendingQueries > 0) { return; } - if (!gAgentWearables.changeInProgress()) + if (!isAgentAvatarValid() || (getRegion() && getRegion()->getCentralBakeVersion())) return; + + // At this point we have a complete appearance to send and are in a non-baking region. + // DRANO FIXME + //gAgentAvatarp->setIsUsingServerBakes(FALSE); + S32 sb_count, host_count, both_count, neither_count; + gAgentAvatarp->bakedTextureOriginCounts(sb_count, host_count, both_count, neither_count); + if (both_count != 0 || neither_count != 0) { - // Change is fully resolved, can close some open phases. - gAgentAvatarp->getPhases().stopPhase("process_initial_wearables_update"); - gAgentAvatarp->getPhases().stopPhase("wear_inventory_category"); + llwarns << "bad bake texture state " << sb_count << "," << host_count << "," << both_count << "," << neither_count << llendl; + } + if (sb_count != 0 && host_count == 0) + { + gAgentAvatarp->setIsUsingServerBakes(true); + } + else if (sb_count == 0 && host_count != 0) + { + gAgentAvatarp->setIsUsingServerBakes(false); + } + else if (sb_count + host_count > 0) + { + llwarns << "unclear baked texture state, not sending appearance" << llendl; + return; } - gAgentAvatarp->sendAppearanceChangeMetrics(); - LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL; + + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL; //dumpAvatarTEs( "sendAgentSetAppearance()" ); LLMessageSystem* msg = gMessageSystem; @@ -4241,7 +4332,7 @@ void LLAgent::sendAgentSetAppearance() // 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 = gAgentAvatarp->mBodySize; + const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset; msg->addVector3Fast(_PREHASH_Size, body_size); // To guard against out of order packets @@ -4255,7 +4346,7 @@ void LLAgent::sendAgentSetAppearance() for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) { - const ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((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 && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) @@ -4266,19 +4357,30 @@ void LLAgent::sendAgentSetAppearance() // IMG_DEFAULT_AVATAR means not baked. 0 index should be ignored for baked textures if (!gAgentAvatarp->isTextureDefined(texture_index, 0)) { + LL_DEBUGS("Avatar") << "texture not current for baked " << (S32)baked_index << " local " << (S32)texture_index << llendl; textures_current = FALSE; break; } } // only update cache entries if we have all our baked textures + + // FIXME DRANO need additional check for not in appearance editing + // mode, if still using local composites need to set using local + // composites to false, and update mesh textures. if (textures_current) { - LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL; + bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); + std::string dump_prefix = gAgentAvatarp->getFullname() + "_sent_appearance"; + if (enable_verbose_dumps) + { + dumpSentAppearance(dump_prefix); + } + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { BOOL generate_valid_hash = TRUE; - if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index)) + if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLAvatarAppearanceDefines::EBakedTextureIndex)baked_index)) { generate_valid_hash = FALSE; LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL; @@ -4287,7 +4389,7 @@ void LLAgent::sendAgentSetAppearance() const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); if (hash.notNull()) { - ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); + ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); msg->nextBlockFast(_PREHASH_WearableData); msg->addUUIDFast(_PREHASH_CacheID, hash); msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); @@ -4323,7 +4425,7 @@ void LLAgent::sendAgentSetAppearance() } } -// llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; + //llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; sendReliableMessage(); } diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index daa15b0c1a..f5f26f69d8 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -33,7 +33,8 @@ #include "llagentdata.h" // gAgentID, gAgentSessionID #include "llcharacter.h" #include "llcoordframe.h" // for mFrameAgent -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" +#include "llpermissionsflags.h" #include <boost/function.hpp> #include <boost/shared_ptr.hpp> @@ -608,6 +609,7 @@ private: void handleTeleportFinished(); void handleTeleportFailed(); + void handleServerBakeRegionTransition(const LLUUID& region_id); //-------------------------------------------------------------------- // Teleport State @@ -842,6 +844,7 @@ private: public: void sendMessage(); // Send message to this agent's region void sendReliableMessage(); + void dumpSentAppearance(const std::string& dump_prefix); void sendAgentSetAppearance(); void sendAgentDataUpdateRequest(); void sendAgentUserInfoRequest(); @@ -900,7 +903,7 @@ private: S32 mNumPendingQueries; S32 mWearablesCacheQueryID; U32 mUpdateSerialNum; - S32 mActiveCacheQueries[LLVOAvatarDefines::BAKED_NUM_INDICES]; + S32 mActiveCacheQueries[LLAvatarAppearanceDefines::BAKED_NUM_INDICES]; }; extern LLAgentQueryManager gAgentQueryManager; diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 9025c7af8b..0896aa5972 100755 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -50,7 +50,7 @@ #include "llwindow.h" #include "llworld.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; extern LLMenuBarGL* gMenuBarView; @@ -594,7 +594,6 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance) abs_target_offset.abs(); LLVector3 target_offset_dir = target_offset_origin; - F32 object_radius = mFocusObject->getVObjRadius(); BOOL target_outside_object_extents = FALSE; @@ -689,17 +688,6 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance) 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; @@ -1079,8 +1067,8 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) if (!isAgentAvatarValid()) return; - LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot.getWorldRotation(); - LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot.getWorldRotation(); + LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); + LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && (root_at * last_at_axis > 0.95f)) @@ -1433,7 +1421,7 @@ void LLAgentCamera::updateCamera() LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); LLVector3 diff = mCameraPositionAgent - head_pos; - diff = diff * ~gAgentAvatarp->mRoot.getWorldRotation(); + diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); LLJoint* torso_joint = gAgentAvatarp->mTorsop; LLJoint* chest_joint = gAgentAvatarp->mChestp; @@ -1457,7 +1445,7 @@ void LLAgentCamera::updateCamera() gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); - gAgentAvatarp->mRoot.updateWorldMatrixChildren(); + gAgentAvatarp->mRoot->updateWorldMatrixChildren(); for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ) @@ -1658,7 +1646,6 @@ F32 LLAgentCamera::calcCameraFOVZoomFactor() else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) { // 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()); @@ -1685,7 +1672,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) F32 camera_land_height; LLVector3d frame_center_global = !isAgentAvatarValid() ? gAgent.getPositionGlobal() : - gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition()); + gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); BOOL isConstrained = FALSE; LLVector3d head_offset; @@ -1820,7 +1807,6 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) // set the global camera position LLVector3d camera_offset; - LLVector3 av_pos = !isAgentAvatarValid() ? LLVector3::zero : gAgentAvatarp->getRenderPosition(); camera_offset.setVec( local_camera_offset ); camera_position_global = frame_center_global + head_offset + camera_offset; @@ -2257,7 +2243,7 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToCustomizeAvatar() { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) + if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) { return; } @@ -2281,29 +2267,21 @@ void LLAgentCamera::changeCameraToCustomizeAvatar() gFocusMgr.setKeyboardFocus( NULL ); gFocusMgr.setMouseCapture( NULL ); - LLVOAvatarSelf::onCustomizeStart(); + // Remove any pitch or rotation from the avatar + LLVector3 at = gAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); - if (isAgentAvatarValid()) - { - // Remove any pitch or rotation from the avatar - LLVector3 at = gAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); + gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); + gAgent.setCustomAnim(TRUE); + gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); - gAgent.setCustomAnim(TRUE); - gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); - LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - - if (turn_motion) - { - // delay camera animation long enough to play through turn animation - setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); - } - - gAgentAvatarp->invalidateAll(); - gAgentAvatarp->updateMeshTextures(); + if (turn_motion) + { + // delay camera animation long enough to play through turn animation + setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); } } diff --git a/indra/newview/llagentpilot.cpp b/indra/newview/llagentpilot.cpp index 734c502fcf..c7872fc5f6 100755 --- a/indra/newview/llagentpilot.cpp +++ b/indra/newview/llagentpilot.cpp @@ -139,7 +139,7 @@ void LLAgentPilot::loadXML(const std::string& filename) mActions.reset(); LLSD record; - while (!file.eof() && LLSDSerialize::fromXML(record, file)) + while (!file.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(record, file)) { Action action; action.mTime = record["time"].asReal(); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e441f21f90..c88694ef76 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -47,7 +47,7 @@ #include "lltooldraganddrop.h" #include "llviewerregion.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llwearablelist.h" #include <boost/scoped_ptr.hpp> @@ -56,24 +56,21 @@ LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; /////////////////////////////////////////////////////////////////////////////// // Callback to wear and start editing an item that has just been created. -class LLWearAndEditCallback : public LLInventoryCallback +void wear_and_edit_cb(const LLUUID& inv_item) { - void fire(const LLUUID& inv_item) - { - if (inv_item.isNull()) return; - - // Request editing the item after it gets worn. - gAgentWearables.requestEditingWearable(inv_item); - - // Wear it. - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); - } -}; + if (inv_item.isNull()) return; + + // Request editing the item after it gets worn. + gAgentWearables.requestEditingWearable(inv_item); + + // Wear it. + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); +} /////////////////////////////////////////////////////////////////////////////// @@ -82,7 +79,7 @@ class LLWearAndEditCallback : public LLInventoryCallback // wearable type stored in asset is some other value. // Calling this function whenever a wearable is added to increase visibility if this problem // turns up in other inventories. -void checkWearableAgainstInventory(LLWearable *wearable) +void checkWearableAgainstInventory(LLViewerWearable *wearable) { if (wearable->getItemID().isNull()) return; @@ -119,7 +116,7 @@ void LLAgentWearables::dump() llinfos << "Type: " << i << " count " << count << llendl; for (U32 j=0; j<count; j++) { - LLWearable* wearable = getWearable((LLWearableType::EType)i,j); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)i,j); if (wearable == NULL) { llinfos << " " << j << " NULL wearable" << llendl; @@ -159,6 +156,7 @@ struct LLAgentDumper }; LLAgentWearables::LLAgentWearables() : + LLWearableData(), mWearablesLoaded(FALSE) , mCOFChangeInProgress(false) { @@ -182,12 +180,11 @@ void LLAgentWearables::initClass() } void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) -{ - if (avatar) - { - avatar->outputRezTiming("Sending wearables request"); - sendAgentWearablesRequest(); - } +{ + llassert(avatar); + avatar->outputRezTiming("Sending wearables request"); + sendAgentWearablesRequest(); + setAvatarAppearance(avatar); } // wearables @@ -213,12 +210,13 @@ LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCal * @param todo Bitmask of actions to take on completion. */ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback( - LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, LLWearable* wearable, U32 todo) : + LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo, const std::string description) : mType(type), mIndex(index), mWearable(wearable), mTodo(todo), - mCB(cb) + mCB(cb), + mDescription(description) { llinfos << "constructor" << llendl; } @@ -258,14 +256,14 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_WEARITEM) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item, true); + LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription); } } void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::EType type, const U32 index, const LLUUID& item_id, - LLWearable* wearable) + LLViewerWearable* wearable) { llinfos << "type " << type << " index " << index << " item " << item_id.asString() << llendl; @@ -312,7 +310,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() { for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index) { - LLWearable* wearable = getWearable((LLWearableType::EType)type,index); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type,index); if (wearable) { if (wearable->getItemID().isNull()) @@ -354,7 +352,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() U8 type_u8 = (U8)type; gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8); - LLWearable* wearable = getWearable((LLWearableType::EType)type, 0); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type, 0); if (wearable) { //llinfos << "Sending wearable " << wearable->getName() << llendl; @@ -382,14 +380,14 @@ void LLAgentWearables::sendAgentWearablesUpdate() void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update, const std::string new_name) { - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); if(!old_wearable) return; bool name_changed = !new_name.empty() && (new_name != old_wearable->getName()); if (name_changed || old_wearable->isDirty() || old_wearable->isOldVersion()) { LLUUID old_item_id = old_wearable->getItemID(); - LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); - new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()? + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); + new_wearable->setItemID(old_item_id); // should this be in LLViewerWearable::copyDataFrom()? setWearable(type,index,new_wearable); // old_wearable may still be referred to by other inventory items. Revert @@ -458,6 +456,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, + const std::string& description, BOOL save_in_lost_and_found) { if (!isWearableCopyable(type, index)) @@ -465,7 +464,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; return; } - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); if (!old_wearable) { llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; @@ -480,7 +479,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, } std::string trunc_name(new_name); LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); - LLWearable* new_wearable = LLWearableList::instance().createCopy( + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy( old_wearable, trunc_name); LLPointer<LLInventoryCallback> cb = @@ -489,7 +488,9 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, type, index, new_wearable, - addWearableToAgentInventoryCallback::CALL_WEARITEM); + addWearableToAgentInventoryCallback::CALL_WEARITEM, + description + ); LLUUID category_id; if (save_in_lost_and_found) { @@ -518,7 +519,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) { - LLWearable* wearable = getWearable(type, index); + LLViewerWearable* wearable = getViewerWearable(type, index); llassert(wearable); if (wearable) { @@ -553,13 +554,13 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& LLUUID curr_item_id = getWearableItemID((LLWearableType::EType)i,j); if (curr_item_id == item_id) { - LLWearable* old_wearable = getWearable((LLWearableType::EType)i,j); + LLViewerWearable* old_wearable = getViewerWearable((LLWearableType::EType)i,j); llassert(old_wearable); if (!old_wearable) continue; std::string old_name = old_wearable->getName(); old_wearable->setName(new_name); - LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); new_wearable->setItemID(item_id); LLInventoryItem* item = gInventory.getItem(item_id); if (item) @@ -640,14 +641,14 @@ LLInventoryItem* LLAgentWearables::getWearableInventoryItem(LLWearableType::ETyp return item; } -const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const +const LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - const LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + const LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -657,14 +658,14 @@ const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) return NULL; } -LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) +LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -674,13 +675,13 @@ LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) return NULL; } -LLWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_id) +LLViewerWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_id) { for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getAssetID() == asset_id)) { return curr_wearable; @@ -699,215 +700,55 @@ void LLAgentWearables::sendAgentWearablesRequest() gAgent.sendReliableMessage(); } -// static -BOOL LLAgentWearables::selfHasWearable(LLWearableType::EType type) -{ - return (gAgentWearables.getWearableCount(type) > 0); -} - -LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) -{ - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; - } -} - -void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) +LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) { - - LLWearable *old_wearable = getWearable(type,index); - if (!old_wearable) - { - pushWearable(type,wearable); - return; - } - - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - llwarns << "invalid type, type " << type << " index " << index << llendl; - return; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - llwarns << "invalid index, type " << type << " index " << index << llendl; - } - else - { - wearable_vec[index] = wearable; - old_wearable->setLabelUpdated(); - wearableUpdated(wearable); - checkWearableAgainstInventory(wearable); - } + return dynamic_cast<LLViewerWearable*> (getWearable(type, index)); } -U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLWearable *wearable) +const LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) const { - if (wearable == NULL) - { - // no null wearables please! - llwarns << "Null wearable sent for type " << type << llendl; - return MAX_CLOTHING_PER_TYPE; - } - if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) - { - mWearableDatas[type].push_back(wearable); - wearableUpdated(wearable); - checkWearableAgainstInventory(wearable); - return mWearableDatas[type].size()-1; - } - return MAX_CLOTHING_PER_TYPE; + return dynamic_cast<const LLViewerWearable*> (getWearable(type, index)); } -void LLAgentWearables::wearableUpdated(LLWearable *wearable) +// static +BOOL LLAgentWearables::selfHasWearable(LLWearableType::EType type) { - gAgentAvatarp->wearableUpdated(wearable->getType(), FALSE); - wearable->refreshName(); - wearable->setLabelUpdated(); - - wearable->pullCrossWearableValues(); - - // Hack pt 2. If the wearable we just loaded has definition version 24, - // then force a re-save of this wearable after slamming the version number to 22. - // This number was incorrectly incremented for internal builds before release, and - // this fix will ensure that the affected wearables are re-saved with the right version number. - // the versions themselves are compatible. This code can be removed before release. - if( wearable->getDefinitionVersion() == 24 ) - { - wearable->setDefinitionVersion(22); - U32 index = getWearableIndex(wearable); - llinfos << "forcing werable type " << wearable->getType() << " to version 22 from 24" << llendl; - saveWearable(wearable->getType(),index,TRUE); - } - + return (gAgentWearables.getWearableCount(type) > 0); } -void LLAgentWearables::popWearable(LLWearable *wearable) +// virtual +void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) { - if (wearable == NULL) + if (isAgentAvatarValid()) { - // nothing to do here. move along. - return; + const BOOL upload_result = removed; + gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result); } - U32 index = getWearableIndex(wearable); - LLWearableType::EType type = wearable->getType(); + LLWearableData::wearableUpdated(wearable, removed); - if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type)) + if (!removed) { - popWearable(type, index); - } -} + LLViewerWearable* viewer_wearable = dynamic_cast<LLViewerWearable*>(wearable); + viewer_wearable->refreshName(); -void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) -{ - LLWearable *wearable = getWearable(type, index); - if (wearable) - { - mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - if (isAgentAvatarValid()) + // Hack pt 2. If the wearable we just loaded has definition version 24, + // then force a re-save of this wearable after slamming the version number to 22. + // This number was incorrectly incremented for internal builds before release, and + // this fix will ensure that the affected wearables are re-saved with the right version number. + // the versions themselves are compatible. This code can be removed before release. + if( wearable->getDefinitionVersion() == 24 ) { - gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); + wearable->setDefinitionVersion(22); + U32 index = getWearableIndex(wearable); + llinfos << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << llendl; + saveWearable(wearable->getType(),index,TRUE); } - wearable->setLabelUpdated(); - } -} -U32 LLAgentWearables::getWearableIndex(const LLWearable *wearable) const -{ - if (wearable == NULL) - { - return MAX_CLOTHING_PER_TYPE; + checkWearableAgainstInventory(viewer_wearable); } - - const LLWearableType::EType type = wearable->getType(); - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - llwarns << "tried to get wearable index with an invalid type!" << llendl; - return MAX_CLOTHING_PER_TYPE; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - for(U32 index = 0; index < wearable_vec.size(); index++) - { - if (wearable_vec[index] == wearable) - { - return index; - } - } - - return MAX_CLOTHING_PER_TYPE; } -const LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; - } -} - -LLWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type) -{ - U32 count = getWearableCount(type); - if ( count == 0) - { - return NULL; - } - - return getWearable(type, count-1); -} - -LLWearable* LLAgentWearables::getBottomWearable(const LLWearableType::EType type) -{ - if (getWearableCount(type) == 0) - { - return NULL; - } - - return getWearable(type, 0); -} - -U32 LLAgentWearables::getWearableCount(const LLWearableType::EType type) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return 0; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - return wearable_vec.size(); -} - -U32 LLAgentWearables::getWearableCount(const U32 tex_index) const -{ - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)tex_index); - return getWearableCount(wearable_type); -} - - BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const { return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end(); @@ -920,7 +761,7 @@ U32 LLAgentWearables::itemUpdatePendingCount() const const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const { - const LLWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getViewerWearable(type,index); if (wearable) return wearable->getItemID(); else @@ -929,7 +770,7 @@ const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 const LLUUID LLAgentWearables::getWearableAssetID(LLWearableType::EType type, U32 index) const { - const LLWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getViewerWearable(type,index); if (wearable) return wearable->getAssetID(); else @@ -955,8 +796,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs if (isAgentAvatarValid()) { - //gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading. - gAgentAvatarp->getPhases().startPhase("process_initial_wearables_update"); + gAgentAvatarp->startPhase("process_initial_wearables_update"); gAgentAvatarp->outputRezTiming("Received initial wearables update"); } @@ -1012,7 +852,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i); if (asset_id.isNull()) { - LLWearable::removeFromAvatar(type, FALSE); + LLViewerWearable::removeFromAvatar(type, FALSE); } else { @@ -1058,7 +898,7 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type, // Try to recover by replacing missing wearable with a new one. LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; - LLWearable* new_wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* new_wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); setWearable(type,index,new_wearable); //new_wearable->writeToAvatar(TRUE); @@ -1093,9 +933,9 @@ void LLAgentWearables::recoverMissingWearableDone() } } -void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index) +void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index) { - LLWearable* wearable = getWearable((LLWearableType::EType)wearable_type, wearable_index); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)wearable_type, wearable_index); if (!wearable) { llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl; @@ -1125,10 +965,10 @@ public: llinfos << "All items created" << llendl; LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; LLAppearanceMgr::instance().linkAll(LLAppearanceMgr::instance().getCOF(), - mItemsToLink, - link_waiter); + mItemsToLink, + link_waiter); } - void addPendingWearable(LLWearable *wearable) + void addPendingWearable(LLViewerWearable *wearable) { if (!wearable) { @@ -1163,7 +1003,7 @@ public: LLWearableType::EType type = item->getWearableType(); if (type < LLWearableType::WT_COUNT) { - LLWearable *wearable = mWearablesAwaitingItems[type]; + LLViewerWearable *wearable = mWearablesAwaitingItems[type]; if (wearable) wearable->setItemID(inv_item); } @@ -1176,7 +1016,7 @@ public: private: LLInventoryModel::item_array_t mItemsToLink; - std::vector<LLWearable*> mWearablesAwaitingItems; + std::vector<LLViewerWearable*> mWearablesAwaitingItems; }; void LLAgentWearables::createStandardWearables() @@ -1208,7 +1048,7 @@ void LLAgentWearables::createStandardWearables() if (create[i]) { llassert(getWearableCount((LLWearableType::EType)i) == 0); - LLWearable* wearable = LLWearableList::instance().createNewWearable((LLWearableType::EType)i); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable((LLWearableType::EType)i, gAgentAvatarp); ((OnWearableItemCreatedCB*)(&(*cb)))->addPendingWearable(wearable); // no need to update here... LLUUID category_id = LLUUID::null; @@ -1267,7 +1107,7 @@ void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback> cb, - LLWearable* wearable, + LLViewerWearable* wearable, const LLUUID& category_id, BOOL notify) { @@ -1305,7 +1145,7 @@ void LLAgentWearables::removeWearable(const LLWearableType::EType type, bool do_ } else { - LLWearable* old_wearable = getWearable(type,index); + LLViewerWearable* old_wearable = getViewerWearable(type,index); if (old_wearable) { @@ -1360,10 +1200,10 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo //LLAgentDumper dumper("removeWearable"); if (do_remove_all) { - S32 max_entry = mWearableDatas[type].size()-1; + S32 max_entry = getWearableCount(type)-1; for (S32 i=max_entry; i>=0; i--) { - LLWearable* old_wearable = getWearable(type,i); + LLViewerWearable* old_wearable = getViewerWearable(type,i); //queryWearableCache(); // moved below if (old_wearable) { @@ -1371,11 +1211,11 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo old_wearable->removeFromAvatar(TRUE); } } - mWearableDatas[type].clear(); + clearWearableType(type); } else { - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); //queryWearableCache(); // moved below if (old_wearable) @@ -1394,7 +1234,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo // Assumes existing wearables are not dirty. void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items, - const LLDynamicArray< LLWearable* >& wearables, + const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove) { llinfos << "setWearableOutfit() start" << llendl; @@ -1419,7 +1259,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it S32 i; for (i = 0; i < count; i++) { - LLWearable* new_wearable = wearables[i]; + LLViewerWearable* new_wearable = wearables[i]; LLPointer<LLInventoryItem> new_item = items[i]; llassert(new_wearable); @@ -1439,8 +1279,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { pushWearable(type,new_wearable); } - wearableUpdated(new_wearable); - checkWearableAgainstInventory(new_wearable); + const BOOL removed = FALSE; + wearableUpdated(new_wearable, removed); } } @@ -1476,7 +1316,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // User has picked "wear on avatar" from a menu. -void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) +void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) { //LLAgentDumper dumper("setWearableItem"); if (isWearingItem(new_item->getUUID())) @@ -1491,7 +1331,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* ne { // Remove old wearable, if any // MULTI_WEARABLE: hardwired to 0 - LLWearable* old_wearable = getWearable(type,0); + LLViewerWearable* old_wearable = getViewerWearable(type,0); if (old_wearable) { const LLUUID& old_item_id = old_wearable->getItemID(); @@ -1517,7 +1357,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* ne } // static -bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable) +bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); @@ -1553,16 +1393,17 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& // Called from setWearableItem() and onSetWearableDialog() to actually set the wearable. // MULTI_WEARABLE: unify code after null objects are gone. -void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) +void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) { const LLWearableType::EType type = new_wearable->getType(); if (do_append && getWearableItemID(type,0).notNull()) { new_wearable->setItemID(new_item->getUUID()); - mWearableDatas[type].push_back(new_wearable); + const bool trigger_updated = false; + pushWearable(type, new_wearable, trigger_updated); llinfos << "Added additional wearable for type " << type - << " size is now " << mWearableDatas[type].size() << llendl; + << " size is now " << getWearableCount(type) << llendl; checkWearableAgainstInventory(new_wearable); } else @@ -1570,7 +1411,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n // Replace the old wearable with a new one. llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); - LLWearable *old_wearable = getWearable(type,0); + LLViewerWearable *old_wearable = getViewerWearable(type,0); LLUUID old_item_id; if (old_wearable) { @@ -1585,7 +1426,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n gInventory.notifyObservers(); } llinfos << "Replaced current element 0 for type " << type - << " size is now " << mWearableDatas[type].size() << llendl; + << " size is now " << getWearableCount(type) << llendl; } //llinfos << "LLVOAvatar::setWearableItem()" << llendl; @@ -1597,7 +1438,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n void LLAgentWearables::queryWearableCache() { - if (!areWearablesLoaded()) + if (!areWearablesLoaded() || (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion())) { return; } @@ -1626,7 +1467,7 @@ void LLAgentWearables::queryWearableCache() num_queries++; // *NOTE: make sure at least one request gets packed - ETextureIndex te_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl; gMessageSystem->nextBlockFast(_PREHASH_WearableData); @@ -1645,53 +1486,21 @@ void LLAgentWearables::queryWearableCache() gAgentAvatarp->outputRezTiming("Fetching textures from cache"); } - LL_INFOS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL; + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL; gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); gAgentQueryManager.mNumPendingQueries++; gAgentQueryManager.mWearablesCacheQueryID++; } } -LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index, - BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache +// virtual +void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const { - LLUUID hash_id; - bool hash_computed = false; - LLMD5 hash; - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); - - for (U8 i=0; i < baked_dict->mWearables.size(); i++) - { - const LLWearableType::EType baked_type = baked_dict->mWearables[i]; - const U32 num_wearables = getWearableCount(baked_type); - for (U32 index = 0; index < num_wearables; ++index) - { - const LLWearable* wearable = getWearable(baked_type,index); - if (wearable) - { - LLUUID asset_id = wearable->getAssetID(); - hash.update((const unsigned char*)asset_id.mData, UUID_BYTES); - hash_computed = true; - } - } - } - if (hash_computed) + // Add some garbage into the hash so that it becomes invalid. + if (isAgentAvatarValid()) { - hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES); - - // Add some garbage into the hash so that it becomes invalid. - if (!generate_valid_hash) - { - if (isAgentAvatarValid()) - { - hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES); - } - } - hash.finalize(); - hash.raw_digest(hash_id.mData); + hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES); } - - return hash_id; } // User has picked "remove from avatar" from a menu. @@ -1715,7 +1524,7 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty } } -// Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to +// Combines userRemoveMulipleAttachments() and userAttachMultipleAttachments() logic to // get attachments into desired state with minimal number of adds/removes. void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array) { @@ -1811,31 +1620,6 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo gMessageSystem->sendReliable(gAgent.getRegionHost()); } -void LLAgentWearables::userRemoveAllAttachments() -{ - if (!isAgentAvatarValid()) return; - - llvo_vec_t objects_to_remove; - - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end();) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *attached_object = (*attachment_iter); - if (attached_object) - { - objects_to_remove.push_back(attached_object); - } - } - } - userRemoveMultipleAttachments(objects_to_remove); -} - void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array) { // Build a compound message to send all the objects that need to be rezzed. @@ -1900,7 +1684,7 @@ void LLAgentWearables::checkWearablesLoaded() const // Returns false if the given wearable is already topmost/bottommost // (depending on closer_to_body parameter). -bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) +bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const { const LLWearable* wearable = getWearableFromItemID(item_id); if (!wearable) return false; @@ -1928,7 +1712,7 @@ void LLAgentWearables::updateWearablesLoaded() } } -bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const +bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) const { if (!wearable) return false; @@ -1943,7 +1727,7 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake) { for (S32 count = 0; count < (S32)getWearableCount((LLWearableType::EType)type); ++count) { - LLWearable *wearable = getWearable((LLWearableType::EType)type,count); + LLViewerWearable *wearable = getViewerWearable((LLWearableType::EType)type,count); llassert(wearable); if (wearable) { @@ -1958,28 +1742,39 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos if (!item) return false; if (!item->isWearableType()) return false; - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(item->getWearableType()); - if (wearable_iter == mWearableDatas.end()) return false; - - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (wearable_vec.empty()) return false; + LLWearableType::EType type = item->getWearableType(); + U32 wearable_count = getWearableCount(type); + if (0 == wearable_count) return false; const LLUUID& asset_id = item->getAssetUUID(); //nowhere to move if the wearable is already on any boundary (closest to the body/furthest from the body) - if (closer_to_body && asset_id == wearable_vec.front()->getAssetID()) return false; - if (!closer_to_body && asset_id == wearable_vec.back()->getAssetID()) return false; + if (closer_to_body) + { + LLViewerWearable* bottom_wearable = dynamic_cast<LLViewerWearable*>( getBottomWearable(type) ); + if (bottom_wearable->getAssetID() == asset_id) + { + return false; + } + } + else // !closer_to_body + { + LLViewerWearable* top_wearable = dynamic_cast<LLViewerWearable*>( getTopWearable(type) ); + if (top_wearable->getAssetID() == asset_id) + { + return false; + } + } - for (U32 i = 0; i < wearable_vec.size(); ++i) + for (U32 i = 0; i < wearable_count; ++i) { - LLWearable* wearable = wearable_vec[i]; + LLViewerWearable* wearable = getViewerWearable(type, i); if (!wearable) continue; if (wearable->getAssetID() != asset_id) continue; //swapping wearables U32 swap_i = closer_to_body ? i-1 : i+1; - wearable_vec[i] = wearable_vec[swap_i]; - wearable_vec[swap_i] = wearable; + swapWearables(type, i, swap_i); return true; } @@ -1991,10 +1786,10 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con { if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return; - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); LLAssetType::EType asset_type = wearable->getAssetType(); LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; - LLPointer<LLInventoryCallback> cb = wear ? new LLWearAndEditCallback : NULL; + LLPointer<LLInventoryCallback> cb = wear ? new LLBoostFuncInventoryCallback(wear_and_edit_cb) : NULL; LLUUID folder_id; if (parent_id.notNull()) @@ -2024,7 +1819,7 @@ void LLAgentWearables::editWearable(const LLUUID& item_id) return; } - LLWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); + LLViewerWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); if (!wearable) { llwarns << "Cannot get wearable" << llendl; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 5932be21c6..5be4648636 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -36,16 +36,16 @@ // newview #include "llinventorymodel.h" #include "llviewerinventory.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" +#include "llwearabledata.h" class LLInventoryItem; class LLVOAvatarSelf; -class LLWearable; +class LLViewerWearable; class LLInitialWearablesFetch; class LLViewerObject; -class LLTexLayerTemplate; -class LLAgentWearables : public LLInitClass<LLAgentWearables> +class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearableData { //-------------------------------------------------------------------- // Constructors / destructors / Initializers @@ -79,10 +79,10 @@ public: bool isCOFChangeInProgress() const { return mCOFChangeInProgress; } void updateWearablesLoaded(); void checkWearablesLoaded() const; - bool canMoveWearable(const LLUUID& item_id, bool closer_to_body); + bool canMoveWearable(const LLUUID& item_id, bool closer_to_body) const; // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1. - bool canWearableBeRemoved(const LLWearable* wearable) const; + bool canWearableBeRemoved(const LLViewerWearable* wearable) const; void animateAllWearableParams(F32 delta, BOOL upload_bake); @@ -92,52 +92,38 @@ public: public: const LLUUID getWearableItemID(LLWearableType::EType type, U32 index /*= 0*/) const; const LLUUID getWearableAssetID(LLWearableType::EType type, U32 index /*= 0*/) const; - const LLWearable* getWearableFromItemID(const LLUUID& item_id) const; - LLWearable* getWearableFromItemID(const LLUUID& item_id); - LLWearable* getWearableFromAssetID(const LLUUID& asset_id); + const LLViewerWearable* getWearableFromItemID(const LLUUID& item_id) const; + LLViewerWearable* getWearableFromItemID(const LLUUID& item_id); + LLViewerWearable* getWearableFromAssetID(const LLUUID& asset_id); + LLViewerWearable* getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLViewerWearable* getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; LLInventoryItem* getWearableInventoryItem(LLWearableType::EType type, U32 index /*= 0*/); static BOOL selfHasWearable(LLWearableType::EType type); - LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); - const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; - LLWearable* getTopWearable(const LLWearableType::EType type); - LLWearable* getBottomWearable(const LLWearableType::EType type); - U32 getWearableCount(const LLWearableType::EType type) const; - U32 getWearableCount(const U32 tex_index) const; - - static const U32 MAX_CLOTHING_PER_TYPE = 5; - //-------------------------------------------------------------------- // Setters //-------------------------------------------------------------------- - private: - // Low-level data structure setter - public access is via setWearableItem, etc. - void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); - U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable); - void wearableUpdated(LLWearable *wearable); - void popWearable(LLWearable *wearable); - void popWearable(const LLWearableType::EType type, U32 index); - + /*virtual*/void wearableUpdated(LLWearable *wearable, BOOL removed); public: - void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false); - void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove); + void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false); + void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); - void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index); - U32 getWearableIndex(const LLWearable *wearable) const; + // *TODO: Move this into llappearance/LLWearableData ? + void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index); protected: - void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false); - static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable); + void setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append = false); + static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable); void addWearableToAgentInventory(LLPointer<LLInventoryCallback> cb, - LLWearable* wearable, + LLViewerWearable* wearable, const LLUUID& category_id = LLUUID::null, BOOL notify = TRUE); void addWearabletoAgentInventoryDone(const LLWearableType::EType type, const U32 index, const LLUUID& item_id, - LLWearable* wearable); + LLViewerWearable* wearable); void recoverMissingWearable(const LLWearableType::EType type, U32 index /*= 0*/); void recoverMissingWearableDone(); @@ -172,15 +158,14 @@ protected: public: // Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant) static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data); - LLUUID computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index, - BOOL generate_valid_hash = TRUE); protected: + /*virtual*/ void invalidateBakedTextureHash(LLMD5& hash) const; void sendAgentWearablesUpdate(); void sendAgentWearablesRequest(); void queryWearableCache(); void updateServer(); - static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata); + static void onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata); //-------------------------------------------------------------------- // Outfits @@ -198,7 +183,7 @@ private: // Save Wearables //-------------------------------------------------------------------- public: - void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found); + void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, const std::string& description, BOOL save_in_lost_and_found); void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE, const std::string new_name = ""); void saveAllWearables(); @@ -215,7 +200,6 @@ public: static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array); static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); - static void userRemoveAllAttachments(); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); BOOL itemUpdatePending(const LLUUID& item_id) const; @@ -245,10 +229,6 @@ private: // Member variables //-------------------------------------------------------------------- private: - typedef std::vector<LLWearable*> wearableentry_vec_t; // all wearables of a certain type (EG all shirts) - typedef std::map<LLWearableType::EType, wearableentry_vec_t> wearableentry_map_t; // wearable "categories" arranged by wearable type - wearableentry_map_t mWearableDatas; - static BOOL mInitialWearablesUpdateReceived; BOOL mWearablesLoaded; std::set<LLUUID> mItemsAwaitingWearableUpdate; @@ -289,15 +269,17 @@ private: addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, - LLWearable* wearable, - U32 todo = CALL_NONE); + LLViewerWearable* wearable, + U32 todo = CALL_NONE, + const std::string description = ""); virtual void fire(const LLUUID& inv_item); private: LLWearableType::EType mType; U32 mIndex; - LLWearable* mWearable; + LLViewerWearable* mWearable; U32 mTodo; LLPointer<LLRefCount> mCB; + std::string mDescription; }; }; // LLAgentWearables diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index e31e39dca2..2d2d730396 100755 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -35,61 +35,52 @@ #include "llvoavatarself.h" -class LLOrderMyOutfitsOnDestroy: public LLInventoryCallback +void order_my_outfits_cb() { -public: - LLOrderMyOutfitsOnDestroy() {}; - - virtual ~LLOrderMyOutfitsOnDestroy() + if (!LLApp::isRunning()) { - if (!LLApp::isRunning()) - { - llwarns << "called during shutdown, skipping" << llendl; - return; - } + llwarns << "called during shutdown, skipping" << llendl; + return; + } - const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - if (my_outfits_id.isNull()) return; - - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(my_outfits_id, cats, items); - if (!cats) return; + const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + if (my_outfits_id.isNull()) return; - //My Outfits should at least contain saved initial outfit and one another outfit - if (cats->size() < 2) - { - llwarning("My Outfits category was not populated properly", 0); - return; - } + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(my_outfits_id, cats, items); + if (!cats) return; - llinfos << "Starting updating My Outfits with wearables ordering information" << llendl; + //My Outfits should at least contain saved initial outfit and one another outfit + if (cats->size() < 2) + { + llwarning("My Outfits category was not populated properly", 0); + return; + } - for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin(); - outfit_iter != cats->end(); ++outfit_iter) - { - const LLUUID& cat_id = (*outfit_iter)->getUUID(); - if (cat_id.isNull()) continue; + llinfos << "Starting updating My Outfits with wearables ordering information" << llendl; - // saved initial outfit already contains wearables ordering information - if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue; + for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin(); + outfit_iter != cats->end(); ++outfit_iter) + { + const LLUUID& cat_id = (*outfit_iter)->getUUID(); + if (cat_id.isNull()) continue; - LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id); - } + // saved initial outfit already contains wearables ordering information + if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue; - llinfos << "Finished updating My Outfits with wearables ordering information" << llendl; + LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id); } - /* virtual */ void fire(const LLUUID& inv_item) {}; -}; - + llinfos << "Finished updating My Outfits with wearables ordering information" << llendl; +} LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) : LLInventoryFetchDescendentsObserver(cof_id) { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().startPhase("initial_wearables_fetch"); + gAgentAvatarp->startPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch started"); } } @@ -108,7 +99,7 @@ void LLInitialWearablesFetch::done() doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this)); if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().stopPhase("initial_wearables_fetch"); + gAgentAvatarp->stopPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch done"); } } @@ -563,7 +554,7 @@ void LLLibraryOutfitsFetch::contentsDone() LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - LLPointer<LLOrderMyOutfitsOnDestroy> order_myoutfits_on_destroy = new LLOrderMyOutfitsOnDestroy; + LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb); for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); folder_iter != mImportedClothingFolders.end(); diff --git a/indra/newview/llappearance.h b/indra/newview/llappearance.h index a28b77b1fc..05dfac4e42 100755 --- a/indra/newview/llappearance.h +++ b/indra/newview/llappearance.h @@ -38,14 +38,14 @@ public: void addParam( S32 id, F32 value ) { mParamMap[id] = value; } F32 getParam( S32 id, F32 defval ) { return get_if_there(mParamMap, id, defval ); } - void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLVOAvatarDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; } - const LLUUID& getTexture( S32 te ) { return ( te < LLVOAvatarDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; } + void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLAvatarAppearanceDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; } + const LLUUID& getTexture( S32 te ) { return ( te < LLAvatarAppearanceDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; } - void clear() { mParamMap.clear(); for( S32 i=0; i<LLVOAvatarDefines::TEX_NUM_INDICES; i++ ) mTextures[i].setNull(); } + void clear() { mParamMap.clear(); for( S32 i=0; i<LLAvatarAppearanceDefines::TEX_NUM_INDICES; i++ ) mTextures[i].setNull(); } typedef std::map<S32, F32> param_map_t; param_map_t mParamMap; - LLUUID mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; + LLUUID mTextures[LLAvatarAppearanceDefines::TEX_NUM_INDICES]; }; #endif // LL_LLAPPEARANCE_H diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 769b4eafe1..652f199e28 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" +#include <boost/lexical_cast.hpp> #include "llaccordionctrltab.h" #include "llagent.h" #include "llagentcamera.h" @@ -49,6 +50,13 @@ #include "llvoavatarself.h" #include "llviewerregion.h" #include "llwearablelist.h" +#include "llsdutil.h" +#include "llsdserialize.h" + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif std::string self_av_string() { @@ -155,71 +163,342 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string } } -class LLWearInventoryCategoryCallback : public LLInventoryCallback +// We want this to be much lower (e.g. 15.0 is usually fine), bumping +// up for now until we can diagnose some cases of very slow response +// to requests. +const F32 DEFAULT_RETRY_AFTER_INTERVAL = 300.0; + +// Given the current back-end problems, retrying is causing too many +// duplicate items. Bump this back to 2 once they are resolved (or can +// leave at 0 if the operations become actually reliable). +const S32 DEFAULT_MAX_RETRIES = 0; + +class LLCallAfterInventoryBatchMgr: public LLEventTimer { public: - LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append) - { - mCatID = cat_id; - mAppend = append; + LLCallAfterInventoryBatchMgr(const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func, + nullary_func_t on_failure_func = no_op, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, + S32 max_retries = DEFAULT_MAX_RETRIES + ): + mDstCatID(dst_cat_id), + mTrackingPhase(phase_name), + mOnCompletionFunc(on_completion_func), + mOnFailureFunc(on_failure_func), + mRetryAfter(retry_after), + mMaxRetries(max_retries), + mPendingRequests(0), + mFailCount(0), + mCompletionOrFailureCalled(false), + mRetryCount(0), + LLEventTimer(5.0) + { + if (!mTrackingPhase.empty()) + { + selfStartPhase(mTrackingPhase); + } + } + + void addItems(LLInventoryModel::item_array_t& src_items) + { + for (LLInventoryModel::item_array_t::const_iterator it = src_items.begin(); + it != src_items.end(); + ++it) + { + LLViewerInventoryItem* item = *it; + llassert(item); + addItem(item->getUUID()); + } + } - LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + // Request or re-request operation for specified item. + void addItem(const LLUUID& item_id) + { + LL_DEBUGS("Avatar") << "item_id " << item_id << llendl; - selfStartPhase("wear_inventory_category_callback"); + if (!requestOperation(item_id)) + { + LL_DEBUGS("Avatar") << "item_id " << item_id << " requestOperation false, skipping" << llendl; + return; + } + + mPendingRequests++; + // On a re-request, this will reset the timer. + mWaitTimes[item_id] = LLTimer(); + if (mRetryCounts.find(item_id) == mRetryCounts.end()) + { + mRetryCounts[item_id] = 0; + } + else + { + mRetryCounts[item_id]++; + } } - void fire(const LLUUID& item_id) + + virtual bool requestOperation(const LLUUID& item_id) = 0; + + void onOp(const LLUUID& src_id, const LLUUID& dst_id, LLTimer timestamp) { - /* - * Do nothing. We only care about the destructor - * - * The reason for this is that this callback is used in a hack where the - * same callback is given to dozens of items, and the destructor is called - * after the last item has fired the event and dereferenced it -- if all - * the events actually fire! - */ - LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL; + if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateLateOpRate")) + { + llwarns << "Simulating late operation by punting handling to later" << llendl; + doAfterInterval(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,src_id,dst_id,timestamp), + mRetryAfter); + return; + } + mPendingRequests--; + F32 elapsed = timestamp.getElapsedTimeF32(); + LL_DEBUGS("Avatar") << "op done, src_id " << src_id << " dst_id " << dst_id << " after " << elapsed << " seconds" << llendl; + if (mWaitTimes.find(src_id) == mWaitTimes.end()) + { + // No longer waiting for this item - either serviced + // already or gave up after too many retries. + llwarns << "duplicate or late operation, src_id " << src_id << "dst_id " << dst_id + << " elapsed " << elapsed << " after end " << (S32) mCompletionOrFailureCalled << llendl; + } + mTimeStats.push(elapsed); + mWaitTimes.erase(src_id); + if (mWaitTimes.empty() && !mCompletionOrFailureCalled) + { + onCompletionOrFailure(); + } } -protected: - ~LLWearInventoryCategoryCallback() + void onCompletionOrFailure() { - LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL; + assert (!mCompletionOrFailureCalled); + mCompletionOrFailureCalled = true; - selfStopPhase("wear_inventory_category_callback"); - - // Is the destructor called by ordinary dereference, or because the app's shutting down? - // If the inventory callback manager goes away, we're shutting down, no longer want the callback. - if( LLInventoryCallbackManager::is_instantiated() ) + // Will never call onCompletion() if any item has been flagged as + // a failure - otherwise could wind up with corrupted + // outfit, involuntary nudity, etc. + reportStats(); + if (!mTrackingPhase.empty()) { - LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend); + selfStopPhase(mTrackingPhase); + } + if (!mFailCount) + { + onCompletion(); } else { - llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; + onFailure(); } } -private: - LLUUID mCatID; - bool mAppend; -}; + void onFailure() + { + llinfos << "failed" << llendl; + mOnFailureFunc(); + } + void onCompletion() + { + llinfos << "done" << llendl; + mOnCompletionFunc(); + } + + // virtual + // Will be deleted after returning true - only safe to do this if all callbacks have fired. + BOOL tick() + { + // mPendingRequests will be zero if all requests have been + // responded to. mWaitTimes.empty() will be true if we have + // received at least one reply for each UUID. If requests + // have been dropped and retried, these will not necessarily + // be the same. Only safe to return true if all requests have + // been serviced, since it will result in this object being + // deleted. + bool all_done = (mPendingRequests==0); -//Inventory callback updating "dirty" state when destroyed -class LLUpdateDirtyState: public LLInventoryCallback + if (!mWaitTimes.empty()) + { + llwarns << "still waiting on " << mWaitTimes.size() << " items" << llendl; + for (std::map<LLUUID,LLTimer>::iterator it = mWaitTimes.begin(); + it != mWaitTimes.end();) + { + // Use a copy of iterator because it may be erased/invalidated. + std::map<LLUUID,LLTimer>::iterator curr_it = it; + ++it; + + F32 time_waited = curr_it->second.getElapsedTimeF32(); + S32 retries = mRetryCounts[curr_it->first]; + if (time_waited > mRetryAfter) + { + if (retries < mMaxRetries) + { + LL_DEBUGS("Avatar") << "Waited " << time_waited << + " for " << curr_it->first << ", retrying" << llendl; + mRetryCount++; + addItem(curr_it->first); + } + else + { + llwarns << "Giving up on " << curr_it->first << " after too many retries" << llendl; + mWaitTimes.erase(curr_it); + mFailCount++; + } + } + if (mWaitTimes.empty()) + { + onCompletionOrFailure(); + } + + } + } + return all_done; + } + + void reportStats() + { + LL_DEBUGS("Avatar") << "Phase: " << mTrackingPhase << llendl; + LL_DEBUGS("Avatar") << "mFailCount: " << mFailCount << llendl; + LL_DEBUGS("Avatar") << "mRetryCount: " << mRetryCount << llendl; + LL_DEBUGS("Avatar") << "Times: n " << mTimeStats.getCount() << " min " << mTimeStats.getMinValue() << " max " << mTimeStats.getMaxValue() << llendl; + LL_DEBUGS("Avatar") << "Mean " << mTimeStats.getMean() << " stddev " << mTimeStats.getStdDev() << llendl; + } + + virtual ~LLCallAfterInventoryBatchMgr() + { + LL_DEBUGS("Avatar") << "deleting" << llendl; + } + +protected: + std::string mTrackingPhase; + std::map<LLUUID,LLTimer> mWaitTimes; + std::map<LLUUID,S32> mRetryCounts; + LLUUID mDstCatID; + nullary_func_t mOnCompletionFunc; + nullary_func_t mOnFailureFunc; + F32 mRetryAfter; + S32 mMaxRetries; + S32 mPendingRequests; + S32 mFailCount; + S32 mRetryCount; + bool mCompletionOrFailureCalled; + LLViewerStats::StatsAccumulator mTimeStats; +}; + +class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr { public: - LLUpdateDirtyState() {} - virtual ~LLUpdateDirtyState() + LLCallAfterInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, + const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func, + nullary_func_t on_failure_func = no_op, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, + S32 max_retries = DEFAULT_MAX_RETRIES + ): + LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) + { + addItems(src_items); + } + + virtual bool requestOperation(const LLUUID& item_id) { - if (LLAppearanceMgr::instanceExists()) + LLViewerInventoryItem *item = gInventory.getItem(item_id); + llassert(item); + LL_DEBUGS("Avatar") << "copying item " << item_id << llendl; + if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) { - LLAppearanceMgr::getInstance()->updateIsDirty(); + LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; + return true; } + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + mDstCatID, + std::string(), + new LLBoostFuncInventoryCallback(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer())) + ); + return true; } - virtual void fire(const LLUUID&) {} }; +class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr +{ +public: + LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, + const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func, + nullary_func_t on_failure_func = no_op, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, + S32 max_retries = DEFAULT_MAX_RETRIES + ): + LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) + { + addItems(src_items); + } + + virtual bool requestOperation(const LLUUID& item_id) + { + bool request_sent = false; + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + if (item->getParentUUID() == mDstCatID) + { + LL_DEBUGS("Avatar") << "item " << item_id << " name " << item->getName() << " is already a child of " << mDstCatID << llendl; + return false; + } + LL_DEBUGS("Avatar") << "linking item " << item_id << " name " << item->getName() << " to " << mDstCatID << llendl; + // create an inventory item link. + if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) + { + LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; + return true; + } + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + mDstCatID, + item->getName(), + item->getActualDescription(), + LLAssetType::AT_LINK, + new LLBoostFuncInventoryCallback( + boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); + return true; + } + else + { + // create a base outfit link if appropriate. + LLViewerInventoryCategory *catp = gInventory.getCategory(item_id); + if (!catp) + { + llwarns << "link request failed, id not found as inventory item or category " << item_id << llendl; + return false; + } + const LLUUID cof = LLAppearanceMgr::instance().getCOF(); + std::string new_outfit_name = ""; + + LLAppearanceMgr::instance().purgeBaseOutfitLink(cof); + + if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) + { + LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; + return true; + } + LL_DEBUGS("Avatar") << "linking folder " << item_id << " name " << catp->getName() << " to cof " << cof << llendl; + link_inventory_item(gAgent.getID(), item_id, cof, catp->getName(), "", + LLAssetType::AT_LINK_FOLDER, + new LLBoostFuncInventoryCallback( + boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); + new_outfit_name = catp->getName(); + request_sent = true; + } + + LLAppearanceMgr::instance().updatePanelOutfitName(new_outfit_name); + } + return request_sent; + } +}; LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering): mFireCount(0), @@ -278,7 +557,7 @@ struct LLFoundData std::string mName; LLAssetType::EType mAssetType; LLWearableType::EType mWearableType; - LLWearable* mWearable; + LLViewerWearable* mWearable; bool mIsReplacement; }; @@ -302,7 +581,7 @@ public: void recoverMissingWearable(LLWearableType::EType type); void clearCOFLinksForMissingWearables(); - void onWearableAssetFetch(LLWearable *wearable); + void onWearableAssetFetch(LLViewerWearable *wearable); void onAllComplete(); typedef std::list<LLFoundData> found_list_t; @@ -328,7 +607,7 @@ private: typedef std::set<LLWearableHoldingPattern*> type_set_hp; static type_set_hp sActiveHoldingPatterns; bool mIsMostRecent; - std::set<LLWearable*> mLateArrivals; + std::set<LLViewerWearable*> mLateArrivals; bool mIsAllComplete; }; @@ -559,100 +838,72 @@ bool LLWearableHoldingPattern::pollFetchCompletion() return done; } -class RecoveredItemLinkCB: public LLInventoryCallback +void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder) { -public: - RecoveredItemLinkCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder): - mHolder(holder), - mWearable(wearable), - mType(type) + if (!holder->isMostRecent()) { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? } - void fire(const LLUUID& item_id) - { - if (!mHolder->isMostRecent()) - { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; - // runway skip here? - } - llinfos << "Recovered item link for type " << mType << llendl; - mHolder->eraseTypeToLink(mType); - // Add wearable to FoundData for actual wearing - LLViewerInventoryItem *item = gInventory.getItem(item_id); - LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; + llinfos << "Recovered item link for type " << type << llendl; + holder->eraseTypeToLink(type); + // Add wearable to FoundData for actual wearing + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; - if (linked_item) - { - gInventory.addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); + if (linked_item) + { + gInventory.addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); - if (item) - { - LLFoundData found(linked_item->getUUID(), - linked_item->getAssetUUID(), - linked_item->getName(), - linked_item->getType(), - linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID, - true // is replacement - ); - found.mWearable = mWearable; - mHolder->getFoundList().push_front(found); - } - else - { - llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl; - } + if (item) + { + LLFoundData found(linked_item->getUUID(), + linked_item->getAssetUUID(), + linked_item->getName(), + linked_item->getType(), + linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID, + true // is replacement + ); + found.mWearable = wearable; + holder->getFoundList().push_front(found); } else { - llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl; + llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl; } } -private: - LLWearableHoldingPattern* mHolder; - LLWearable *mWearable; - LLWearableType::EType mType; -}; + else + { + llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl; + } +} -class RecoveredItemCB: public LLInventoryCallback +void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder) { -public: - RecoveredItemCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder): - mHolder(holder), - mWearable(wearable), - mType(type) + if (!holder->isMostRecent()) { + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } - void fire(const LLUUID& item_id) - { - if (!mHolder->isMostRecent()) - { - // runway skip here? - llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; - } - LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << mType << LL_ENDL; - LLViewerInventoryItem *itemp = gInventory.getItem(item_id); - mWearable->setItemID(item_id); - LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder); - mHolder->eraseTypeToRecover(mType); - llassert(itemp); - if (itemp) - { - link_inventory_item( gAgent.getID(), - item_id, - LLAppearanceMgr::instance().getCOF(), - itemp->getName(), - itemp->getDescription(), - LLAssetType::AT_LINK, - cb); - } + LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL; + LLViewerInventoryItem *itemp = gInventory.getItem(item_id); + wearable->setItemID(item_id); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_link_cb,_1,type,wearable,holder)); + holder->eraseTypeToRecover(type); + llassert(itemp); + if (itemp) + { + link_inventory_item( gAgent.getID(), + item_id, + LLAppearanceMgr::instance().getCOF(), + itemp->getName(), + itemp->getDescription(), + LLAssetType::AT_LINK, + cb); } -private: - LLWearableHoldingPattern* mHolder; - LLWearable *mWearable; - LLWearableType::EType mType; -}; +} void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type) { @@ -666,11 +917,11 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); // Add a new one in the lost and found folder. const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - LLPointer<LLInventoryCallback> cb = new RecoveredItemCB(type,wearable,this); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_cb,_1,type,wearable,this)); create_inventory_item(gAgent.getID(), gAgent.getSessionID(), @@ -699,7 +950,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() { // Wearable link that was never resolved; remove links to it from COF LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; - LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false); + LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); } } } @@ -773,11 +1024,11 @@ void LLWearableHoldingPattern::handleLateArrivals() iter != getFoundList().end(); ++iter) { LLFoundData& data = *iter; - for (std::set<LLWearable*>::iterator wear_it = mLateArrivals.begin(); + for (std::set<LLViewerWearable*>::iterator wear_it = mLateArrivals.begin(); wear_it != mLateArrivals.end(); ++wear_it) { - LLWearable *wearable = *wear_it; + LLViewerWearable *wearable = *wear_it; if(wearable->getAssetID() == data.mAssetID) { @@ -813,7 +1064,7 @@ void LLWearableHoldingPattern::handleLateArrivals() if (data.mWearable && data.mIsReplacement && replaced_types.find(data.mWearableType) != replaced_types.end()) { - LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false); + LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); std::list<LLFoundData>::iterator clobber_ator = iter; ++iter; getFoundList().erase(clobber_ator); @@ -837,7 +1088,7 @@ void LLWearableHoldingPattern::resetTime(F32 timeout) mWaitTime.setTimerExpirySec(timeout); } -void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) +void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable) { if (!isMostRecent()) { @@ -888,7 +1139,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) } } -static void onWearableAssetFetch(LLWearable* wearable, void* data) +static void onWearableAssetFetch(LLViewerWearable* wearable, void* data) { LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data; holder->onWearableAssetFetch(wearable); @@ -927,6 +1178,18 @@ const LLUUID LLAppearanceMgr::getCOF() const return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); } +S32 LLAppearanceMgr::getCOFVersion() const +{ + LLViewerInventoryCategory *cof = gInventory.getCategory(getCOF()); + if (cof) + { + return cof->getVersion(); + } + else + { + return LLViewerInventoryCategory::VERSION_UNKNOWN; + } +} const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() { @@ -995,6 +1258,18 @@ const LLUUID LLAppearanceMgr::getBaseOutfitUUID() return outfit_cat->getUUID(); } +void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false) +{ + if (inv_item.isNull()) + return; + + LLViewerInventoryItem *item = gInventory.getItem(inv_item); + if (item) + { + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item, true, do_replace); + } +} + bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer<LLInventoryCallback> cb) { if (item_id_to_wear.isNull()) return false; @@ -1014,8 +1289,8 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(replace); - copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace)); + copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb); return false; } else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID())) @@ -1041,7 +1316,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up if ((replace && wearable_count != 0) || (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ) { - removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); + removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1)); } addCOFItemLink(item_to_wear, do_update, cb); } @@ -1051,7 +1326,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. - removeCOFLinksOfType(item_to_wear->getWearableType(), false); + removeCOFLinksOfType(item_to_wear->getWearableType()); addCOFItemLink(item_to_wear, do_update, cb); break; @@ -1149,11 +1424,13 @@ void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id) LLInventoryModel::item_array_t::const_iterator it = items.begin(); const LLInventoryModel::item_array_t::const_iterator it_end = items.end(); + uuid_vec_t uuids_to_remove; for( ; it_end != it; ++it) { LLViewerInventoryItem* item = *it; - removeItemFromAvatar(item->getUUID()); + uuids_to_remove.push_back(item->getUUID()); } + removeItemsFromAvatar(uuids_to_remove); } // Create a copy of src_id + contents as a subfolder of dst_id. @@ -1197,13 +1474,13 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL { case LLAssetType::AT_LINK: { - //LLInventoryItem::getDescription() is used for a new description + //getActualDescription() is used for a new description //to propagate ordering information saved in descriptions of links link_inventory_item(gAgent.getID(), item->getLinkedUUID(), dst_id, item->getName(), - item->LLInventoryItem::getDescription(), + item->getActualDescription(), LLAssetType::AT_LINK, cb); break; } @@ -1383,7 +1660,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) } } -void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links) +void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1396,8 +1673,19 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin continue; if (item->getIsLinkType()) { +#if 0 + if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL) + { + llinfos << "preserved item" << llendl; + } + else + { + gInventory.purgeObject(item->getUUID()); + } +#else gInventory.purgeObject(item->getUUID()); } +#endif } } @@ -1437,7 +1725,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, item->getLinkedUUID(), cat_uuid, item->getName(), - item->LLInventoryItem::getDescription(), + item->getActualDescription(), LLAssetType::AT_LINK, cb); @@ -1508,40 +1796,31 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false); removeDuplicateItems(gest_items); - // Remove current COF contents. - bool keep_outfit_links = append; - purgeCategory(cof, keep_outfit_links); - gInventory.notifyObservers(); - // Create links to new COF contents. - LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL; - LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL; -#endif - linkAll(cof, body_items, link_waiter); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL; -#endif - linkAll(cof, wear_items, link_waiter); + LLInventoryModel::item_array_t all_items; + all_items += body_items; + all_items += wear_items; + all_items += obj_items; + all_items += gest_items; -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL; -#endif - linkAll(cof, obj_items, link_waiter); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL; -#endif - linkAll(cof, gest_items, link_waiter); + // Will link all the above items. + LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; + linkAll(cof,all_items,link_waiter); // Add link to outfit if category is an outfit. if (!append) { createBaseOutfitLink(category, link_waiter); } + + // Remove current COF contents. Have to do this after creating + // the link_waiter so links can be followed for any items that get + // carried over (e.g. keeping old shape if the new outfit does not + // contain one) + bool keep_outfit_links = append; + purgeCategory(cof, keep_outfit_links, &all_items); + gInventory.notifyObservers(); + LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } @@ -1577,7 +1856,7 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo { lldebugs << "updateAgentWearables()" << llendl; LLInventoryItem::item_array_t items; - LLDynamicArray< LLWearable* > wearables; + LLDynamicArray< LLViewerWearable* > wearables; // For each wearable type, find the wearables of that type. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) @@ -1586,7 +1865,7 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo iter != holder->getFoundList().end(); ++iter) { LLFoundData& data = *iter; - LLWearable* wearable = data.mWearable; + LLViewerWearable* wearable = data.mWearable; if( wearable && ((S32)wearable->getType() == i) ) { LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID); @@ -1622,7 +1901,7 @@ static void remove_non_link_items(LLInventoryModel::item_array_t &items) } //a predicate for sorting inventory items by actual descriptions -bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* item2) +bool sort_by_actual_description(const LLInventoryItem* item1, const LLInventoryItem* item2) { if (!item1 || !item2) { @@ -1630,7 +1909,7 @@ bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* it return true; } - return item1->LLInventoryItem::getDescription() < item2->LLInventoryItem::getDescription(); + return item1->getActualDescription() < item2->getActualDescription(); } void item_array_diff(LLInventoryModel::item_array_t& full_list, @@ -1712,11 +1991,10 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) return; } - LLVOAvatar::ScopedPhaseSetter(gAgentAvatarp,"update_appearance_from_cof"); - BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); + selfStartPhase("update_appearance_from_cof"); - LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL; //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) @@ -1730,9 +2008,18 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // the saved outfit stored as a folder link updateIsDirty(); + // Send server request for appearance update + if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) + { + requestServerAppearanceUpdate(); + } + // DRANO really should wait for the appearance message to set this. + // verify that deleting this line doesn't break anything. + //gAgentAvatarp->setIsUsingServerBakes(gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()); + //dumpCat(getCOF(),"COF, start"); - bool follow_folder_links = true; + bool follow_folder_links = false; LLUUID current_outfit_id = getCOF(); // Find all the wearables that are in the COF's subtree. @@ -1820,6 +2107,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // Fetch the wearables about to be worn. LLWearableList::instance().getAsset(found.mAssetID, found.mName, + gAgentAvatarp, found.mAssetType, onWearableAssetFetch, (void*)holder); @@ -1954,22 +2242,15 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap pid, LLFolderType::FT_NONE, name); - LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(new_cat_id, append); - it = items->begin(); - for(; it < end; ++it) - { - item = *it; - if(item) - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - new_cat_id, - std::string(), - cb); - } - } + + // Create a CopyMgr that will copy items, manage its own destruction + new LLCallAfterInventoryCopyMgr( + *items, new_cat_id, std::string("wear_inventory_category_callback"), + boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, + LLAppearanceMgr::getInstance(), + gInventory.getCategory(new_cat_id), + append)); + // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); } @@ -1986,7 +2267,13 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego // Avoid unintentionally overwriting old wearables. We have to do // this up front to avoid having to deal with the case of multiple // wearables being dirty. - if(!category) return; + if (!category) return; + + if ( !LLInventoryCallbackManager::is_instantiated() ) + { + // shutting down, ignore. + return; + } LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName() << "'" << LL_ENDL; @@ -2053,10 +2340,11 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer<LLInventoryCallback> cb = NULL): + LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer<LLInventoryCallback> cb = NULL, std::string description = ""): mItemID(item_id), mDoUpdate(do_update), - mCallback(cb) + mCallback(cb), + mDescription(description) { } @@ -2078,28 +2366,49 @@ public: private: const LLUUID mItemID; bool mDoUpdate; + std::string mDescription; LLPointer<LLInventoryCallback> mCallback; }; // BAP - note that this runs asynchronously if the item is not already loaded from inventory. // Dangerous if caller assumes link will exist after calling the function. -void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer<LLInventoryCallback> cb) +void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description) { const LLInventoryItem *item = gInventory.getItem(item_id); if (!item) { - LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb); + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description); gInventory.addObserver(observer); } else { - addCOFItemLink(item, do_update, cb); + addCOFItemLink(item, do_update, cb, description); + } +} + +void modified_cof_cb(const LLUUID& inv_item) +{ + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(inv_item); + + // TODO: camera mode may not be changed if a debug setting is tweaked + if( gAgentCamera.cameraCustomizeAvatar() ) + { + // If we're in appearance editing mode, the current tab may need to be refreshed + LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); + if (panel) + { + panel->showDefaultSubpart(); + } } } -void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer<LLInventoryCallback> cb) +void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description) { + std::string link_description = description; const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item); if (!vitem) { @@ -2161,37 +2470,106 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update { if(do_update && cb.isNull()) { - cb = new ModifiedCOFCallback; + cb = new LLBoostFuncInventoryCallback(modified_cof_cb); + } + if (vitem->getIsLinkType()) + { + link_description = vitem->getActualDescription(); } - const std::string description = vitem->getIsLinkType() ? vitem->getDescription() : ""; link_inventory_item( gAgent.getID(), vitem->getLinkedUUID(), getCOF(), vitem->getName(), - description, + link_description, LLAssetType::AT_LINK, cb); } return; } -// BAP remove ensemble code for 2.1? -void LLAppearanceMgr::addEnsembleLink( LLInventoryCategory* cat, bool do_update ) +LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) { -#if SUPPORT_ENSEMBLES - // BAP add check for already in COF. - LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0; - link_inventory_item( gAgent.getID(), - cat->getLinkedUUID(), - getCOF(), - cat->getName(), - cat->getDescription(), - LLAssetType::AT_LINK_FOLDER, - cb); -#endif + + LLInventoryModel::item_array_t result; + const LLViewerInventoryItem *vitem = + dynamic_cast<const LLViewerInventoryItem*>(gInventory.getItem(item_id)); + + if (vitem) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.count(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.get(i).get(); + if (inv_item->getLinkedUUID() == vitem->getLinkedUUID()) + { + result.put(item_array.get(i)); + } + } + } + return result; } -void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, bool do_update) +void LLAppearanceMgr::removeAllClothesFromAvatar() +{ + // Fetch worn clothes (i.e. the ones in COF). + LLInventoryModel::item_array_t clothing_items; + LLInventoryModel::cat_array_t dummy; + LLIsType is_clothing(LLAssetType::AT_CLOTHING); + gInventory.collectDescendentsIf(getCOF(), + dummy, + clothing_items, + LLInventoryModel::EXCLUDE_TRASH, + is_clothing, + false); + uuid_vec_t item_ids; + for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin(); + it != clothing_items.end(); ++it) + { + item_ids.push_back((*it).get()->getLinkedUUID()); + } + + // Take them off by removing from COF. + removeItemsFromAvatar(item_ids); +} + +void LLAppearanceMgr::removeAllAttachmentsFromAvatar() +{ + if (!isAgentAvatarValid()) return; + + LLAgentWearables::llvo_vec_t objects_to_remove; + + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = (*attachment_iter); + if (attached_object) + { + objects_to_remove.push_back(attached_object); + } + } + } + uuid_vec_t ids_to_remove; + for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_remove.begin(); + it != objects_to_remove.end(); + ++it) + { + ids_to_remove.push_back((*it)->getAttachmentItemID()); + } + removeItemsFromAvatar(ids_to_remove); +} + +void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id) { gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); @@ -2209,13 +2587,9 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, bool do_update) gInventory.purgeObject(item->getUUID()); } } - if (do_update) - { - LLAppearanceMgr::updateAppearanceFromCOF(); - } } -void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, bool do_update) +void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type) { LLFindWearablesOfType filter_wearables_of_type(type); LLInventoryModel::cat_array_t cats; @@ -2231,11 +2605,6 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, bool do_u gInventory.purgeObject(item->getUUID()); } } - - if (do_update) - { - updateAppearanceFromCOF(); - } } bool sort_by_linked_uuid(const LLViewerInventoryItem* item1, const LLViewerInventoryItem* item2) @@ -2303,7 +2672,7 @@ void LLAppearanceMgr::updateIsDirty() if (item1->getLinkedUUID() != item2->getLinkedUUID() || item1->getName() != item2->getName() || - item1->LLInventoryItem::getDescription() != item2->LLInventoryItem::getDescription()) + item1->getActualDescription() != item2->getActualDescription()) { mOutfitIsDirty = true; return; @@ -2372,7 +2741,7 @@ void LLAppearanceMgr::copyLibraryGestures() folder_name == COMMON_GESTURES_FOLDER || folder_name == OTHER_GESTURES_FOLDER) { - cb = new ActivateGestureCallback; + cb = new LLBoostFuncInventoryCallback(activate_gesture_cb); } LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name); @@ -2426,6 +2795,16 @@ void LLAppearanceMgr::onFirstFullyVisible() } } +// update "dirty" state - defined outside class to allow for calling +// after appearance mgr instance has been destroyed. +void appearance_mgr_update_dirty_state() +{ + if (LLAppearanceMgr::instanceExists()) + { + LLAppearanceMgr::getInstance()->updateIsDirty(); + } +} + bool LLAppearanceMgr::updateBaseOutfit() { if (isOutfitLocked()) @@ -2446,8 +2825,8 @@ bool LLAppearanceMgr::updateBaseOutfit() // in a Base Outfit we do not remove items, only links purgeCategory(base_outfit_id, false); - - LLPointer<LLInventoryCallback> dirty_state_updater = new LLUpdateDirtyState(); + LLPointer<LLInventoryCallback> dirty_state_updater = + new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); //COF contains only links so we copy to the Base Outfit only links shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater); @@ -2504,8 +2883,8 @@ struct WearablesOrderComparator return true; } - const std::string& desc1 = item1->LLInventoryItem::getDescription(); - const std::string& desc2 = item2->LLInventoryItem::getDescription(); + const std::string& desc1 = item1->getActualDescription(); + const std::string& desc2 = item2->getActualDescription(); bool item1_valid = (desc1.size() == mControlSize) && (ORDER_NUMBER_SEPARATOR == desc1[0]); bool item2_valid = (desc2.size() == mControlSize) && (ORDER_NUMBER_SEPARATOR == desc2[0]); @@ -2563,7 +2942,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (!item) continue; std::string new_order_str = build_order_string((LLWearableType::EType)type, i); - if (new_order_str == item->LLInventoryItem::getDescription()) continue; + if (new_order_str == item->getActualDescription()) continue; item->setDescription(new_order_str); item->setComplete(TRUE); @@ -2578,52 +2957,424 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (inventory_changed) gInventory.notifyObservers(); } +// This is intended for use with HTTP Clients/Responders, but is not +// specifically coupled with those classes. +class LLHTTPRetryPolicy: public LLThreadSafeRefCount +{ +public: + LLHTTPRetryPolicy() {} + virtual ~LLHTTPRetryPolicy() {} + virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0; +}; + +// Example of simplest possible policy, not necessarily recommended. +class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy +{ +public: + LLAlwaysRetryImmediatelyPolicy() {} + bool shouldRetry(U32 status, F32& seconds_to_wait) + { + seconds_to_wait = 0.0; + return true; + } +}; + +// Very general policy with geometric back-off after failures, +// up to a maximum delay, and maximum number of retries. +class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy +{ +public: + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): + mMinDelay(min_delay), + mMaxDelay(max_delay), + mBackoffFactor(backoff_factor), + mMaxRetries(max_retries), + mDelay(min_delay), + mRetryCount(0) + { + } + bool shouldRetry(U32 status, F32& seconds_to_wait) + { + seconds_to_wait = mDelay; + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + mRetryCount++; + return (mRetryCount<=mMaxRetries); + } +private: + F32 mMinDelay; // delay never less than this value + F32 mMaxDelay; // delay never exceeds this value + F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. + U32 mMaxRetries; // maximum number of times shouldRetry will return true. + F32 mDelay; // current delay. + U32 mRetryCount; // number of times shouldRetry has been called. +}; -class LLShowCreatedOutfit: public LLInventoryCallback +class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { public: - LLShowCreatedOutfit(LLUUID& folder_id, bool show_panel = true): mFolderID(folder_id), mShowPanel(show_panel) - {} + RequestAgentUpdateAppearanceResponder() + { + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); + } - virtual ~LLShowCreatedOutfit() + virtual ~RequestAgentUpdateAppearanceResponder() { - if (!LLApp::isRunning()) + } + + // Successful completion. + /* virtual */ void result(const LLSD& content) + { + LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + if (content["success"].asBoolean()) { - llwarns << "called during shutdown, skipping" << llendl; - return; + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); + } } + else + { + onFailure(200); + } + } - LLSD key; + // Error + /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + { + llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); + debugCOF(content); - //EXT-7727. For new accounts LLShowCreatedOutfit is created during login process - // add may be processed after login process is finished - if (mShowPanel) + } + onFailure(status); + } + + void onFailure(U32 status) + { + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(status,seconds_to_wait)) + { + llinfos << "retrying" << llendl; + doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, + LLAppearanceMgr::getInstance(), + LLCurl::ResponderPtr(this)), + seconds_to_wait); + } + else + { + llwarns << "giving up after too many retries" << llendl; + } + } + + void dumpContents(const std::string outprefix, const LLSD& content) + { + std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + std::ofstream ofs(fullpath.c_str(), std::ios_base::out); + ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY); + LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL; + } + + void debugCOF(const LLSD& content) + { + LL_DEBUGS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl; + std::set<LLUUID> ais_items, local_items; + const LLSD& cof_raw = content["cof_raw"]; + for (LLSD::array_const_iterator it = cof_raw.beginArray(); + it != cof_raw.endArray(); ++it) + { + const LLSD& item = *it; + if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF()) + { + ais_items.insert(item["item_id"].asUUID()); + if (item["type"].asInteger() == 24) // link + { + LL_DEBUGS("Avatar") << "Link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << llendl; + } + else if (item["type"].asInteger() == 25) // folder link + { + LL_DEBUGS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << llendl; + + } + else + { + LL_DEBUGS("Avatar") << "Other: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << llendl; + } + } + } + LL_DEBUGS("Avatar") << llendl; + LL_DEBUGS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl; + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.count(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.get(i).get(); + local_items.insert(inv_item->getUUID()); + LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << llendl; + } + LL_DEBUGS("Avatar") << llendl; + for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it) + { + if (ais_items.find(*it) == ais_items.end()) + { + LL_DEBUGS("Avatar") << "LOCAL ONLY: " << *it << llendl; + } + } + for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it) { - LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key); + if (local_items.find(*it) == local_items.end()) + { + LL_DEBUGS("Avatar") << "AIS ONLY: " << *it << llendl; + } + } + } + + LLPointer<LLHTTPRetryPolicy> mRetryPolicy; +}; +LLSD LLAppearanceMgr::dumpCOF() const +{ + LLSD links = LLSD::emptyArray(); + LLMD5 md5; + + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(getCOF(),cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.count(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.get(i).get(); + LLSD item; + LLUUID item_id(inv_item->getUUID()); + md5.update((unsigned char*)item_id.mData, 16); + item["description"] = inv_item->getActualDescription(); + md5.update(inv_item->getActualDescription()); + item["asset_type"] = inv_item->getActualType(); + LLUUID linked_id(inv_item->getLinkedUUID()); + item["linked_id"] = linked_id; + md5.update((unsigned char*)linked_id.mData, 16); + + if (LLAssetType::AT_LINK == inv_item->getActualType()) + { + const LLViewerInventoryItem* linked_item = inv_item->getLinkedItem(); + if (NULL == linked_item) + { + llwarns << "Broken link for item '" << inv_item->getName() + << "' (" << inv_item->getUUID() + << ") during requestServerAppearanceUpdate" << llendl; + continue; + } + // Some assets may be 'hidden' and show up as null in the viewer. + //if (linked_item->getAssetUUID().isNull()) + //{ + // llwarns << "Broken link (null asset) for item '" << inv_item->getName() + // << "' (" << inv_item->getUUID() + // << ") during requestServerAppearanceUpdate" << llendl; + // continue; + //} + LLUUID linked_asset_id(linked_item->getAssetUUID()); + md5.update((unsigned char*)linked_asset_id.mData, 16); + U32 flags = linked_item->getFlags(); + md5.update(boost::lexical_cast<std::string>(flags)); + } + else if (LLAssetType::AT_LINK_FOLDER != inv_item->getActualType()) + { + llwarns << "Non-link item '" << inv_item->getName() + << "' (" << inv_item->getUUID() + << ") type " << (S32) inv_item->getActualType() + << " during requestServerAppearanceUpdate" << llendl; + continue; } - LLOutfitsList *outfits_list = - dynamic_cast<LLOutfitsList*>(LLFloaterSidePanelContainer::getPanel("appearance", "outfitslist_tab")); - if (outfits_list) + links.append(item); + } + LLSD result = LLSD::emptyMap(); + result["cof_contents"] = links; + char cof_md5sum[MD5HEX_STR_SIZE]; + md5.finalize(); + md5.hex_digest(cof_md5sum); + result["cof_md5sum"] = std::string(cof_md5sum); + return result; +} + +void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr) +{ + if (gAgentAvatarp->isEditingAppearance()) + { + // don't send out appearance updates if in appearance editing mode + return; + } + + if (!gAgent.getRegion()) + { + llwarns << "Region not set, cannot request server appearance update" << llendl; + return; + } + if (gAgent.getRegion()->getCentralBakeVersion()==0) + { + llwarns << "Region does not support baking" << llendl; + } + std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); + if (url.empty()) + { + llwarns << "No cap for UpdateAvatarAppearance." << llendl; + return; + } + + LLSD body; + S32 cof_version = getCOFVersion(); + if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate")) + { + body = dumpCOF(); + } + else + { + body["cof_version"] = cof_version; + if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure")) { - outfits_list->setSelectedOutfitByUUID(mFolderID); + body["cof_version"] = cof_version+999; } + } + LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl; + + //LLCurl::ResponderPtr responder_ptr; + if (!responder_ptr.get()) + { + responder_ptr = new RequestAgentUpdateAppearanceResponder; + } + LLHTTPClient::post(url, body, responder_ptr); + llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion); + gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version; +} - LLAppearanceMgr::getInstance()->updateIsDirty(); - gAgentWearables.notifyLoadingFinished(); // New outfit is saved. - LLAppearanceMgr::getInstance()->updatePanelOutfitName(""); +class LLIncrementCofVersionResponder : public LLHTTPClient::Responder +{ +public: + LLIncrementCofVersionResponder() : LLHTTPClient::Responder() + { + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 16.0, 2.0, 5); + } + + virtual ~LLIncrementCofVersionResponder() + { } - virtual void fire(const LLUUID&) - {} + virtual void result(const LLSD &pContent) + { + llinfos << "Successfully incremented agent's COF." << llendl; + S32 new_version = pContent["category"]["version"].asInteger(); -private: - LLUUID mFolderID; - bool mShowPanel; + // cof_version should have increased + llassert(new_version > gAgentAvatarp->mLastUpdateRequestCOFVersion); + + gAgentAvatarp->mLastUpdateRequestCOFVersion = new_version; + } + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content) + { + llwarns << "While attempting to increment the agent's cof we got an error with [status:" + << pStatus << "]: " << content << llendl; + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait)) + { + llinfos << "retrying" << llendl; + doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, + LLAppearanceMgr::getInstance(), + LLHTTPClient::ResponderPtr(this)), + seconds_to_wait); + } + else + { + llwarns << "giving up after too many retries" << llendl; + } + } + + LLPointer<LLHTTPRetryPolicy> mRetryPolicy; }; +void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr) +{ + // If we don't have a region, report it as an error + if (gAgent.getRegion() == NULL) + { + llwarns << "Region not set, cannot request cof_version increment" << llendl; + return; + } + + std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion"); + if (url.empty()) + { + llwarns << "No cap for IncrementCofVersion." << llendl; + return; + } + + llinfos << "Requesting cof_version be incremented via capability to: " + << url << llendl; + LLSD headers; + LLSD body = LLSD::emptyMap(); + + if (!responder_ptr.get()) + { + responder_ptr = LLHTTPClient::ResponderPtr(new LLIncrementCofVersionResponder()); + } + + LLHTTPClient::get(url, body, responder_ptr, headers, 30.0f); +} + +std::string LLAppearanceMgr::getAppearanceServiceURL() const +{ + if (gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride").empty()) + { + return mAppearanceServiceURL; + } + return gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride"); +} + +void show_created_outfit(LLUUID& folder_id, bool show_panel = true) +{ + if (!LLApp::isRunning()) + { + llwarns << "called during shutdown, skipping" << llendl; + return; + } + + LLSD key; + + //EXT-7727. For new accounts inventory callback is created during login process + // and may be processed after login process is finished + if (show_panel) + { + LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key); + + } + LLOutfitsList *outfits_list = + dynamic_cast<LLOutfitsList*>(LLFloaterSidePanelContainer::getPanel("appearance", "outfitslist_tab")); + if (outfits_list) + { + outfits_list->setSelectedOutfitByUUID(folder_id); + } + + LLAppearanceMgr::getInstance()->updateIsDirty(); + gAgentWearables.notifyLoadingFinished(); // New outfit is saved. + LLAppearanceMgr::getInstance()->updatePanelOutfitName(""); +} + LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel) { if (!isAgentAvatarValid()) return LLUUID::null; @@ -2639,7 +3390,8 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, b updateClothingOrderingInfo(); - LLPointer<LLInventoryCallback> cb = new LLShowCreatedOutfit(folder_id,show_panel); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func, + boost::bind(show_created_outfit,folder_id,show_panel)); shallowCopyCategoryContents(getCOF(),folder_id, cb); createBaseOutfitLink(folder_id, cb); @@ -2656,33 +3408,26 @@ void LLAppearanceMgr::wearBaseOutfit() updateCOF(base_outfit_id); } -void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) +void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) { - LLViewerInventoryItem * item_to_remove = gInventory.getItem(id_to_remove); - if (!item_to_remove) return; - - switch (item_to_remove->getType()) + if (ids_to_remove.empty()) { - case LLAssetType::AT_CLOTHING: - if (get_is_item_worn(id_to_remove)) - { - //*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future - LLWearableBridge::removeItemFromAvatar(item_to_remove); - } - break; - case LLAssetType::AT_OBJECT: - LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID()); - default: - break; + llwarns << "called with empty list, nothing to do" << llendl; + } + for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it) + { + const LLUUID& id_to_remove = *it; + const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove); + removeCOFItemLinks(linked_item_id); } + updateAppearanceFromCOF(); +} - // *HACK: Force to remove garbage from COF. - // Unworn links or objects can't be processed by existed removing functionality - // since it is not designed for such cases. As example attachment object can't be removed - // since sever don't sends message _PREHASH_KillObject in that case. - // Also we can't check is link was successfully removed from COF since in case - // deleting attachment link removing performs asynchronously in process_kill_object callback. - removeCOFItemLinks(id_to_remove,false); +void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) +{ + LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); + removeCOFItemLinks(linked_item_id); + updateAppearanceFromCOF(); } bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) @@ -2711,8 +3456,8 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b closer_to_body ? --it : ++it; LLViewerInventoryItem* swap_item = *it; if (!swap_item) return false; - std::string tmp = swap_item->LLInventoryItem::getDescription(); - swap_item->setDescription(item->LLInventoryItem::getDescription()); + std::string tmp = swap_item->getActualDescription(); + swap_item->setDescription(item->getActualDescription()); item->setDescription(tmp); @@ -2745,7 +3490,7 @@ void LLAppearanceMgr::sortItemsByActualDescription(LLInventoryModel::item_array_ { if (items.size() < 2) return; - std::sort(items.begin(), items.end(), sort_by_description); + std::sort(items.begin(), items.end(), sort_by_actual_description); } //#define DUMP_CAT_VERBOSE @@ -2811,7 +3556,7 @@ LLAppearanceMgr::~LLAppearanceMgr() void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) { - llinfos << "setAttachmentInvLinkEnable => " << (int) val << llendl; + LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << llendl; mAttachmentInvLinkEnabled = val; } @@ -2855,7 +3600,7 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) if (mAttachmentInvLinkEnabled) { - LLAppearanceMgr::removeCOFItemLinks(item_id, false); + LLAppearanceMgr::removeCOFItemLinks(item_id); } else { @@ -2949,9 +3694,9 @@ public: } virtual void done() { - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. + // What we do here is get the complete information on the + // items in the requested category, and set up an observer + // that will wait for that to happen. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(mComplete.front(), @@ -2964,9 +3709,8 @@ public: llwarns << "Nothing fetched in category " << mComplete.front() << llendl; gInventory.removeObserver(this); + doOnIdleOneTime(mCallable); - // lets notify observers that loading is finished. - gAgentWearables.notifyLoadingFinished(); delete this; return; } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index c1d561781d..46252afbde 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -35,7 +35,6 @@ #include "llinventoryobserver.h" #include "llviewerinventory.h" -class LLWearable; class LLWearableHoldingPattern; class LLInventoryCallback; class LLOutfitUnLockTimer; @@ -93,6 +92,10 @@ public: // Find the Current Outfit folder. const LLUUID getCOF() const; + S32 getCOFVersion() const; + + // Debugging - get truncated LLSD summary of COF contents. + LLSD dumpCOF() const; // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); @@ -107,6 +110,7 @@ public: // Update the displayed outfit name in UI. void updatePanelOutfitName(const std::string& name); + void purgeBaseOutfitLink(const LLUUID& category); void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter); void updateAgentWearables(LLWearableHoldingPattern* holder, bool append); @@ -126,15 +130,17 @@ public: LLPointer<LLInventoryCallback> cb); // Add COF link to individual item. - void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL); - void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL); + void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = ""); - // Remove COF entries - void removeCOFItemLinks(const LLUUID& item_id, bool do_update = true); - void removeCOFLinksOfType(LLWearableType::EType type, bool do_update = true); + // Find COF entries referencing the given item. + LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id); - // Add COF link to ensemble folder. - void addEnsembleLink(LLInventoryCategory* item, bool do_update = true); + // Remove COF entries + void removeCOFItemLinks(const LLUUID& item_id); + void removeCOFLinksOfType(LLWearableType::EType type); + void removeAllClothesFromAvatar(); + void removeAllAttachmentsFromAvatar(); //has the current outfit changed since it was loaded? bool isOutfitDirty() { return mOutfitIsDirty; } @@ -162,6 +168,7 @@ public: bool updateBaseOutfit(); //Remove clothing or detach an object from the agent (a bodypart cannot be removed) + void removeItemsFromAvatar(const uuid_vec_t& item_ids); void removeItemFromAvatar(const LLUUID& item_id); @@ -182,6 +189,20 @@ public: bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; } + void requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr = NULL); + + void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL); + + // *HACK Remove this after server side texture baking is deployed on all sims. + void incrementCofVersionLegacy(); + + void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } + std::string getAppearanceServiceURL() const; + +private: + std::string mAppearanceServiceURL; + + protected: LLAppearanceMgr(); ~LLAppearanceMgr(); @@ -201,9 +222,7 @@ private: LLInventoryModel::item_array_t& gest_items, bool follow_folder_links); - void purgeCategory(const LLUUID& category, bool keep_outfit_links); - void purgeBaseOutfitLink(const LLUUID& category); - + void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items = NULL); static void onOutfitRename(const LLSD& notification, const LLSD& response); void setOutfitLocked(bool locked); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 53c694eaca..97962b8705 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -292,6 +292,10 @@ LLTimer gLogoutTimer; static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg. F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; + +S32 gPendingMetricsUploads = 0; + + BOOL gDisconnected = FALSE; // used to restore texture state after a mode switch @@ -682,6 +686,15 @@ LLAppViewer::~LLAppViewer() removeMarkerFile(); } +class LLUITranslationBridge : public LLTranslationBridge +{ +public: + virtual std::string getString(const std::string &xml_desc) + { + return LLTrans::getString(xml_desc); + } +}; + bool LLAppViewer::init() { // @@ -693,6 +706,10 @@ bool LLAppViewer::init() // LLFastTimer::reset(); + // initialize LLWearableType translation bridge. + // Memory will be cleaned up in ::cleanupClass() + LLWearableType::initClass(new LLUITranslationBridge()); + // initialize SSE options LLVector4a::initClass(); @@ -786,7 +803,7 @@ bool LLAppViewer::init() LLUIImageList::getInstance(), ui_audio_callback, deferred_ui_audio_callback, - &LLUI::sGLScaleFactor); + &LLUI::getScaleFactor()); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; // NOW LLUI::getLanguage() should work. gDirUtilp must know the language @@ -1690,19 +1707,7 @@ bool LLAppViewer::cleanup() gAudiop->setStreamingAudioImpl(NULL); // shut down the audio subsystem - - bool want_longname = false; - if (gAudiop->getDriverName(want_longname) == "FMOD") - { - // This hack exists because fmod likes to occasionally - // crash or hang forever when shutting down, for no - // apparent reason. - llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush; - } - else - { - gAudiop->shutdown(); - } + gAudiop->shutdown(); delete gAudiop; gAudiop = NULL; @@ -1775,6 +1780,8 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning up Objects" << llendflush; LLViewerObject::cleanupVOClasses(); + + LLAvatarAppearance::cleanupClass(); LLPostProcess::cleanupClass(); @@ -2014,6 +2021,8 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning up LLProxy." << llendl; LLProxy::cleanupClass(); + LLWearableType::cleanupClass(); + LLMainLoopRepeater::instance().stop(); //release all private memory pools. @@ -3573,6 +3582,12 @@ void LLAppViewer::requestQuit() // Try to send metrics back to the grid metricsSend(!gDisconnected); + + // Try to send last batch of avatar rez metrics. + if (!gDisconnected && isAgentAvatarValid()) + { + gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent. + } LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(gAgent.getPositionGlobal()); @@ -4365,7 +4380,6 @@ void LLAppViewer::idle() // The 5-second interval is nice for this purpose. If the object debug // bit moves or is disabled, please give this a suitable home. LLViewerAssetStatsFF::record_fps_main(gFPSClamped); - LLViewerAssetStatsFF::record_avatar_stats(); } } @@ -4681,6 +4695,13 @@ void LLAppViewer::idleShutdown() return; } + if (gPendingMetricsUploads > 0 + && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME + && !logoutRequestSent()) + { + return; + } + // All floaters are closed. Tell server we want to quit. if( !logoutRequestSent() ) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 7563d672e3..08039100b3 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -342,6 +342,8 @@ extern LLFrameTimer gLoggedInTime; extern F32 gLogoutMaxTime; extern LLTimer gLogoutTimer; +extern S32 gPendingMetricsUploads; + extern F32 gSimLastTime; extern F32 gSimFrames; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 8326be433e..82b93b52a2 100755 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -92,7 +92,7 @@ void nvapi_error(NvAPI_Status status) llwarns << szDesc << llendl; //should always trigger when asserts are enabled - llassert(status == NVAPI_OK); + //llassert(status == NVAPI_OK); } // Create app mutex creates a unique global windows object. diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp index f943759bb8..4bdb690225 100755 --- a/indra/newview/llassetuploadqueue.cpp +++ b/indra/newview/llassetuploadqueue.cpp @@ -69,10 +69,11 @@ public: delete mData; } - virtual void error(U32 statusNum, const std::string& reason) + virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - llwarns << "Error: " << reason << llendl; - LLUpdateTaskInventoryResponder::error(statusNum, reason); + llwarns << "LLAssetUploadChainResponder Error [status:" + << statusNum << "]: " << content << llendl; + LLUpdateTaskInventoryResponder::errorWithContent(statusNum, reason, content); LLAssetUploadQueue *queue = mSupplier->get(); if (queue) { diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 7b2c536f5a..2564802387 100755 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -48,8 +48,8 @@ #include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "llviewermenufile.h" +#include "llviewertexlayer.h" #include "llviewerwindow.h" -#include "lltexlayer.h" #include "lltrans.h" // library includes @@ -225,10 +225,10 @@ LLAssetUploadResponder::~LLAssetUploadResponder() } // virtual -void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) +void LLAssetUploadResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - llinfos << "LLAssetUploadResponder::error " << statusNum - << " reason: " << reason << llendl; + llinfos << "LLAssetUploadResponder::error [status:" + << statusNum << "]: " << content << llendl; LLSD args; switch(statusNum) { @@ -340,9 +340,9 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( } // virtual -void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reason) +void LLNewAgentInventoryResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - LLAssetUploadResponder::error(statusNum, reason); + LLAssetUploadResponder::errorWithContent(statusNum, reason, content); //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); } @@ -456,7 +456,7 @@ LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, LLSendTexLayerResponder::~LLSendTexLayerResponder() { - // mBakedUploadData is normally deleted by calls to LLTexLayerSetBuffer::onTextureUploadComplete() below + // mBakedUploadData is normally deleted by calls to LLViewerTexLayerSetBuffer::onTextureUploadComplete() below if (mBakedUploadData) { // ...but delete it in the case where uploadComplete() is never called delete mBakedUploadData; @@ -477,22 +477,23 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) if (result == "complete" && mBakedUploadData != NULL) { // Invoke - LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } else { // Invoke the original callback with an error result - LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } } -void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason) +void LLSendTexLayerResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - llinfos << "status: " << statusNum << " reason: " << reason << llendl; + llinfos << "LLSendTexLayerResponder error [status:" + << statusNum << "]: " << content << llendl; // Invoke the original callback with an error result - LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 381b919c4a..a6d1016136 100755 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -42,7 +42,7 @@ public: LLAssetType::EType asset_type); ~LLAssetUploadResponder(); - virtual void error(U32 statusNum, const std::string& reason); + virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); virtual void result(const LLSD& content); virtual void uploadUpload(const LLSD& content); virtual void uploadComplete(const LLSD& content); @@ -67,7 +67,7 @@ public: const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type); - virtual void error(U32 statusNum, const std::string& reason); + virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); virtual void uploadComplete(const LLSD& content); virtual void uploadFailure(const LLSD& content); }; @@ -122,7 +122,7 @@ public: ~LLSendTexLayerResponder(); virtual void uploadComplete(const LLSD& content); - virtual void error(U32 statusNum, const std::string& reason); + virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); LLBakedUploadData * mBakedUploadData; }; diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 714bde6f37..f34ad23769 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -39,6 +39,8 @@ #include "lluictrlfactory.h" #include "llagentdata.h" #include "llfloaterimsession.h" +#include "llviewertexture.h" +#include "llavatarappearancedefines.h" // library includes #include "llavatarnamecache.h" diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index e5a9be0203..459123a5d8 100755 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -61,6 +61,10 @@ public: if ( params.size() >= 3 ) { result_code = params[ 2 ].asInteger(); + if ( result_code != 0 ) + { + LL_WARNS("LLBuyCurrency") << "Received nonzero result code: " << result_code << LL_ENDL ; + } }; // open the legacy XUI based currency floater diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp index 357a6582d1..79ec43dfe9 100755 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/newview/llcallbacklist.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llcallbacklist.h" +#include "lleventtimer.h" // Library includes #include "llerror.h" @@ -180,6 +181,54 @@ void doOnIdleRepeating(bool_func_t callable) gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor); } +class NullaryFuncEventTimer: public LLEventTimer +{ +public: + NullaryFuncEventTimer(nullary_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } + +private: + BOOL tick() + { + mCallable(); + return TRUE; + } + + nullary_func_t mCallable; +}; + +// Call a given callable once after specified interval. +void doAfterInterval(nullary_func_t callable, F32 seconds) +{ + new NullaryFuncEventTimer(callable, seconds); +} + +class BoolFuncEventTimer: public LLEventTimer +{ +public: + BoolFuncEventTimer(bool_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } +private: + BOOL tick() + { + return mCallable(); + } + + bool_func_t mCallable; +}; + +// Call a given callable every specified number of seconds, until it returns true. +void doPeriodically(bool_func_t callable, F32 seconds) +{ + new BoolFuncEventTimer(callable, seconds); +} + #ifdef _DEBUG void test1(void *data) diff --git a/indra/newview/llcallbacklist.h b/indra/newview/llcallbacklist.h index 97f3bfd9ee..0516c9cdb4 100755 --- a/indra/newview/llcallbacklist.h +++ b/indra/newview/llcallbacklist.h @@ -61,6 +61,12 @@ void doOnIdleOneTime(nullary_func_t callable); // Repeatedly call a callable in idle loop until it returns true. void doOnIdleRepeating(bool_func_t callable); +// Call a given callable once after specified interval. +void doAfterInterval(nullary_func_t callable, F32 seconds); + +// Call a given callable every specified number of seconds, until it returns true. +void doPeriodically(bool_func_t callable, F32 seconds); + extern LLCallbackList gIdleCallbacks; #endif diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 30306b230f..14583e402d 100755 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -184,7 +184,8 @@ LLVector3d LLAvatarTracker::getGlobalPos() global_pos = object->getPositionGlobal(); // HACK - for making the tracker point above the avatar's head // rather than its groin - global_pos.mdV[VZ] += 0.7f * ((LLVOAvatar *)object)->mBodySize.mV[VZ]; + LLVOAvatar* av = (LLVOAvatar*)object; + global_pos.mdV[VZ] += 0.7f * (av->mBodySize.mV[VZ] + av->mAvatarOffset.mV[VZ]); mTrackingData->mGlobalPositionEstimate = global_pos; } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 53926c1fef..0f138873ac 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -408,16 +408,7 @@ public: S32 user_name_width = user_name_rect.getWidth(); S32 time_box_width = time_box->getRect().getWidth(); - if (time_box->getVisible() && user_name_width <= mMinUserNameWidth) - { - time_box->setVisible(FALSE); - - user_name_rect.mRight += time_box_width; - user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight()); - user_name->setRect(user_name_rect); - } - - if (!time_box->getVisible() && user_name_width > mMinUserNameWidth + time_box_width) + if (!time_box->getVisible() && user_name_width > mMinUserNameWidth) { user_name_rect.mRight -= time_box_width; user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight()); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 43c6b558bc..88884042d4 100755 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -430,14 +430,12 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data) { // *TODO : we either suppress this method or return a value. Right now, it servers no purpose. /* - LLUUID session_id = data["session_id"].asUUID(); - S32 unread = data["participant_unread"].asInteger(); - LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); - if (im_floater && im_floater->getVisible() && im_floater->hasFocus()) - { - unread = 0; - } + //LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); + //if (im_floater && im_floater->getVisible() && im_floater->hasFocus()) + //{ + // unread = 0; + //} */ } diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp index b4da31895f..e3cd83e174 100755 --- a/indra/newview/llclassifiedstatsresponder.cpp +++ b/indra/newview/llclassifiedstatsresponder.cpp @@ -62,8 +62,7 @@ void LLClassifiedStatsResponder::result(const LLSD& content) } /*virtual*/ -void LLClassifiedStatsResponder::error(U32 status, const std::string& reason) +void LLClassifiedStatsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llinfos << "LLClassifiedStatsResponder::error(" - << status << ": " << reason << ")" << llendl; + llinfos << "LLClassifiedStatsResponder::error [status:" << status << "]: " << content << llendl; } diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h index 3db1868cb2..06dcb62fd0 100755 --- a/indra/newview/llclassifiedstatsresponder.h +++ b/indra/newview/llclassifiedstatsresponder.h @@ -39,7 +39,7 @@ public: virtual void result(const LLSD& content); //If we get back an error (not found, etc...), handle it here - virtual void error(U32 status, const std::string& reason); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: LLUUID mClassifiedID; diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index e9c7a3fa03..e86d6930e8 100755 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -139,8 +139,7 @@ protected: { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1); - registrar.add("Attachment.Detach", boost::bind(handleMultiple, take_off, mUUIDs)); + registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); return createFromFile("menu_cof_attachment.xml"); } @@ -173,9 +172,8 @@ protected: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; LLUUID selected_id = mUUIDs.back(); - functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1); - registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs)); + registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id)); registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id)); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 5b942f283a..f1f7da5fd1 100755 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -241,8 +241,8 @@ void LLColorSwatchCtrl::draw() { if (!mFallbackImageName.empty()) { - LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, - LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, TRUE, + LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if( fallback_image->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior ); diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 4f5f9e22b6..4588424474 100755 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -161,18 +161,6 @@ BOOL LLFloaterScriptQueue::start() { std::string buffer; - LLSelectMgr *mgr = LLSelectMgr::getInstance(); - LLObjectSelectionHandle selectHandle = mgr->getSelection(); - U32 n_objects = 0; - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - n_objects = selectHandle->getObjectCount(); - } - else - { - n_objects = selectHandle->getRootObjectCount(); - } - LLStringUtil::format_map_t args; args["[START]"] = mStartString; args["[COUNT]"] = llformat ("%d", mObjectIDs.count()); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 956abcd586..b6c53e5e30 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -120,7 +120,7 @@ void LLConversationViewSession::setFlashState(bool flash_state) void LLConversationViewSession::startFlashing() { - if (mFlashStateOn && !mFlashStarted) + if (isInVisibleChain() && mFlashStateOn && !mFlashStarted) { mFlashStarted = true; mFlashTimer->startFlashing(); diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 1e03582a29..d7d9f82910 100755 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -327,6 +327,8 @@ BOOL LLDirPicker::getDir(std::string* filename) return FALSE; } +#if !LL_MESA_HEADLESS + if (mFilePicker) { GtkWindow* picker = mFilePicker->buildFilePicker(false, true, @@ -340,6 +342,8 @@ BOOL LLDirPicker::getDir(std::string* filename) return (!mFilePicker->getFirstFile().empty()); } } +#endif // !LL_MESA_HEADLESS + return FALSE; } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4b0d3b361d..bb1d263670 100755 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -511,7 +511,6 @@ F32 LLDrawable::updateXform(BOOL undamped) //scaling LLVector3 target_scale = mVObjp->getScale(); LLVector3 old_scale = mCurrentScale; - LLVector3 dest_scale = target_scale; // Damping F32 dist_squared = 0.f; @@ -1237,7 +1236,6 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) LLCamera ret = camera; LLXformMatrix* mat = mDrawable->getXform(); LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); - LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); LLVector3 delta = ret.getOrigin() - center; LLQuaternion rot = ~mat->getRotation(); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 1b0b11298c..e8d43c8631 100755 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -153,7 +153,7 @@ void LLStandardBumpmap::addstandard() gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLGLTexture::BOOST_BUMP) ; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ; LLStandardBumpmap::sStandardBumpmapCount++; @@ -1075,7 +1075,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText src_image->getHeight() != bump->getHeight())// || //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) { - src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; + src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ; src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); src_image->forceToSaveRawImage(0) ; } diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 9bc32fddbd..0adb42428d 100755 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -69,7 +69,8 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", - TRUE, LLViewerTexture::BOOST_UI, + FTT_LOCAL_FILE, + TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, format, int_format, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); @@ -78,7 +79,8 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", - TRUE, LLViewerTexture::BOOST_UI, + FTT_LOCAL_FILE, + TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, format, int_format, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); @@ -86,7 +88,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - mTexturep->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); + mTexturep->setBoostLevel(LLGLTexture::BOOST_TERRAIN); //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -170,7 +172,7 @@ void LLDrawPoolTerrain::render(S32 pass) LLVLComposition *compp = regionp->getComposition(); for (S32 i = 0; i < 4; i++) { - compp->mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); + compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 4f6eaa5a5b..5ddc15df42 100755 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -66,11 +66,11 @@ LLVector3 LLDrawPoolWater::sLightDir; LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) { - mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[0]) ; mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[1]); mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index fa42b157a7..29ad4f34d2 100755 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -107,7 +107,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum { setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); } - createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX); + createGLTexture(0, raw_image, 0, TRUE, LLGLTexture::DYNAMIC_TEX); setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mGLTexturep->setGLTextureCreated(false); } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index c51e7d1e1a..d287ae6eeb 100755 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -72,8 +72,8 @@ public: /*virtual*/ S8 getType() const ; - S32 getOriginX() { return mOrigin.mX; } - S32 getOriginY() { return mOrigin.mY; } + S32 getOriginX() const { return mOrigin.mX; } + S32 getOriginY() const { return mOrigin.mY; } S32 getSize() { return mFullWidth * mFullHeight * mComponents; } diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp index 7ed22d68f6..2669b0340f 100755 --- a/indra/newview/llestateinfomodel.cpp +++ b/indra/newview/llestateinfomodel.cpp @@ -65,12 +65,12 @@ void LLEstateInfoModel::sendEstateInfo() } } -bool LLEstateInfoModel::getUseFixedSun() const { return mFlags & REGION_FLAGS_SUN_FIXED; } -bool LLEstateInfoModel::getIsExternallyVisible() const { return mFlags & REGION_FLAGS_EXTERNALLY_VISIBLE; } -bool LLEstateInfoModel::getAllowDirectTeleport() const { return mFlags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT; } -bool LLEstateInfoModel::getDenyAnonymous() const { return mFlags & REGION_FLAGS_DENY_ANONYMOUS; } -bool LLEstateInfoModel::getDenyAgeUnverified() const { return mFlags & REGION_FLAGS_DENY_AGEUNVERIFIED; } -bool LLEstateInfoModel::getAllowVoiceChat() const { return mFlags & REGION_FLAGS_ALLOW_VOICE; } +bool LLEstateInfoModel::getUseFixedSun() const { return getFlag(REGION_FLAGS_SUN_FIXED); } +bool LLEstateInfoModel::getIsExternallyVisible() const { return getFlag(REGION_FLAGS_EXTERNALLY_VISIBLE); } +bool LLEstateInfoModel::getAllowDirectTeleport() const { return getFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT); } +bool LLEstateInfoModel::getDenyAnonymous() const { return getFlag(REGION_FLAGS_DENY_ANONYMOUS); } +bool LLEstateInfoModel::getDenyAgeUnverified() const { return getFlag(REGION_FLAGS_DENY_AGEUNVERIFIED); } +bool LLEstateInfoModel::getAllowVoiceChat() const { return getFlag(REGION_FLAGS_ALLOW_VOICE); } void LLEstateInfoModel::setUseFixedSun(bool val) { setFlag(REGION_FLAGS_SUN_FIXED, val); } void LLEstateInfoModel::setIsExternallyVisible(bool val) { setFlag(REGION_FLAGS_EXTERNALLY_VISIBLE, val); } @@ -122,9 +122,9 @@ public: } // if we get an error response - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Failed to commit estate info (" << status << "): " << reason << llendl; + llwarns << "Failed to commit estate info [status:" << status << "]: " << content << llendl; } }; @@ -199,18 +199,6 @@ void LLEstateInfoModel::commitEstateInfoDataserver() gAgent.sendMessage(); } -void LLEstateInfoModel::setFlag(U32 flag, bool val) -{ - if (val) - { - mFlags |= flag; - } - else - { - mFlags &= ~flag; - } -} - std::string LLEstateInfoModel::getInfoDump() { LLSD dump; diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h index 56391eda91..538f2f7c75 100755 --- a/indra/newview/llestateinfomodel.h +++ b/indra/newview/llestateinfomodel.h @@ -85,19 +85,38 @@ protected: private: bool commitEstateInfoCaps(); void commitEstateInfoDataserver(); - U32 getFlags() const { return mFlags; } - void setFlag(U32 flag, bool val); + inline bool getFlag(U64 flag) const; + inline void setFlag(U64 flag, bool val); + U64 getFlags() const { return mFlags; } std::string getInfoDump(); // estate info std::string mName; /// estate name LLUUID mOwnerID; /// estate owner id U32 mID; /// estate id - U32 mFlags; /// estate flags + U64 mFlags; /// estate flags F32 mSunHour; /// estate sun hour update_signal_t mUpdateSignal; /// emitted when we receive update from sim update_signal_t mCommitSignal; /// emitted when our update gets applied to sim }; +inline bool LLEstateInfoModel::getFlag(U64 flag) const +{ + return ((mFlags & flag) != 0); +} + +inline void LLEstateInfoModel::setFlag(U64 flag, bool val) +{ + if (val) + { + mFlags |= flag; + } + else + { + mFlags &= ~flag; + } +} + + #endif // LL_LLESTATEINFOMODEL_H diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 2c786b7f8b..e0f7223a8c 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -62,7 +62,7 @@ namespace void handleMessage(const LLSD& content); - virtual void error(U32 status, const std::string& reason); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); virtual void result(const LLSD& content); virtual void completedRaw(U32 status, @@ -187,7 +187,7 @@ namespace } //virtual - void LLEventPollResponder::error(U32 status, const std::string& reason) + void LLEventPollResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { if (mDone) return; @@ -207,13 +207,13 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llwarns << "Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; + llwarns << "LLEventPollResponder error [status:" << status << "]: " << content << llendl; } else { - llwarns << "LLEventPollResponder::error: <" << mCount << "> got " - << status << ": " << reason - << (mDone ? " -- done" : "") << llendl; + llwarns << "LLEventPollResponder error <" << mCount + << "> [status:" << status << "]: " << content + << (mDone ? " -- done" : "") << llendl; stop(); // At this point we have given up and the viewer will not receive HTTP messages from the simulator. diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 28e4b32793..281f852b0a 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -555,8 +555,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) /* removed in lieu of raycast uv detection void LLFace::renderSelectedUV() { - LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLViewerTexture::BOOST_UI); - LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLViewerTexture::BOOST_UI); + LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLGLTexture::BOOST_UI); + LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLGLTexture::BOOST_UI); LLGLSUVSelect object_select; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 4dfb93f1bc..fbf72b1a85 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -368,7 +368,7 @@ void LLFastTimerView::draw() S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; - S32 texth, textw; + S32 texth; LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("Rounded_Square"); // Draw the window background @@ -399,7 +399,6 @@ void LLFastTimerView::draw() tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - textw = LLFontGL::getFontMonospace()->getWidth(tdesc); x = xleft, y -= (texth + 2); tdesc = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]); @@ -526,8 +525,6 @@ void LLFastTimerView::draw() y -= (texth + 2); - textw = dx + LLFontGL::getFontMonospace()->getWidth(idp->getName()) + 40; - if (idp->getCollapsed()) { it.skipDescendants(); @@ -1073,7 +1070,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t { //read base log into memory S32 i = 0; std::ifstream is(base.c_str()); - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is)) { base_data[i++] = cur; } @@ -1086,7 +1083,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t { //read current log into memory S32 i = 0; std::ifstream is(target.c_str()); - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is)) { cur_data[i++] = cur; @@ -1377,7 +1374,7 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is) stats_map_t time_stats; stats_map_t sample_stats; - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is)) { for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) { diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index e30dd51acb..6d90667194 100755 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1649,7 +1649,6 @@ void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array gInventory.notifyObservers(); } - // See also LLInventorySort where landmarks in the Favorites folder are sorted. class LLViewerInventoryItemSort { diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index e000adc4aa..f06e9b9b64 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -161,7 +161,7 @@ private: boost::signals2::connection mEndDragConnection; }; - +/* class AddFavoriteLandmarkCallback : public LLInventoryCallback { public: @@ -173,7 +173,7 @@ private: LLUUID mTargetLandmarkId; }; - +*/ /** * Class to store sorting order of favorites landmarks in a local file. EXT-3985. * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. @@ -272,5 +272,4 @@ private: }; }; - #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 4bf5b26b3b..d13f85baa2 100755 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -1103,6 +1103,7 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context) { +#ifndef LL_MESA_HEADLESS if (LLWindowSDL::ll_try_gtk_init()) { GtkWidget *win = NULL; @@ -1174,6 +1175,9 @@ GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::stri { return NULL; } +#else + return NULL; +#endif //LL_MESA_HEADLESS } static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter, @@ -1473,7 +1477,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename return FALSE; } -BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) +BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) { // if local file browsing is turned off, return without opening dialog // (Even though this is a stub, I think we still should not return anything at all) @@ -1494,7 +1498,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) default: break; } mFiles.push_back(filename); - llinfos << "getOpenFile: Will try to open file: " << hackyfilename << llendl; + llinfos << "getOpenFile: Will try to open file: " << filename << llendl; return TRUE; } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index a5ee4607a1..caad0afec0 100755 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -270,9 +270,6 @@ void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale) mSection[0].mVelocity.setVec(0,0,0); mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1); - LLVector3 parentSectionPosition = mSection[0].mPosition; - LLVector3 last_direction = mSection[0].mDirection; - remapSections(mSection, mInitializedRes, mSection, mSimulateRes); mInitializedRes = mSimulateRes; diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 2939d31087..3c40e2d4bc 100755 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -38,6 +38,7 @@ #include "message.h" #include "llagent.h" +#include "llassetstorage.h" #include "llcombobox.h" #include "llestateinfomodel.h" #include "llmimetypes.h" diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index f7dd4a4a6b..113aa9a8f2 100755 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -483,8 +483,7 @@ public: } else { - llinfos << "avatar picker failed " << status - << " reason " << reason << llendl; + llwarns << "avatar picker failed [status:" << status << "]: " << content << llendl; } } @@ -819,7 +818,14 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled() uuid_vec_t avatar_ids; std::vector<LLAvatarName> avatar_names; getSelectedAvatarData(list, avatar_ids, avatar_names); - return mOkButtonValidateSignal(avatar_ids); + if (avatar_ids.size() >= 1) + { + ret_val = mOkButtonValidateSignal(avatar_ids); + } + else + { + ret_val = false; + } } } diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 4e10b4fc2c..048837acfe 100755 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -32,12 +32,13 @@ #include "llagent.h" #include "llagentwearables.h" +#include "llviewerwearable.h" #include "lltexturectrl.h" #include "lluictrlfactory.h" #include "llviewerobjectlist.h" #include "llvoavatarself.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLSD& id) : LLFloater(id), @@ -53,7 +54,7 @@ BOOL LLFloaterAvatarTextures::postBuild() { for (U32 i=0; i < TEX_NUM_INDICES; i++) { - const std::string tex_name = LLVOAvatarDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; + const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; mTextures[i] = getChild<LLTextureCtrl>(tex_name); } mTitle = getTitle(); @@ -75,13 +76,13 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, ETextureIndex te) { LLUUID id = IMG_DEFAULT_AVATAR; - const LLVOAvatarDictionary::TextureEntry* tex_entry = LLVOAvatarDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); if (tex_entry->mIsLocalTexture) { if (avatarp->isSelf()) { const LLWearableType::EType wearable_type = tex_entry->mWearableType; - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(te); @@ -163,17 +164,17 @@ void LLFloaterAvatarTextures::onClickDump(void* data) const LLTextureEntry* te = avatarp->getTE(i); if (!te) continue; - const LLVOAvatarDictionary::TextureEntry* tex_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)(i)); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)(i)); if (!tex_entry) continue; if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) { LLUUID id = IMG_DEFAULT_AVATAR; - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType((ETextureIndex)i); if (avatarp->isSelf()) { - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(i); diff --git a/indra/newview/llfloateravatartextures.h b/indra/newview/llfloateravatartextures.h index 85ff545855..02474a10e1 100755 --- a/indra/newview/llfloateravatartextures.h +++ b/indra/newview/llfloateravatartextures.h @@ -30,7 +30,7 @@ #include "llfloater.h" #include "lluuid.h" #include "llstring.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLTextureCtrl; @@ -51,7 +51,7 @@ private: private: LLUUID mID; std::string mTitle; - LLTextureCtrl* mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; + LLTextureCtrl* mTextures[LLAvatarAppearanceDefines::TEX_NUM_INDICES]; }; #endif diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index fffd724b22..aa6ace2a61 100755 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -40,6 +40,7 @@ #include "llcheckboxctrl.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" // for gInventory #include "llfirstuse.h" #include "llfloaterreg.h" diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 8223e89b64..42857b2aa2 100755 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -538,7 +538,7 @@ void LLFloaterBuyLandUI::updateCovenantInfo() LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause"); if (resellable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) { resellable_clause->setText(getString("can_not_resell")); } @@ -551,7 +551,7 @@ void LLFloaterBuyLandUI::updateCovenantInfo() LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause"); if (changeable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) { changeable_clause->setText(getString("can_change")); } diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 62848586cd..f2deb6a805 100755 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1102,12 +1102,12 @@ BOOL LLPreviewAnimation::render() gGL.flush(); - LLVector3 target_pos = avatarp->mRoot.getWorldPosition(); + LLVector3 target_pos = avatarp->mRoot->getWorldPosition(); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * LLQuaternion(mCameraYaw, LLVector3::z_axis); - LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot; + LLQuaternion av_rot = avatarp->mRoot->getWorldRotation() * camera_rot; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera LLVector3::z_axis, // up diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 38abdcc830..fe6223fbf5 100755 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -164,9 +164,9 @@ LLFloaterGodTools::~LLFloaterGodTools() } -U32 LLFloaterGodTools::computeRegionFlags() const +U64 LLFloaterGodTools::computeRegionFlags() const { - U32 flags = gAgent.getRegion()->getRegionFlags(); + U64 flags = gAgent.getRegion()->getRegionFlags(); if (mPanelRegionTools) flags = mPanelRegionTools->computeRegionFlags(flags); if (mPanelObjectTools) flags = mPanelObjectTools->computeRegionFlags(flags); return flags; @@ -210,7 +210,7 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) if (!msg) return; //const S32 SIM_NAME_BUF = 256; - U32 region_flags; + U64 region_flags; U8 sim_access; U8 agent_limit; std::string sim_name; @@ -231,13 +231,23 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id); - msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, region_flags); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess, sim_access); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents, agent_limit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); + if (msg->has(_PREHASH_RegionInfo3)) + { + msg->getU64Fast(_PREHASH_RegionInfo3, _PREHASH_RegionFlagsExtended, region_flags); + } + else + { + U32 flags = 0; + msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); + region_flags = flags; + } + if (host != gAgent.getRegionHost()) { // Update is for a different region than the one we're in. @@ -341,6 +351,7 @@ void LLFloaterGodTools::sendGodUpdateRegionInfo() LLMessageSystem *msg = gMessageSystem; LLPanelRegionTools *rtool = god_tools->mPanelRegionTools; + U64 region_flags = computeRegionFlags(); msg->newMessage("GodUpdateRegionInfo"); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -349,11 +360,14 @@ void LLFloaterGodTools::sendGodUpdateRegionInfo() msg->addStringFast(_PREHASH_SimName, rtool->getSimName()); msg->addU32Fast(_PREHASH_EstateID, rtool->getEstateID()); msg->addU32Fast(_PREHASH_ParentEstateID, rtool->getParentEstateID()); - msg->addU32Fast(_PREHASH_RegionFlags, computeRegionFlags()); + // Legacy flags + msg->addU32Fast(_PREHASH_RegionFlags, U32(region_flags)); msg->addF32Fast(_PREHASH_BillableFactor, rtool->getBillableFactor()); msg->addS32Fast(_PREHASH_PricePerMeter, rtool->getPricePerMeter()); msg->addS32Fast(_PREHASH_RedirectGridX, rtool->getRedirectGridX()); msg->addS32Fast(_PREHASH_RedirectGridY, rtool->getRedirectGridY()); + msg->nextBlockFast(_PREHASH_RegionInfo2); + msg->addU64Fast(_PREHASH_RegionFlagsExtended, region_flags); gAgent.sendReliableMessage(); } @@ -434,7 +448,7 @@ LLPanelRegionTools::~LLPanelRegionTools() // base class will take care of everything } -U32 LLPanelRegionTools::computeRegionFlags(U32 flags) const +U64 LLPanelRegionTools::computeRegionFlags(U64 flags) const { flags &= getRegionFlagsMask(); flags |= getRegionFlags(); @@ -562,9 +576,9 @@ S32 LLPanelRegionTools::getGridPosY() const return getChild<LLUICtrl>("gridposy")->getValue().asInteger(); } -U32 LLPanelRegionTools::getRegionFlags() const +U64 LLPanelRegionTools::getRegionFlags() const { - U32 flags = 0x0; + U64 flags = 0x0; flags = getChild<LLUICtrl>("check prelude")->getValue().asBoolean() ? set_prelude_flags(flags) : unset_prelude_flags(flags); @@ -601,9 +615,9 @@ U32 LLPanelRegionTools::getRegionFlags() const return flags; } -U32 LLPanelRegionTools::getRegionFlagsMask() const +U64 LLPanelRegionTools::getRegionFlagsMask() const { - U32 flags = 0xffffffff; + U64 flags = 0xFFFFFFFFFFFFFFFFULL; flags = getChild<LLUICtrl>("check prelude")->getValue().asBoolean() ? set_prelude_flags(flags) : unset_prelude_flags(flags); @@ -684,7 +698,7 @@ void LLPanelRegionTools::setParentEstateID(U32 id) getChild<LLUICtrl>("parentestate")->setValue((S32)id); } -void LLPanelRegionTools::setCheckFlags(U32 flags) +void LLPanelRegionTools::setCheckFlags(U64 flags) { getChild<LLUICtrl>("check prelude")->setValue(is_prelude(flags) ? TRUE : FALSE); getChild<LLUICtrl>("check fixed sun")->setValue(flags & REGION_FLAGS_SUN_FIXED ? TRUE : FALSE); @@ -943,7 +957,7 @@ void LLPanelObjectTools::refresh() } -U32 LLPanelObjectTools::computeRegionFlags(U32 flags) const +U64 LLPanelObjectTools::computeRegionFlags(U64 flags) const { if (getChild<LLUICtrl>("disable scripts")->getValue().asBoolean()) { @@ -973,7 +987,7 @@ U32 LLPanelObjectTools::computeRegionFlags(U32 flags) const } -void LLPanelObjectTools::setCheckFlags(U32 flags) +void LLPanelObjectTools::setCheckFlags(U64 flags) { getChild<LLUICtrl>("disable scripts")->setValue(flags & REGION_FLAGS_SKIP_SCRIPTS ? TRUE : FALSE); getChild<LLUICtrl>("disable collisions")->setValue(flags & REGION_FLAGS_SKIP_COLLISIONS ? TRUE : FALSE); diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h index 1aa8b838fb..cbaeee7051 100755 --- a/indra/newview/llfloatergodtools.h +++ b/indra/newview/llfloatergodtools.h @@ -98,7 +98,7 @@ private: ~LLFloaterGodTools(); protected: - U32 computeRegionFlags() const; + U64 computeRegionFlags() const; protected: @@ -147,8 +147,8 @@ public: const std::string getSimName() const; U32 getEstateID() const; U32 getParentEstateID() const; - U32 getRegionFlags() const; - U32 getRegionFlagsMask() const; + U64 getRegionFlags() const; + U64 getRegionFlagsMask() const; F32 getBillableFactor() const; S32 getPricePerMeter() const; S32 getGridPosX() const; @@ -160,7 +160,7 @@ public: void setSimName(const std::string& name); void setEstateID(U32 id); void setParentEstateID(U32 id); - void setCheckFlags(U32 flags); + void setCheckFlags(U64 flags); void setBillableFactor(F32 billable_factor); void setPricePerMeter(S32 price); void setGridPosX(S32 pos); @@ -168,7 +168,7 @@ public: void setRedirectGridX(S32 pos); void setRedirectGridY(S32 pos); - U32 computeRegionFlags(U32 initial_flags) const; + U64 computeRegionFlags(U64 initial_flags) const; void clearAllWidgets(); void enableAllWidgets(); @@ -218,10 +218,10 @@ public: /*virtual*/ void refresh(); void setTargetAvatar(const LLUUID& target_id); - U32 computeRegionFlags(U32 initial_flags) const; + U64 computeRegionFlags(U64 initial_flags) const; void clearAllWidgets(); void enableAllWidgets(); - void setCheckFlags(U32 flags); + void setCheckFlags(U64 flags); void onChangeAnything(); void onApplyChanges(); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 2575f6f817..52e678ce24 100755 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -593,7 +593,7 @@ S8 LLImagePreviewAvatar::getType() const void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) { - mTargetJoint = mDummyAvatar->mRoot.findJoint(joint_name); + mTargetJoint = mDummyAvatar->mRoot->findJoint(joint_name); // clear out existing test mesh if (mTargetMesh) { @@ -612,9 +612,9 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const mDummyAvatar->updateVisualParams(); mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); } - mDummyAvatar->mRoot.setVisible(FALSE, TRUE); + mDummyAvatar->mRoot->setVisible(FALSE, TRUE); - mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name); + mTargetMesh = dynamic_cast<LLViewerJointMesh*>(mDummyAvatar->mRoot->findJoint(mesh_name)); mTargetMesh->setTestTexture(mTextureName); mTargetMesh->setVisible(TRUE, FALSE); mCameraDistance = distance; @@ -631,7 +631,7 @@ void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name) { if (mDummyAvatar) { - LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name); + LLViewerJointMesh *mesh = dynamic_cast<LLViewerJointMesh*>(mDummyAvatar->mRoot->findJoint(mesh_name)); // clear out existing test mesh if (mesh) { diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 7296ec3ced..58817485fb 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -585,6 +585,28 @@ void LLFloaterIMContainer::returnFloaterToHost() floater->onTearOffClicked(); } +void LLFloaterIMContainer::setMinimized(BOOL b) +{ + bool was_minimized = isMinimized(); + LLMultiFloater::setMinimized(b); + + //Switching from minimized to un-minimized + if(was_minimized && !b) + { + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); + + if(session_floater && !session_floater->isTornOff()) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && mSelectedSession.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSelectedSession); + } + } + } +} + void LLFloaterIMContainer::setVisible(BOOL visible) { LLFloaterIMNearbyChat* nearby_chat; if (visible) @@ -597,10 +619,21 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); - setSelectedSession(LLUUID(NULL)); + selectConversationPair(LLUUID(NULL), false, false); } openNearbyChat(); - selectConversationPair(getSelectedSession(), false, false); + flashConversationItemWidget(mSelectedSession,false); + + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); + if(session_floater && !session_floater->isMinimized()) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && mSelectedSession.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSelectedSession); + } + } } nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); @@ -1389,13 +1422,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool widget->getParentFolder()->setSelection(widget, FALSE, FALSE); mConversationsRoot->scrollToShowSelection(); } - - //When in DND mode, remove stored IM notifications - //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal - if(gAgent.isDoNotDisturb() && session_id.notNull()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); - } } /* floater processing */ @@ -1420,14 +1446,19 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool { showStub(true); } + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && session_id.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); + } } // Set the focus on the selected floater - if (!session_floater->hasFocus()) + if (!session_floater->hasFocus() && !session_floater->isMinimized()) { - BOOL is_minimized = session_floater->isMinimized(); session_floater->setFocus(focus_floater); - session_floater->setMinimized(is_minimized); } } flashConversationItemWidget(session_id,false); @@ -1986,8 +2017,11 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) { // Always unminimize before trying to close. // Most of the time the user will never see this state. - setMinimized(FALSE); - + if(isMinimized()) + { + LLMultiFloater::setMinimized(FALSE); + } + LLFloater::closeFloater(app_quitting); } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 52b672241f..e39d20ec35 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -59,6 +59,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void draw(); + /*virtual*/ void setMinimized(BOOL b); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); /*virtual*/ void updateResizeLimits(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index d86e1b3fd7..49f36a2f32 100755 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -264,7 +264,7 @@ void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& if(!isTornOff() && matchesKey(key)) { - LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, false); + LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, take_focus); } } @@ -328,7 +328,7 @@ void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp) void LLFloaterIMNearbyChat::show() { openFloater(getKey()); - } +} bool LLFloaterIMNearbyChat::isChatVisible() const { diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 0824b26406..9ce5e12897 100755 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -605,11 +605,15 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, } //Don't show nearby toast, if conversation is visible and selected - if (im_box->getSelectedSession().isNull() && + if ((nearby_chat->hasFocus()) || + ((im_box->getSelectedSession().isNull() && ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost()) - || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost()))) + || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost()))))) { - return; + if(nearby_chat->isMessagePaneExpanded()) + { + return; + } } //Will show toast when chat preference is set diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 6d5145f205..8ec85e1160 100755 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -39,6 +39,7 @@ #include "llchannelmanager.h" #include "llchiclet.h" #include "llchicletbar.h" +#include "lldonotdisturbnotificationstorage.h" #include "llfloaterreg.h" #include "llfloateravatarpicker.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container @@ -645,6 +646,23 @@ void LLFloaterIMSession::setDocked(bool docked, bool pop_on_undock) } } +void LLFloaterIMSession::setMinimized(BOOL b) +{ + bool wasMinimized = isMinimized(); + LLFloaterIMSessionTab::setMinimized(b); + + //Switching from minimized state to un-minimized state + if(wasMinimized && !b) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSessionID); + } + } +} + void LLFloaterIMSession::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> @@ -713,6 +731,18 @@ BOOL LLFloaterIMSession::getVisible() return visible; } +void LLFloaterIMSession::setFocus(BOOL focus) +{ + LLFloaterIMSessionTab::setFocus(focus); + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(focus && gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSessionID); + } +} + //static bool LLFloaterIMSession::toggle(const LLUUID& session_id) { @@ -1125,9 +1155,10 @@ public: mSessionID = session_id; } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - llinfos << "Error inviting all agents to session" << llendl; + llwarns << "Error inviting all agents to session [status:" + << statusNum << "]: " << content << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index cb330bca0f..a0e0171b34 100755 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -65,8 +65,10 @@ public: // LLView overrides /*virtual*/ BOOL postBuild(); + /*virtual*/ void setMinimized(BOOL b); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); + /*virtual*/ void setFocus(BOOL focus); // Check typing timeout timer. /*virtual*/ void draw(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 5083331167..ce6e639305 100755 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -64,6 +64,8 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mHasVisibleBeenInitialized(false) , mIsParticipantListExpanded(true) , mChatLayoutPanel(NULL) + , mInputPanels(NULL) + , mChatLayoutPanelHeight(0) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -265,13 +267,15 @@ BOOL LLFloaterIMSessionTab::postBuild() mInputEditor = getChild<LLChatEntry>("chat_editor"); mChatLayoutPanel = getChild<LLLayoutPanel>("chat_layout_panel"); + mInputPanels = getChild<LLLayoutStack>("input_panels"); mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this)); mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setPassDelete(TRUE); mInputEditor->setFont(LLViewerChat::getChatFont()); - mInputEditorPad = mChatLayoutPanel->getRect().getHeight() - mInputEditor->getRect().getHeight(); + mChatLayoutPanelHeight = mChatLayoutPanel->getRect().getHeight(); + mInputEditorPad = mChatLayoutPanelHeight - mInputEditor->getRect().getHeight(); setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); @@ -749,9 +753,7 @@ void LLFloaterIMSessionTab::forceReshape() void LLFloaterIMSessionTab::reshapeChatLayoutPanel() { - LLRect chat_layout_panel_rect = mChatLayoutPanel->getRect(); - LLRect input_rect = mInputEditor->getRect(); - mChatLayoutPanel->reshape(chat_layout_panel_rect.getWidth(), input_rect.getHeight() + mInputEditorPad, FALSE); + mChatLayoutPanel->reshape(mChatLayoutPanel->getRect().getWidth(), mInputEditor->getRect().getHeight() + mInputEditorPad, FALSE); } void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) @@ -850,6 +852,7 @@ void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self) self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon")); self->mContentPanel->setVisible(!expand); self->mToolbarPanel->setVisible(!expand); + self->mInputEditor->enableSingleLineMode(expand); self->reshapeFloater(expand); self->setMessagePaneExpanded(!expand); } @@ -862,20 +865,20 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse) if(collapse) { mFloaterHeight = floater_rect.getHeight(); - S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight(); + S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight() + + mChatLayoutPanel->getRect().getHeight() - mChatLayoutPanelHeight + 2; floater_rect.mTop -= height; - enableResizeCtrls(true, true, false); } else { floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; - enableResizeCtrls(true, true, true); - } + + enableResizeCtrls(true, true, !collapse); + saveCollapsedState(); setShape(floater_rect, true); mBodyStack->updateLayout(); - } void LLFloaterIMSessionTab::restoreFloater() diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index c7e73bd70d..302d5a8066 100755 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -175,17 +175,14 @@ protected: LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; LLLayoutPanel * mChatLayoutPanel; - int mInputEditorPad; // padding between input field and chat history - + LLLayoutStack * mInputPanels; + LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; LLButton* mCloseBtn; LLButton* mGearBtn; - S32 mFloaterHeight; - - private: // Handling selection and contextual menu void doToSelected(const LLSD& userdata); @@ -209,6 +206,10 @@ private: bool mHasVisibleBeenInitialized; LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. + + S32 mInputEditorPad; + S32 mChatLayoutPanelHeight; + S32 mFloaterHeight; }; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 0a30fef768..8290494c22 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -557,7 +557,7 @@ void LLPanelLandGeneral::refresh() BOOL is_leased = (LLParcel::OS_LEASED == parcel->getOwnershipStatus()); BOOL region_xfer = FALSE; if(regionp - && !(regionp->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)) + && !(regionp->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))) { region_xfer = TRUE; } @@ -2120,7 +2120,7 @@ void LLPanelLandOptions::refreshSearch() LLViewerParcelMgr::isParcelModifiableByAgent( parcel, GP_LAND_CHANGE_IDENTITY) && region - && !(region->getRegionFlags() & REGION_FLAGS_BLOCK_PARCEL_SEARCH); + && !(region->getRegionFlag(REGION_FLAGS_BLOCK_PARCEL_SEARCH)); // There is a bug with this panel whereby the Show Directory bit can be // slammed off by the Region based on an override. Since this data is cached @@ -2873,7 +2873,7 @@ void LLPanelLandCovenant::refresh() LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause"); if (resellable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) { resellable_clause->setText(getString("can_not_resell")); } @@ -2886,7 +2886,7 @@ void LLPanelLandCovenant::refresh() LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause"); if (changeable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) { changeable_clause->setText(getString("can_change")); } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ea839e6f5a..100f1d580b 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -760,7 +760,6 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) void LLFloaterModelPreview::draw() { LLFloater::draw(); - LLRect r = getRect(); mModelPreview->update(); @@ -1684,7 +1683,6 @@ bool LLModelLoader::doLoadModel() //If no skeleton, do a breadth-first search to get at specific joints bool rootNode = false; - bool skeletonWithNoRootNode = false; //Need to test for a skeleton that does not have a root node //This occurs when your instance controller does not have an associated scene @@ -1695,10 +1693,6 @@ bool LLModelLoader::doLoadModel() { rootNode = true; } - else - { - skeletonWithNoRootNode = true; - } } if ( !pSkeleton || !rootNode ) @@ -2502,7 +2496,7 @@ void LLModelLoader::loadTextures() if(!material.mDiffuseMapFilename.empty()) { material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW); + LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); mNumOfFetchingTextures++ ; @@ -5020,16 +5014,9 @@ BOOL LLModelPreview::render() bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean(); bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean(); - bool resetJoints = false; if ( upload_joints != mLastJointUpdate ) { - if ( mLastJointUpdate ) - { - resetJoints = true; - } - mLastJointUpdate = upload_joints; - } for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a28af2101b..bbf88060c1 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -558,7 +558,7 @@ void LLFloaterPreference::apply() LLViewerMedia::setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); - if (hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) + if (hasChild("web_proxy_enabled", TRUE) &&hasChild("web_proxy_editor", TRUE) && hasChild("web_proxy_port", TRUE)) { bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue(); std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue(); @@ -1582,7 +1582,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) { std::string ctrl_name = name.asString(); - if ((ctrl_name =="" )|| !hasChild(ctrl_name, true)) + if ((ctrl_name =="" )|| !hasChild(ctrl_name, TRUE)) return; LLTextBox* text_box = getChild<LLTextBox>(name.asString()); @@ -1819,7 +1819,7 @@ LLPanelPreference::LLPanelPreference() BOOL LLPanelPreference::postBuild() { ////////////////////// PanelGeneral /////////////////// - if (hasChild("display_names_check")) + if (hasChild("display_names_check", TRUE)) { BOOL use_people_api = gSavedSettings.getBOOL("UsePeopleAPI"); LLCheckBoxCtrl* ctrl_display_name = getChild<LLCheckBoxCtrl>("display_names_check"); @@ -1831,7 +1831,7 @@ BOOL LLPanelPreference::postBuild() } ////////////////////// PanelVoice /////////////////// - if (hasChild("voice_unavailable")) + if (hasChild("voice_unavailable", TRUE)) { BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice"); getChildView("voice_unavailable")->setVisible( voice_disabled); @@ -1840,7 +1840,7 @@ BOOL LLPanelPreference::postBuild() //////////////////////PanelSkins /////////////////// - if (hasChild("skin_selection")) + if (hasChild("skin_selection", TRUE)) { LLFloaterPreference::refreshSkin(this); @@ -1854,28 +1854,28 @@ BOOL LLPanelPreference::postBuild() } //////////////////////PanelPrivacy /////////////////// - if (hasChild("media_enabled")) + if (hasChild("media_enabled", TRUE)) { bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); getChild<LLCheckBoxCtrl>("media_enabled")->set(media_enabled); getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(media_enabled); } - if (hasChild("music_enabled")) + if (hasChild("music_enabled", TRUE)) { getChild<LLCheckBoxCtrl>("music_enabled")->set(gSavedSettings.getBOOL("AudioStreamingMusic")); } - if (hasChild("voice_call_friends_only_check")) + if (hasChild("voice_call_friends_only_check", TRUE)) { getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2)); } - if (hasChild("favorites_on_login_check")) + if (hasChild("favorites_on_login_check", TRUE)) { getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); } //////////////////////PanelAdvanced /////////////////// - if (hasChild("modifier_combo")) + if (hasChild("modifier_combo", TRUE)) { //localizing if push2talk button is set to middle mouse if (MIDDLE_MOUSE_CV == getChild<LLUICtrl>("modifier_combo")->getValue().asString()) @@ -1885,7 +1885,7 @@ BOOL LLPanelPreference::postBuild() } //////////////////////PanelSetup /////////////////// - if (hasChild("max_bandwidth")) + if (hasChild("max_bandwidth"), TRUE) { mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT); gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2)); diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp index c7fab2573f..3a7ca17b73 100755 --- a/indra/newview/llfloaterregiondebugconsole.cpp +++ b/indra/newview/llfloaterregiondebugconsole.cpp @@ -75,7 +75,7 @@ namespace { public: /* virtual */ - void error(U32 status, const std::string& reason) + void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { sConsoleReplySignal(UNABLE_TO_SEND_COMMAND); } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index e6b76159a1..50c013a49d 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -318,7 +318,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) // extract message std::string sim_name; std::string sim_type = LLTrans::getString("land_type_unknown"); - U32 region_flags; + U64 region_flags; U8 agent_limit; F32 object_bonus_factor; U8 sim_access; @@ -328,7 +328,6 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) BOOL use_estate_sun; F32 sun_hour; msg->getString("RegionInfo", "SimName", sim_name); - msg->getU32("RegionInfo", "RegionFlags", region_flags); msg->getU8("RegionInfo", "MaxAgents", agent_limit); msg->getF32("RegionInfo", "ObjectBonusFactor", object_bonus_factor); msg->getU8("RegionInfo", "SimAccess", sim_access); @@ -347,6 +346,17 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) LLTrans::findString(sim_type, sim_type); // try localizing sim product name } + if (msg->has(_PREHASH_RegionInfo3)) + { + msg->getU64("RegionInfo3", "RegionFlagsExtended", region_flags); + } + else + { + U32 flags = 0; + msg->getU32("RegionInfo", "RegionFlags", flags); + region_flags = flags; + } + // GENERAL PANEL panel = tab->getChild<LLPanel>("General"); panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name)); @@ -378,9 +388,9 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel = tab->getChild<LLPanel>("Debug"); panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name) ); - panel->getChild<LLUICtrl>("disable_scripts_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_SCRIPTS)) ); - panel->getChild<LLUICtrl>("disable_collisions_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_COLLISIONS)) ); - panel->getChild<LLUICtrl>("disable_physics_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_PHYSICS)) ); + panel->getChild<LLUICtrl>("disable_scripts_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_SCRIPTS) ? TRUE : FALSE )) ); + panel->getChild<LLUICtrl>("disable_collisions_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_COLLISIONS) ? TRUE : FALSE )) ); + panel->getChild<LLUICtrl>("disable_physics_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_PHYSICS) ? TRUE : FALSE )) ); panel->setCtrlsEnabled(allow_modify); // TERRAIN PANEL @@ -748,9 +758,10 @@ class ConsoleRequestResponder : public LLHTTPClient::Responder { public: /*virtual*/ - void error(U32 status, const std::string& reason) + void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "requesting mesh_rez_enabled failed" << llendl; + llwarns << "ConsoleRequestResponder error requesting mesh_rez_enabled [status:" + << status << "]: " << content << llendl; } }; @@ -760,9 +771,10 @@ class ConsoleUpdateResponder : public LLHTTPClient::Responder { public: /* virtual */ - void error(U32 status, const std::string& reason) + void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Updating mesh enabled region setting failed" << llendl; + llwarns << "ConsoleRequestResponder error updating mesh enabled region setting [status:" + << status << "]: " << content << llendl; } }; @@ -2239,10 +2251,10 @@ public: } // if we get an error response - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llinfos << "LLEstateChangeInfoResponder::error " - << status << ": " << reason << llendl; + llinfos << "LLEstateChangeInfoResponder::error [status:" + << status << "]: " << content << llendl; } private: LLHandle<LLPanel> mpPanel; @@ -2318,7 +2330,7 @@ bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region) LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause"); if (resellable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) { resellable_clause->setText(getString("can_not_resell")); } @@ -2331,7 +2343,7 @@ bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region) LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause"); if (changeable_clause) { - if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) { changeable_clause->setText(getString("can_change")); } diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 0e4c7406c5..35b63c5480 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -111,9 +111,6 @@ LLFloaterReporter::LLFloaterReporter(const LLSD& key) // static void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg) { - U32 region_flags; - msg->getU32("RegionInfo", "RegionFlags", region_flags); - if ( LLFloaterReg::instanceVisible("reporter") ) { LLNotificationsUtil::add("HelpReportAbuseEmailLL"); @@ -713,7 +710,7 @@ class LLUserReportResponder : public LLHTTPClient::Responder public: LLUserReportResponder(): LLHTTPClient::Responder() {} - void error(U32 status, const std::string& reason) + void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { // *TODO do some user messaging here LLUploadDialog::modalUploadFinished(); @@ -783,8 +780,8 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer<LLViewerFetchedTexture> image_in_list = - LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); - image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER); + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid); + image_in_list->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER); // the texture picker then uses that texture LLTexturePicker* texture = getChild<LLTextureCtrl>("screenshot"); @@ -831,12 +828,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, return; } - EReportType report_type = UNKNOWN_REPORT; - if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION) - { - report_type = COMPLAINT_REPORT; - } - else + if (data->mPreferredLocation != LLResourceData::INVALID_LOCATION) { llwarns << "Unknown report type : " << data->mPreferredLocation << llendl; } diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index b691db1049..6c17f62c1e 100755 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -105,7 +105,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: if (objectp) { - objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI)); + objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); floater_label = llformat("%s(%.0f, %.0f, %.0f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 8d8bba7b17..13cb3c2eb0 100755 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -221,9 +221,9 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) } } -void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason) +void fetchScriptLimitsRegionInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Error from responder " << reason << llendl; + llwarns << "fetchScriptLimitsRegionInfoResponder error [status:" << status << "]: " << content << llendl; } void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) @@ -308,9 +308,9 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) } } -void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason) +void fetchScriptLimitsRegionSummaryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Error from responder " << reason << llendl; + llwarns << "fetchScriptLimitsRegionSummaryResponder error [status:" << status << "]: " << content << llendl; } void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref) @@ -417,9 +417,9 @@ result (map) } } -void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason) +void fetchScriptLimitsRegionDetailsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Error from responder " << reason << llendl; + llwarns << "fetchScriptLimitsRegionDetailsResponder error [status:" << status << "]: " << content << llendl; } void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) @@ -513,9 +513,9 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) } } -void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason) +void fetchScriptLimitsAttachmentInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "Error from responder " << reason << llendl; + llwarns << "fetchScriptLimitsAttachmentInfoResponder error [status:" << status << "]: " << content << llendl; } ///---------------------------------------------------------------------------- diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index 9bcfa5fe14..f8732ef94b 100755 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -89,7 +89,7 @@ class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); public: protected: LLSD mInfo; @@ -101,7 +101,7 @@ class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); public: protected: LLSD mInfo; @@ -113,7 +113,7 @@ class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); public: protected: LLSD mInfo; @@ -125,7 +125,7 @@ class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder fetchScriptLimitsAttachmentInfoResponder() {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); public: protected: }; diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 96b5c6b09b..5f9556a870 100755 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -28,10 +28,13 @@ #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" +#include "llpaneleditwearable.h" // newview includes #include "llsidetraypanelcontainer.h" #include "lltransientfloatermgr.h" +#include "llpaneloutfitedit.h" +#include "llsidepanelappearance.h" //static const std::string LLFloaterSidePanelContainer::sMainPanelName("main_panel"); @@ -54,6 +57,27 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key) getChild<LLPanel>(sMainPanelName)->onOpen(key); } +void LLFloaterSidePanelContainer::onClickCloseBtn() +{ + LLPanelOutfitEdit* panel_outfit_edit = + dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); + if (panel_outfit_edit) + { + LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); + if (parent == this ) + { + LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance")); + if ( panel_appearance ) + { + panel_appearance->getWearable()->onClose(); + panel_appearance->showOutfitsInventoryPanel(); + } + } + } + + LLFloater::onClickCloseBtn(); +} + LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) { LLView* view = findChildView(panel_name, true); diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 10d85867ce..491723471f 100755 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -51,6 +51,8 @@ public: /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClickCloseBtn(); + LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); static void showPanel(const std::string& floater_name, const LLSD& key); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 15e0b89f6c..0106a1615d 100755 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -855,7 +855,6 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID) LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params); // create a new panel panel->buildFromFile(path); // build it - LLRect new_size = panel->getRect(); // get its rectangle panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index a4dfd94496..5c6ce9d311 100755 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -521,7 +521,7 @@ public: void fire(const LLUUID& inv_item_id) { LLViewerInventoryItem* item = gInventory.getItem(inv_item_id); - + if (item) LLFriendCardsManager::instance().extractAvatarID(item->getCreatorUUID()); } @@ -557,7 +557,7 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) lldebugs << "Sent create_inventory_item for " << avatarID << ", " << name << llendl; // TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not - LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback(); + LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback; create_inventory_callingcard(avatarID, findFriendAllSubfolderUUIDImpl(), cb); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index f307505ff8..9aa86297fc 100755 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -338,7 +338,7 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) gAgent.sendReliableMessage(); - LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, false); + LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id); notifyObservers(); } diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 1208c9378e..60fa53f491 100755 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -79,10 +79,10 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); - left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]); - right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]); - top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]); - bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]); + left = llround((F32) left * LLUI::getScaleFactor().mV[VX]); + right = llround((F32) right * LLUI::getScaleFactor().mV[VX]); + top = llround((F32) top * LLUI::getScaleFactor().mV[VY]); + bottom = llround((F32) bottom * LLUI::getScaleFactor().mV[VY]); F32 old_far_plane = LLViewerCamera::getInstance()->getFar(); F32 old_near_plane = LLViewerCamera::getInstance()->getNear(); diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 188c4bcf25..2d0fc26c2a 100755 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -29,6 +29,7 @@ #include "llgroupiconctrl.h" #include "llagent.h" +#include "llviewertexture.h" /* #include "llavatarconstants.h" #include "llcallingcard.h" // for LLAvatarTracker diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 81eb1d397e..cbd844cdac 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1847,14 +1847,15 @@ public: GroupMemberDataResponder() {} virtual ~GroupMemberDataResponder() {} virtual void result(const LLSD& pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); private: LLSD mMemberData; }; -void GroupMemberDataResponder::error(U32 pStatus, const std::string& pReason) +void GroupMemberDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) { - LL_WARNS("GrpMgr") << "Error receiving group member data." << LL_ENDL; + LL_WARNS("GrpMgr") << "Error receiving group member data [status:" + << pStatus << "]: " << pContent << LL_ENDL; } void GroupMemberDataResponder::result(const LLSD& content) diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp index 4850d18d99..37428c4a44 100755 --- a/indra/newview/llhomelocationresponder.cpp +++ b/indra/newview/llhomelocationresponder.cpp @@ -97,7 +97,7 @@ void LLHomeLocationResponder::result( const LLSD& content ) } } -void LLHomeLocationResponder::error( U32 status, const std::string& reason ) +void LLHomeLocationResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) { - llinfos << "received error(" << reason << ")" << llendl; + llwarns << "LLHomeLocationResponder error [status:" << status << "]: " << content << llendl; } diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h index d640b9c894..9bf4b12c4e 100755 --- a/indra/newview/llhomelocationresponder.h +++ b/indra/newview/llhomelocationresponder.h @@ -36,7 +36,7 @@ class LLHomeLocationResponder : public LLHTTPClient::Responder { virtual void result( const LLSD& content ); - virtual void error( U32 status, const std::string& reason ); + virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content ); }; #endif diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index bc3b220dc0..9dde65ceb6 100755 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -636,7 +636,7 @@ bool LLHUDEffectLookAt::calcTargetPosition() } else { - target_rot = target_av->mRoot.getWorldRotation(); + target_rot = target_av->mRoot->getWorldRotation(); } } else // target obj is not an avatar diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 579b6008ae..3c6bcd9829 100755 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -186,11 +186,8 @@ void LLHUDText::renderText() LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); } - LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight()); LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; - LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; - LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; @@ -440,7 +437,7 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset) LLVector3 x_pixel_vec; LLVector3 y_pixel_vec; LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); - LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec); +// LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec); // if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen) // { // // bubble off-screen, so find a spot for it along screen edge diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index c64ecdc47a..59272d721f 100755 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -394,9 +394,10 @@ public: mSessionID = session_id; } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - llinfos << "Error inviting all agents to session" << llendl; + llwarns << "Error inviting all agents to session [status:" + << statusNum << "]: " << content << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 76a314f807..2c20409381 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -174,6 +174,8 @@ void on_new_message(const LLSD& msg) // determine state of conversations floater enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; + + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); @@ -181,9 +183,9 @@ void on_new_message(const LLSD& msg) { conversations_floater_status = CLOSED; } - else if ( !im_box->hasFocus() && - (!session_floater || !LLFloater::isVisible(session_floater) - || session_floater->isMinimized() || !session_floater->hasFocus())) + else if (!im_box->hasFocus() && + !(session_floater && LLFloater::isVisible(session_floater) + && !session_floater->isMinimized() && session_floater->hasFocus())) { conversations_floater_status = NOT_ON_TOP; } @@ -226,7 +228,7 @@ void on_new_message(const LLSD& msg) // 0. nothing - exit if (("none" == user_preferences || ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status) - && session_floater->isMessagePaneExpanded()) + && session_floater->isMessagePaneExpanded()) { return; } @@ -274,7 +276,9 @@ void on_new_message(const LLSD& msg) // 2. Flash line item if ("openconversations" == user_preferences - || ON_TOP == conversations_floater_status) + || ON_TOP == conversations_floater_status + || ("toast" == user_preferences && ON_TOP != conversations_floater_status) + || ("flash" == user_preferences && CLOSED == conversations_floater_status)) { if(!LLMuteList::getInstance()->isMuted(participant_id)) { @@ -295,8 +299,11 @@ void on_new_message(const LLSD& msg) } // 4. Toast - if ("toast" == user_preferences + if ((("toast" == user_preferences) && + (CLOSED == conversations_floater_status + || NOT_ON_TOP == conversations_floater_status)) || !session_floater->isMessagePaneExpanded()) + { //Show IM toasts (upper right toasts) // Skip toasting for system messages and for nearby chat @@ -1393,7 +1400,7 @@ public: mAgents = agents_to_invite; } - virtual void error(U32 statusNum, const std::string& reason) + virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { //try an "old school" way. if ( statusNum == 400 ) @@ -1405,6 +1412,9 @@ public: mAgents); } + llwarns << "LLStartConferenceChatResponder error [status:" + << statusNum << "]: " << content << llendl; + //else throw an error back to the client? //in theory we should have just have these error strings //etc. set up in this file as opposed to the IMMgr, @@ -1550,8 +1560,10 @@ public: } } - void error(U32 statusNum, const std::string& reason) - { + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + { + llwarns << "LLViewerChatterBoxInvitationAcceptResponder error [status:" + << statusNum << "]: " << content << llendl; //throw something back to the viewer here? if ( gIMMgr ) { @@ -2839,6 +2851,8 @@ LLUUID LLIMMgr::addSession( //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions if (!new_session) return session_id; + llinfos << "LLIMMgr::addSession, new session added, name = " << name << ", session id = " << session_id << llendl; + //Per Plan's suggestion commented "explicit offline status warning" out to make Dessie happier (see EXT-3609) //*TODO After February 2010 remove this commented out line if no one will be missing that warning //noteOfflineUsers(session_id, floater, ids); @@ -2874,6 +2888,8 @@ void LLIMMgr::removeSession(const LLUUID& session_id) LLIMModel::getInstance()->clearSession(session_id); + llinfos << "LLIMMgr::removeSession, session removed, session id = " << session_id << llendl; + notifyObserverSessionRemoved(session_id); } @@ -2891,7 +2907,6 @@ void LLIMMgr::inviteToSession( // voice invite question is different from default only for group call (EXT-7118) std::string question_type = "VoiceInviteQuestionDefault"; - BOOL ad_hoc_invite = FALSE; BOOL voice_invite = FALSE; bool is_linden = LLMuteList::getInstance()->isLinden(caller_name); @@ -2914,13 +2929,11 @@ void LLIMMgr::inviteToSession( //else it's an ad-hoc //and a voice ad-hoc notify_box_type = "VoiceInviteAdHoc"; - ad_hoc_invite = TRUE; voice_invite = TRUE; } else if ( inv_type == INVITATION_TYPE_IMMEDIATE ) { notify_box_type = "InviteAdHoc"; - ad_hoc_invite = TRUE; } LLSD payload; @@ -3505,10 +3518,9 @@ public: } std::string buffer = saved + message; - BOOL is_this_agent = FALSE; if(from_id == gAgentID) { - is_this_agent = TRUE; + return; } gIMMgr->addMessage( session_id, diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 1e15dc832c..9c6db3676f 100755 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -292,6 +292,11 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) delete mPropertiesRequest; mPropertiesRequest = NULL; } +/* +prep# + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + llwarns << "MuteVoiceResponder error [status:" << status << "]: " << content << llendl; + */ void LLInspectAvatar::updateVolumeSlider() { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0ee78d57bd..a5043a30ac 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -51,6 +51,7 @@ #include "llclipboard.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" @@ -96,8 +97,6 @@ struct LLMoveInv using namespace LLOldEvents; // Function declarations -void remove_inventory_category_from_avatar(LLInventoryCategory* category); -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); void teleport_via_landmark(const LLUUID& asset_id); @@ -1545,7 +1544,7 @@ LLUIImagePtr LLItemBridge::getIcon() const mIsLink); } - return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT); + return LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT); } LLUIImagePtr LLItemBridge::getIconOverlay() const @@ -2649,7 +2648,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, if(drop && accept) { it = inventory_objects.begin(); - LLInventoryObject::object_list_t::iterator first_it = inventory_objects.begin(); LLMoveInv* move_inv = new LLMoveInv; move_inv->mObjectID = object_id; move_inv->mCategoryID = category_id; @@ -2926,7 +2924,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) LLViewerInventoryCategory* cat = getCategory(); if(!cat) return; - remove_inventory_category_from_avatar ( cat ); + LLAppearanceMgr::instance().takeOffOutfit( cat->getLinkedUUID() ); return; } else if ("purge" == action) @@ -5236,7 +5234,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) else if(item && item->isFinished()) { // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); copy_inventory_item( gAgent.getID(), item->getPermissions().getOwner(), @@ -5253,11 +5251,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) } else if (isRemoveAction(action)) { - LLInventoryItem* item = gInventory.getItem(mUUID); - if(item) - { - LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID()); - } + LLAppearanceMgr::instance().removeItemFromAvatar(mUUID); } else LLItemBridge::performAction(model, action); } @@ -5549,120 +5543,6 @@ LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory, mInvType = inv_type; } -void remove_inventory_category_from_avatar( LLInventoryCategory* category ) -{ - if(!category) return; - lldebugs << "remove_inventory_category_from_avatar( " << category->getName() - << " )" << llendl; - - - if (gAgentCamera.cameraCustomizeAvatar()) - { - // switching to outfit editor should automagically save any currently edited wearable - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); - } - - remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); -} - -struct OnRemoveStruct -{ - LLUUID mUUID; - OnRemoveStruct(const LLUUID& uuid): - mUUID(uuid) - { - } -}; - -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) -{ - - // Find all the wearables that are in the category's subtree. - lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; - if(proceed) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_wearable); - S32 i; - S32 wearable_count = item_array.count(); - - LLInventoryModel::cat_array_t obj_cat_array; - LLInventoryModel::item_array_t obj_item_array; - LLIsType is_object( LLAssetType::AT_OBJECT ); - gInventory.collectDescendentsIf(category_id, - obj_cat_array, - obj_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_object); - S32 obj_count = obj_item_array.count(); - - // Find all gestures in this folder - LLInventoryModel::cat_array_t gest_cat_array; - LLInventoryModel::item_array_t gest_item_array; - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - gInventory.collectDescendentsIf(category_id, - gest_cat_array, - gest_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_gesture); - S32 gest_count = gest_item_array.count(); - - if (wearable_count > 0) //Loop through wearables. If worn, remove. - { - for(i = 0; i < wearable_count; ++i) - { - LLViewerInventoryItem *item = item_array.get(i); - if (item->getType() == LLAssetType::AT_BODYPART) - continue; - if (gAgent.isTeen() && item->isWearableType() && - (item->getWearableType() == LLWearableType::WT_UNDERPANTS || item->getWearableType() == LLWearableType::WT_UNDERSHIRT)) - continue; - if (get_is_item_worn(item->getUUID())) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item->getLinkedUUID())); - } - } - } - - if (obj_count > 0) - { - for(i = 0; i < obj_count; ++i) - { - LLViewerInventoryItem *obj_item = obj_item_array.get(i); - if (get_is_item_worn(obj_item->getUUID())) - { - LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID()); - } - } - } - - if (gest_count > 0) - { - for(i = 0; i < gest_count; ++i) - { - LLViewerInventoryItem *gest_item = gest_item_array.get(i); - if (get_is_item_worn(gest_item->getUUID())) - { - LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() ); - gInventory.updateItem( gest_item ); - gInventory.notifyObservers(); - } - - } - } - } -} - BOOL LLWearableBridge::renameItem(const std::string& new_name) { if (get_is_item_worn(mUUID)) @@ -5873,7 +5753,7 @@ void LLWearableBridge::wearAddOnAvatar() } // static -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) +void LLWearableBridge::onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata ) { LLUUID* item_id = (LLUUID*) userdata; if(wearable) @@ -5899,7 +5779,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda // static // BAP remove the "add" code path once everything is fully COF-ified. -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) +void LLWearableBridge::onWearAddOnAvatarArrived( LLViewerWearable* wearable, void* userdata ) { LLUUID* item_id = (LLUUID*) userdata; if(wearable) @@ -5959,95 +5839,12 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) return FALSE; } -// static -void LLWearableBridge::onRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - if(get_is_item_worn(self->mUUID)) - { - LLViewerInventoryItem* item = self->getItem(); - if (item) - { - LLUUID parent_id = item->getParentUUID(); - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new OnRemoveStruct(LLUUID(self->mUUID))); - } - } -} - -// static -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, - void* userdata) -{ - OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; - const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); - if(wearable) - { - if( get_is_item_worn( item_id ) ) - { - LLWearableType::EType type = wearable->getType(); - - if( !(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES ) ) //&& - //!((!gAgent.isTeen()) && ( type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT )) ) - { - bool do_remove_all = false; - U32 index = gAgentWearables.getWearableIndex(wearable); - gAgentWearables.removeWearable( type, do_remove_all, index ); - } - } - } - - // Find and remove this item from the COF. - LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); - gInventory.notifyObservers(); - - delete on_remove_struct; -} - -// static -void LLWearableBridge::removeAllClothesFromAvatar() -{ - // Fetch worn clothes (i.e. the ones in COF). - LLInventoryModel::item_array_t clothing_items; - LLInventoryModel::cat_array_t dummy; - LLIsType is_clothing(LLAssetType::AT_CLOTHING); - gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - dummy, - clothing_items, - LLInventoryModel::EXCLUDE_TRASH, - is_clothing, - false); - - // Take them off by removing from COF. - for (LLInventoryModel::item_array_t::const_iterator it = clothing_items.begin(); it != clothing_items.end(); ++it) - { - LLAppearanceMgr::instance().removeItemFromAvatar((*it)->getUUID()); - } -} - -// static -void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) -{ - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item->getUUID())); - } -} - void LLWearableBridge::removeFromAvatar() { + llwarns << "safe to remove?" << llendl; if (get_is_item_worn(mUUID)) { - LLViewerInventoryItem* item = getItem(); - removeItemFromAvatar(item); + LLAppearanceMgr::instance().removeItemFromAvatar(mUUID); } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 5c6cf0f0f0..517153e171 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -34,7 +34,7 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llviewercontrol.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "lltooldraganddrop.h" class LLInventoryFilter; @@ -509,10 +509,10 @@ public: static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu static BOOL canWearOnAvatar( void* userdata ); - static void onWearOnAvatarArrived( LLWearable* wearable, void* userdata ); + static void onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata ); void wearOnAvatar(); - static void onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ); + static void onWearAddOnAvatarArrived( LLViewerWearable* wearable, void* userdata ); void wearAddOnAvatar(); static BOOL canEditOnAvatar( void* userdata ); // Access to editOnAvatar() from menu @@ -520,9 +520,6 @@ public: void editOnAvatar(); static BOOL canRemoveFromAvatar( void* userdata ); - static void onRemoveFromAvatar( void* userdata ); - static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata ); - static void removeItemFromAvatar(LLViewerInventoryItem *item); static void removeAllClothesFromAvatar(); void removeFromAvatar(); protected: diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 34734d57c5..02a2475cfd 100755 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -25,6 +25,8 @@ */ #include "llviewerprecompiledheaders.h" + +#include "linden_common.h" #include "llinventoryicon.h" #include "lldictionary.h" @@ -41,7 +43,7 @@ struct IconEntry : public LLDictionaryEntry }; class LLIconDictionary : public LLSingleton<LLIconDictionary>, - public LLDictionary<LLInventoryIcon::EIconName, IconEntry> + public LLDictionary<LLInventoryType::EIconName, IconEntry> { public: LLIconDictionary(); @@ -49,48 +51,48 @@ public: LLIconDictionary::LLIconDictionary() { - addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); - addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); - addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); - - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); - addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); - addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); - - addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); - addEntry(LLInventoryIcon::ICONNAME_MESH, new IconEntry("Inv_Mesh")); - - addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); - - addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); + addEntry(LLInventoryType::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); + addEntry(LLInventoryType::ICONNAME_SOUND, new IconEntry("Inv_Sound")); + addEntry(LLInventoryType::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryType::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryType::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryType::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryType::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); + addEntry(LLInventoryType::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); + addEntry(LLInventoryType::ICONNAME_OBJECT, new IconEntry("Inv_Object")); + addEntry(LLInventoryType::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); + addEntry(LLInventoryType::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); + addEntry(LLInventoryType::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); + addEntry(LLInventoryType::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); + + addEntry(LLInventoryType::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); + addEntry(LLInventoryType::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); + addEntry(LLInventoryType::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); + addEntry(LLInventoryType::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); + + addEntry(LLInventoryType::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); + addEntry(LLInventoryType::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); + addEntry(LLInventoryType::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); + + addEntry(LLInventoryType::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); + + addEntry(LLInventoryType::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); + addEntry(LLInventoryType::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); + addEntry(LLInventoryType::ICONNAME_MESH, new IconEntry("Inv_Mesh")); + + addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); + + addEntry(LLInventoryType::ICONNAME_NONE, new IconEntry("NONE")); } LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, @@ -102,7 +104,7 @@ LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, return LLUI::getUIImage(icon_name); } -LLUIImagePtr LLInventoryIcon::getIcon(EIconName idx) +LLUIImagePtr LLInventoryIcon::getIcon(LLInventoryType::EIconName idx) { return LLUI::getUIImage(getIconName(idx)); } @@ -112,56 +114,56 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, U32 misc_flag, BOOL item_is_multi) { - EIconName idx = ICONNAME_OBJECT; + LLInventoryType::EIconName idx = LLInventoryType::ICONNAME_OBJECT; if (item_is_multi) { - idx = ICONNAME_OBJECT_MULTI; + idx = LLInventoryType::ICONNAME_OBJECT_MULTI; return getIconName(idx); } switch(asset_type) { case LLAssetType::AT_TEXTURE: - idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? ICONNAME_SNAPSHOT : ICONNAME_TEXTURE; + idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? LLInventoryType::ICONNAME_SNAPSHOT : LLInventoryType::ICONNAME_TEXTURE; break; case LLAssetType::AT_SOUND: - idx = ICONNAME_SOUND; + idx = LLInventoryType::ICONNAME_SOUND; break; case LLAssetType::AT_CALLINGCARD: - idx = (misc_flag != 0) ? ICONNAME_CALLINGCARD_ONLINE : ICONNAME_CALLINGCARD_OFFLINE; + idx = (misc_flag != 0) ? LLInventoryType::ICONNAME_CALLINGCARD_ONLINE : LLInventoryType::ICONNAME_CALLINGCARD_OFFLINE; break; case LLAssetType::AT_LANDMARK: - idx = (misc_flag != 0) ? ICONNAME_LANDMARK_VISITED : ICONNAME_LANDMARK; + idx = (misc_flag != 0) ? LLInventoryType::ICONNAME_LANDMARK_VISITED : LLInventoryType::ICONNAME_LANDMARK; break; case LLAssetType::AT_SCRIPT: case LLAssetType::AT_LSL_TEXT: case LLAssetType::AT_LSL_BYTECODE: - idx = ICONNAME_SCRIPT; + idx = LLInventoryType::ICONNAME_SCRIPT; break; case LLAssetType::AT_CLOTHING: case LLAssetType::AT_BODYPART: idx = assignWearableIcon(misc_flag); break; case LLAssetType::AT_NOTECARD: - idx = ICONNAME_NOTECARD; + idx = LLInventoryType::ICONNAME_NOTECARD; break; case LLAssetType::AT_ANIMATION: - idx = ICONNAME_ANIMATION; + idx = LLInventoryType::ICONNAME_ANIMATION; break; case LLAssetType::AT_GESTURE: - idx = ICONNAME_GESTURE; + idx = LLInventoryType::ICONNAME_GESTURE; break; case LLAssetType::AT_LINK: - idx = ICONNAME_LINKITEM; + idx = LLInventoryType::ICONNAME_LINKITEM; break; case LLAssetType::AT_LINK_FOLDER: - idx = ICONNAME_LINKFOLDER; + idx = LLInventoryType::ICONNAME_LINKFOLDER; break; case LLAssetType::AT_OBJECT: - idx = ICONNAME_OBJECT; + idx = LLInventoryType::ICONNAME_OBJECT; break; case LLAssetType::AT_MESH: - idx = ICONNAME_MESH; + idx = LLInventoryType::ICONNAME_MESH; default: break; } @@ -170,13 +172,13 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, } -const std::string& LLInventoryIcon::getIconName(EIconName idx) +const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx) { const IconEntry *entry = LLIconDictionary::instance().lookup(idx); return entry->mName; } -LLInventoryIcon::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) +LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) { const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); return LLWearableType::getIconName(wearable_type); diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h index 5c8acf9e85..2197c53bb8 100755 --- a/indra/newview/llinventoryicon.h +++ b/indra/newview/llinventoryicon.h @@ -35,66 +35,20 @@ class LLInventoryIcon { public: - enum EIconName - { - ICONNAME_TEXTURE, - ICONNAME_SOUND, - ICONNAME_CALLINGCARD_ONLINE, - ICONNAME_CALLINGCARD_OFFLINE, - ICONNAME_LANDMARK, - ICONNAME_LANDMARK_VISITED, - ICONNAME_SCRIPT, - ICONNAME_CLOTHING, - ICONNAME_OBJECT, - ICONNAME_OBJECT_MULTI, - ICONNAME_NOTECARD, - ICONNAME_BODYPART, - ICONNAME_SNAPSHOT, - - ICONNAME_BODYPART_SHAPE, - ICONNAME_BODYPART_SKIN, - ICONNAME_BODYPART_HAIR, - ICONNAME_BODYPART_EYES, - ICONNAME_CLOTHING_SHIRT, - ICONNAME_CLOTHING_PANTS, - ICONNAME_CLOTHING_SHOES, - ICONNAME_CLOTHING_SOCKS, - ICONNAME_CLOTHING_JACKET, - ICONNAME_CLOTHING_GLOVES, - ICONNAME_CLOTHING_UNDERSHIRT, - ICONNAME_CLOTHING_UNDERPANTS, - ICONNAME_CLOTHING_SKIRT, - ICONNAME_CLOTHING_ALPHA, - ICONNAME_CLOTHING_TATTOO, - - ICONNAME_ANIMATION, - ICONNAME_GESTURE, - - ICONNAME_CLOTHING_PHYSICS, - - ICONNAME_LINKITEM, - ICONNAME_LINKFOLDER, - ICONNAME_MESH, - - ICONNAME_INVALID, - ICONNAME_COUNT, - ICONNAME_NONE = -1 - }; - static const std::string& getIconName(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, U32 misc_flag = 0, // different meanings depending on item type BOOL item_is_multi = FALSE); - static const std::string& getIconName(EIconName idx); + static const std::string& getIconName(LLInventoryType::EIconName idx); static LLUIImagePtr getIcon(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, U32 misc_flag = 0, // different meanings depending on item type BOOL item_is_multi = FALSE); - static LLUIImagePtr getIcon(EIconName idx); + static LLUIImagePtr getIcon(LLInventoryType::EIconName idx); protected: - static EIconName assignWearableIcon(U32 misc_flag); + static LLInventoryType::EIconName assignWearableIcon(U32 misc_flag); }; #endif // LL_LLINVENTORYICON_H diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index 3e0849a795..0601796436 100755 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -37,6 +37,7 @@ #include "lltextutil.h" // newview +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llviewerinventory.h" @@ -230,7 +231,7 @@ const std::string& LLPanelInventoryListItemBase::getDescription() const { return LLStringUtil::null; } - return inv_item->getDescription(); + return inv_item->getActualDescription(); } time_t LLPanelInventoryListItemBase::getCreationDate() const diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index e7d59d92d9..935fe2b4d0 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -460,9 +460,10 @@ public: { } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("InvAPI") << "CreateInventoryCategory failed. status = " << status << ", reasion = \"" << reason << "\"" << LL_ENDL; + LL_WARNS("InvAPI") << "CreateInventoryCategory failed [status:" + << status << "]: " << content << LL_ENDL; } virtual void result(const LLSD& content) @@ -1410,7 +1411,6 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) item_array_t items; update_map_t update; S32 count = content["items"].size(); - bool all_one_folder = true; LLUUID folder_id; // Does this loop ever execute more than once? for(S32 i = 0; i < count; ++i) @@ -1443,10 +1443,6 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) { folder_id = titem->getParentUUID(); } - else - { - all_one_folder = false; - } } U32 changes = 0x0; @@ -1460,10 +1456,9 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) } //If we get back an error (not found, etc...), handle it here -void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason) +void LLInventoryModel::fetchInventoryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llinfos << "fetchInventory::error " - << status << ": " << reason << llendl; + llwarns << "fetchInventory error [status:" << status << "]: " << content << llendl; gInventory.notifyObservers(); } @@ -1996,8 +1991,9 @@ bool LLInventoryModel::loadSkeleton( { LLViewerInventoryCategory* cat = (*invalid_cat_it).get(); cat->setVersion(NO_VERSION); - llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl; + LL_DEBUGS("Inventory") << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl; } + LL_INFOS("Inventory") << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << llendl; // At this point, we need to set the known descendents for each // category which successfully cached so that we do not @@ -2534,7 +2530,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) item_array_t items; update_map_t update; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); - bool all_one_folder = true; LLUUID folder_id; // Does this loop ever execute more than once? for(S32 i = 0; i < count; ++i) @@ -2566,10 +2561,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) { folder_id = titem->getParentUUID(); } - else - { - all_one_folder = false; - } } if(account) { @@ -3295,8 +3286,71 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c } } +//* @param[in] items vector of items in order to be saved. +/* +void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + item->setSortField(++sortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + updateItem(item); + // Tell the parent folder to refresh its sort order. + addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); + } + notifyObservers(); +} +*/ +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) + { + return a->getSortField() < b->getSortField(); + } +}; + +/** + * Sorts passed items by LLViewerInventoryItem sort field. + * + * @param[in, out] items - array of items, not sorted. + */ +//static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) +//{ +// static LLViewerInventoryItemSort sort_functor; +// std::sort(items.begin(), items.end(), sort_functor); +//} + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +/* +void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + // ensure items are sorted properly before changing order. EXT-3498 + rearrange_item_order_by_sort_field(items); + + // update order + updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} +*/ //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 503de627a0..8aac879a93 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -84,7 +84,7 @@ public: public: fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: LLSD mRequestSD; }; @@ -231,7 +231,8 @@ public: // Returns the uuid of the category that specifies 'type' as what it // defaults to containing. The category is not necessarily only for that type. // NOTE: If create_folder is true, this will create a new inventory category - // on the fly if one does not exist. + // on the fly if one does not exist. *NOTE: if find_in_library is true it + // will search in the user's library folder instead of "My Inventory" const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true); // will search in the user's library folder instead of "My Inventory" @@ -363,6 +364,12 @@ public: // Returns end() of the vector if not found. static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); + + // Rearranges Landmarks inside Favorites folder. + // Moves source landmark before target one. + void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + //void saveItemsOrder(const LLInventoryModel::item_array_t& items); + //-------------------------------------------------------------------- // Creation //-------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f4d0110b0f..f2b39e7186 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -183,7 +183,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) void LLInventoryModelBackgroundFetch::backgroundFetch() { - if (mBackgroundFetchActive && gAgent.getRegion()) + if (mBackgroundFetchActive && gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived()) { // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. if (gSavedSettings.getBOOL("UseHTTPInventory")) @@ -366,7 +366,7 @@ class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInvento public: LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); }; void LLInventoryModelFetchItemResponder::result( const LLSD& content ) @@ -375,9 +375,9 @@ void LLInventoryModelFetchItemResponder::result( const LLSD& content ) LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } -void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason ) +void LLInventoryModelFetchItemResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) { - LLInventoryModel::fetchInventoryResponder::error(status, reason); + LLInventoryModel::fetchInventoryResponder::errorWithContent(status, reason, content); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } @@ -391,7 +391,7 @@ public: {}; //LLInventoryModelFetchDescendentsResponder() {}; void result(const LLSD& content); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: BOOL getIsRecursive(const LLUUID& cat_id) const; private: @@ -529,12 +529,12 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) } // If we get back an error (not found, etc...), handle it here. -void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason) +void LLInventoryModelFetchDescendentsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - llinfos << "LLInventoryModelFetchDescendentsResponder::error " - << status << ": " << reason << llendl; + llinfos << "LLInventoryModelFetchDescendentsResponder::error [status:" + << status << "]: " << content << llendl; fetcher->incrFetchCount(-1); @@ -564,7 +564,6 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat { return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end()); } - // Bundle up a bunch of requests to send all at once. // static void LLInventoryModelBackgroundFetch::bulkFetch() @@ -687,20 +686,23 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { if (folder_count) { - std::string url = region->getCapability("FetchInventoryDescendents2"); - mFetchCount++; - if (folder_request_body["folders"].size()) - { - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); - LLHTTPClient::post(url, folder_request_body, fetcher, 300.0); - } - if (folder_request_body_lib["folders"].size()) + std::string url = region->getCapability("FetchInventoryDescendents2"); + if ( !url.empty() ) { - std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); + mFetchCount++; + if (folder_request_body["folders"].size()) + { + LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); + LLHTTPClient::post(url, folder_request_body, fetcher, 300.0); + } + if (folder_request_body_lib["folders"].size()) + { + std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); - LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); - } + LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); + LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); + } + } } if (item_count) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index fabcd50c7d..cf1fd4c0d0 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -401,8 +401,6 @@ void LLInventoryPanel::modelChanged(U32 mask) static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); LLFastTimer t2(FTM_REFRESH); - bool handled = false; - if (!mViewsInitialized) return; const LLInventoryModel* model = getModel(); @@ -437,7 +435,6 @@ void LLInventoryPanel::modelChanged(U32 mask) // Empty out the display name for relabel. if (mask & LLInventoryObserver::LABEL) { - handled = true; if (view_item) { // Request refresh on this item (also flags for filtering) @@ -456,7 +453,6 @@ void LLInventoryPanel::modelChanged(U32 mask) // Destroy and regenerate the UI. if (mask & LLInventoryObserver::REBUILD) { - handled = true; if (model_item && view_item && viewmodel_item) { const LLUUID& idp = viewmodel_item->getUUID(); @@ -500,8 +496,6 @@ void LLInventoryPanel::modelChanged(U32 mask) LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) { - handled = true; - ////////////////////////////// // ADD Operation // Item exists in memory but a UI element hasn't been created for it. diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 97ba5b634a..25df4889b0 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -53,7 +53,7 @@ #include "llviewerobject.h" #include "llface.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llagentwearables.h" #include "lltexlayerparams.h" #include "llvovolume.h" @@ -195,7 +195,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) mLastModified = new_last_modified; LLPointer<LLViewerFetchedTexture> texture = new LLViewerFetchedTexture - ("file://"+mFilename, mWorldID, LL_LOCAL_USE_MIPMAPS); + ("file://"+mFilename, FTT_LOCAL_FILE, mWorldID, LL_LOCAL_USE_MIPMAPS); texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image); texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image); @@ -437,8 +437,8 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id) LLFace* face = object->mDrawable->getFace(face_iter); if (face && face->getTexture() && face->getTexture()->getID() == old_id) { - object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture - (new_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture( + new_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); update_obj = true; } @@ -481,7 +481,7 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp U32 count = gAgentWearables.getWearableCount(type); for(U32 wearable_iter = 0; wearable_iter < count; wearable_iter++) { - LLWearable* wearable = gAgentWearables.getWearable(type, wearable_iter); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_iter); if (wearable) { std::vector<LLLocalTextureObject*> texture_list = wearable->getLocalTextureListSeq(); @@ -493,11 +493,11 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp if (lto && lto->getID() == old_id) { U32 local_texlayer_index = 0; /* can't keep that as static const, gives errors, so i'm leaving this var here */ - LLVOAvatarDefines::EBakedTextureIndex baked_texind = + LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind = lto->getTexLayer(local_texlayer_index)->getTexLayerSet()->getBakedTexIndex(); - LLVOAvatarDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind); - if (reg_texind != LLVOAvatarDefines::TEX_NUM_INDICES) + LLAvatarAppearanceDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind); + if (reg_texind != LLAvatarAppearanceDefines::TEX_NUM_INDICES) { U32 index = gAgentWearables.getWearableIndex(wearable); gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index); @@ -513,10 +513,10 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp } } -LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( - LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind) +LLAvatarAppearanceDefines::ETextureIndex LLLocalBitmap::getTexIndex( + LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind) { - LLVOAvatarDefines::ETextureIndex result = LLVOAvatarDefines::TEX_NUM_INDICES; // using as a default/fail return. + LLAvatarAppearanceDefines::ETextureIndex result = LLAvatarAppearanceDefines::TEX_NUM_INDICES; // using as a default/fail return. switch(type) { @@ -524,32 +524,32 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_EYES: + case LLAvatarAppearanceDefines::BAKED_EYES: { - result = LLVOAvatarDefines::TEX_EYES_ALPHA; + result = LLAvatarAppearanceDefines::TEX_EYES_ALPHA; break; } - case LLVOAvatarDefines::BAKED_HAIR: + case LLAvatarAppearanceDefines::BAKED_HAIR: { - result = LLVOAvatarDefines::TEX_HAIR_ALPHA; + result = LLAvatarAppearanceDefines::TEX_HAIR_ALPHA; break; } - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_ALPHA; + result = LLAvatarAppearanceDefines::TEX_HEAD_ALPHA; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_ALPHA; + result = LLAvatarAppearanceDefines::TEX_LOWER_ALPHA; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_ALPHA; + result = LLAvatarAppearanceDefines::TEX_UPPER_ALPHA; break; } @@ -565,9 +565,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_EYES: { - if (baked_texind == LLVOAvatarDefines::BAKED_EYES) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_EYES) { - result = LLVOAvatarDefines::TEX_EYES_IRIS; + result = LLAvatarAppearanceDefines::TEX_EYES_IRIS; } break; @@ -575,9 +575,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_GLOVES: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_GLOVES; + result = LLAvatarAppearanceDefines::TEX_UPPER_GLOVES; } break; @@ -585,13 +585,13 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_JACKET: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_JACKET; + result = LLAvatarAppearanceDefines::TEX_LOWER_JACKET; } - else if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + else if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_JACKET; + result = LLAvatarAppearanceDefines::TEX_UPPER_JACKET; } break; @@ -599,9 +599,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_PANTS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_PANTS; + result = LLAvatarAppearanceDefines::TEX_LOWER_PANTS; } break; @@ -609,9 +609,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SHIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_SHIRT; + result = LLAvatarAppearanceDefines::TEX_UPPER_SHIRT; } break; @@ -619,9 +619,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SHOES: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_SHOES; + result = LLAvatarAppearanceDefines::TEX_LOWER_SHOES; } break; @@ -631,20 +631,20 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_HEAD_BODYPAINT; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_LOWER_BODYPAINT; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_UPPER_BODYPAINT; break; } @@ -659,9 +659,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SKIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_SKIRT) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_SKIRT) { - result = LLVOAvatarDefines::TEX_SKIRT; + result = LLAvatarAppearanceDefines::TEX_SKIRT; } break; @@ -669,9 +669,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SOCKS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_SOCKS; + result = LLAvatarAppearanceDefines::TEX_LOWER_SOCKS; } break; @@ -681,20 +681,20 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_TATTOO; + result = LLAvatarAppearanceDefines::TEX_HEAD_TATTOO; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_TATTOO; + result = LLAvatarAppearanceDefines::TEX_LOWER_TATTOO; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_TATTOO; + result = LLAvatarAppearanceDefines::TEX_UPPER_TATTOO; break; } @@ -709,9 +709,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_UNDERPANTS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_UNDERPANTS; + result = LLAvatarAppearanceDefines::TEX_LOWER_UNDERPANTS; } break; @@ -719,9 +719,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_UNDERSHIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_UNDERSHIRT; + result = LLAvatarAppearanceDefines::TEX_UPPER_UNDERSHIRT; } break; diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index 7a23c7ef6e..580b6dfa7e 100755 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -28,11 +28,14 @@ #ifndef LL_LOCALBITMAPS_H #define LL_LOCALBITMAPS_H +#include "llavatarappearancedefines.h" #include "lleventtimer.h" +#include "llimage.h" +#include "llpointer.h" #include "llwearabletype.h" -#include "llvoavatardefines.h" class LLScrollListCtrl; +class LLViewerObject; class LLLocalBitmap { @@ -63,7 +66,7 @@ class LLLocalBitmap void updateUserPrims(LLUUID old_id, LLUUID new_id); void updateUserSculpts(LLUUID old_id, LLUUID new_id); void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type); - LLVOAvatarDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind); + LLAvatarAppearanceDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind); private: /* private enums */ enum ELinkStatus diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 8d9d70b50e..5022dba934 100755 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -1217,11 +1217,11 @@ void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon) case SCRIPTS_ICON: { LLViewerRegion* region = gAgent.getRegion(); - if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) + if(region && region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsStopped"); } - else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) + else if(region && region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsNotRunning"); } diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index 9ec5d7c20c..a7d6cb5eac 100755 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -53,7 +53,7 @@ #include "llresmgr.h" #include "pipeline.h" #include "llglheaders.h" - +#include "lluiimage.h" // Local constants... const S32 VERTICAL_OFFSET = 50; diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 826e8d560a..d79f1040bb 100755 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1689,7 +1689,6 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y ) return; } - LLQuaternion object_rot = first_object->getRenderRotation(); LLVector3 rotation_center = gAgent.getPosAgentFromGlobal(mRotationCenter); LLVector3 mouse_dir_x; LLVector3 mouse_dir_y; diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 00a0bf8894..ae0884ac5d 100755 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -1191,9 +1191,6 @@ void LLManipScale::dragFace( S32 x, S32 y ) mInSnapRegime = FALSE; } - BOOL send_scale_update = FALSE; - BOOL send_position_update = FALSE; - LLVector3 dir_agent; if( part_dir_local.mV[VX] ) { @@ -1210,8 +1207,6 @@ void LLManipScale::dragFace( S32 x, S32 y ) stretchFace( projected_vec(drag_start_dir_f, dir_agent) + drag_start_center_agent, projected_vec(drag_delta, dir_agent)); - send_position_update = TRUE; - send_scale_update = TRUE; mDragPointGlobal = drag_point_global; } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 362308c176..b62db70ec8 100755 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -485,7 +485,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } // Throttle updates to 10 per second. - BOOL send_update = FALSE; LLVector3 axis_f; LLVector3d axis_d; @@ -702,11 +701,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) LLVector3 old_position_local = object->getPosition(); LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); - // move and clamp root object first, before adjusting children - if (new_position_local != old_position_local) - { - send_update = TRUE; - } //RN: I forget, but we need to do this because of snapping which doesn't often result // in position changes even when the mouse moves object->setPosition(new_position_local); @@ -716,8 +710,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) if (selectNode->mIndividualSelection) { - send_update = FALSE; - // counter-translate child objects if we are moving the root as an individual object->resetChildrenPosition(old_position_local - new_position_local, TRUE) ; } @@ -753,7 +745,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } // PR: Only update if changed - LLVector3d old_position_global = object->getPositionGlobal(); LLVector3 old_position_agent = object->getPositionAgent(); LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); if (object->isRootEdit()) @@ -775,11 +766,6 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) { // counter-translate child objects if we are moving the root as an individual object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE) ; - send_update = FALSE; - } - else if (old_position_global != new_position_global) - { - send_update = TRUE; } } selectNode->mLastPositionLocal = object->getPosition(); @@ -1310,7 +1296,6 @@ void LLManipTranslate::renderSnapGuides() // add in off-axis offset tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); - BOOL is_sub_tick = FALSE; F32 tick_scale = 1.f; for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) { @@ -1319,7 +1304,6 @@ void LLManipTranslate::renderSnapGuides() break; } tick_scale *= 0.7f; - is_sub_tick = TRUE; } // S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side; @@ -1542,7 +1526,6 @@ void LLManipTranslate::renderSnapGuides() float a = line_alpha; - LLColor4 col = LLUIColorTable::instance().getColor("SilhouetteChildColor"); { //draw grid behind objects LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 99b4707158..2075aeed63 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -119,8 +119,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]); setTextureSize(screen_width, screen_height); } @@ -469,8 +469,8 @@ void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)width * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)height * LLUI::getScaleFactor().mV[VY]); // when floater is minimized, these sizes are negative if ( screen_height > 0 && screen_width > 0 ) @@ -667,7 +667,7 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); if(mClearCache) { @@ -750,7 +750,7 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -864,14 +864,14 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); } - x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]); + x = llround((F32)x * LLUI::getScaleFactor().mV[VX]); if ( ! coords_opengl ) { - y = llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(y) * LLUI::getScaleFactor().mV[VY]); } else { - y = llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(getRect().getHeight() - y) * LLUI::getScaleFactor().mV[VY]); }; } diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 31038b4aac..e3b46d5d2f 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -564,7 +564,7 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request) } /*virtual*/ -void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) +void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { mRequest->stopTracking(); @@ -596,8 +596,8 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) } else { - std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; - LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *mRequest << " http error [status:" + << status << "]:" << content << ")" << LL_ENDL; } } @@ -1003,7 +1003,7 @@ LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::crea } /*virtual*/ -void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string& reason) +void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { getRequest()->stopTracking(); @@ -1017,7 +1017,7 @@ void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string // class if (status == HTTP_SERVICE_UNAVAILABLE) { - LLMediaDataClient::Responder::error(status, reason); + LLMediaDataClient::Responder::errorWithContent(status, reason, content); } else { diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index ab90915c55..89e20a28d0 100755 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -195,7 +195,7 @@ protected: public: Responder(const request_ptr_t &request); //If we get back an error (not found, etc...), handle it here - virtual void error(U32 status, const std::string& reason); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); //If we get back a normal response, handle it here. Default just logs it. virtual void result(const LLSD& content); @@ -400,7 +400,7 @@ protected: public: Responder(const request_ptr_t &request) : LLMediaDataClient::Responder(request) {} - virtual void error(U32 status, const std::string& reason); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); virtual void result(const LLSD &content); private: void mediaNavigateBounceBack(); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1223615079..17311dd75e 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3222,6 +3222,7 @@ void LLPhysicsDecomp::doDecomposition() param_map[params[i].mName] = params+i; } + U32 ret = LLCD_OK; //set parameter values for (decomp_params::iterator iter = mCurRequest->mParams.begin(); iter != mCurRequest->mParams.end(); ++iter) { @@ -3235,7 +3236,6 @@ void LLPhysicsDecomp::doDecomposition() continue; } - U32 ret = LLCD_OK; if (param->mType == LLCDParam::LLCD_FLOAT) { @@ -3254,8 +3254,6 @@ void LLPhysicsDecomp::doDecomposition() mCurRequest->setStatusMessage("Executing."); - LLCDResult ret = LLCD_OK; - if (LLConvexDecomposition::getInstance() != NULL) { ret = LLConvexDecomposition::getInstance()->executeStage(stage); diff --git a/indra/newview/llmorphview.cpp b/indra/newview/llmorphview.cpp index eaa044cb59..252d1b78ea 100755 --- a/indra/newview/llmorphview.cpp +++ b/indra/newview/llmorphview.cpp @@ -99,8 +99,6 @@ void LLMorphView::initialize() //----------------------------------------------------------------------------- void LLMorphView::shutdown() { - LLVOAvatarSelf::onCustomizeEnd(); - if (isAgentAvatarValid()) { gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 1bda7640bd..dea90b9042 100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -150,7 +150,7 @@ void LLNetMap::draw() static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white); static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white); - static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white); + //static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white); static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white); static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white); diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index a346909027..0682af1278 100755 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -31,7 +31,7 @@ #include "../llui/llview.h" #include "llmutelist.h" #include "llspeakingindicatormanager.h" -#include "../llui/lluiimage.h" +//#include "../llui/lluiimage.h" class LLTextBox; class LLUICtrlFactory; diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 6889b98ab1..862e4be203 100755 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -55,6 +55,7 @@ #include "lltrans.h" #include "llscrollcontainer.h" #include "llstatusbar.h" +#include "llviewertexture.h" const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 77e1487f38..1a427338e5 100755 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -78,8 +78,6 @@ const char* LLPanelContents::PERMS_ANYONE_CONTROL_KEY = "perms_anyone_control"; BOOL LLPanelContents::postBuild() { - LLRect rect = this->getRect(); - setMouseOpaque(FALSE); childSetAction("button new script",&LLPanelContents::onClickNewScript, this); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 6b9edcb07c..e71dba5cae 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -28,7 +28,7 @@ #include "llpaneleditwearable.h" #include "llpanel.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "lluictrl.h" #include "llscrollingpanellist.h" #include "llvisualparam.h" @@ -52,6 +52,7 @@ #include "lltexturectrl.h" #include "lltextureentry.h" #include "llviewercontrol.h" // gSavedSettings +#include "llviewerregion.h" #include "llviewertexturelist.h" #include "llagentcamera.h" #include "llmorphview.h" @@ -104,7 +105,7 @@ enum ESubpart { SUBPART_PHYSICS_ADVANCED, }; -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; typedef std::vector<ESubpart> subpart_vec_t; @@ -718,8 +719,8 @@ BOOL LLPanelEditWearable::postBuild() mBtnBack = getChild<LLButton>("back_btn"); mBackBtnLabel = mBtnBack->getLabelUnselected(); mBtnBack->setLabel(LLStringUtil::null); - // handled at appearance panel level? - //mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); + + mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); mNameEditor = getChild<LLLineEditor>("description"); @@ -762,11 +763,11 @@ BOOL LLPanelEditWearable::postBuild() mWearablePtr = NULL; - configureAlphaCheckbox(LLVOAvatarDefines::TEX_LOWER_ALPHA, "lower alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_UPPER_ALPHA, "upper alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_HEAD_ALPHA, "head alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_EYES_ALPHA, "eye alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_LOWER_ALPHA, "lower alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_UPPER_ALPHA, "upper alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_HEAD_ALPHA, "head alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_EYES_ALPHA, "eye alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible"); // configure tab expanded callbacks for (U32 type_index = 0; type_index < (U32)LLWearableType::WT_COUNT; ++type_index) @@ -856,6 +857,14 @@ void LLPanelEditWearable::draw() LLPanel::draw(); } +void LLPanelEditWearable::onClose() +{ + if ( isDirty() ) + { + revertChanges(); + } +} + void LLPanelEditWearable::setVisible(BOOL visible) { if (!visible) @@ -865,13 +874,22 @@ void LLPanelEditWearable::setVisible(BOOL visible) LLPanel::setVisible(visible); } -void LLPanelEditWearable::setWearable(LLWearable *wearable, BOOL disable_camera_switch) +void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_camera_switch) { showWearable(mWearablePtr, FALSE, disable_camera_switch); mWearablePtr = wearable; showWearable(mWearablePtr, TRUE, disable_camera_switch); } +//static +void LLPanelEditWearable::onBackButtonClicked(void* userdata) +{ + LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; + if ( panel->isDirty() ) + { + LLAppearanceMgr::instance().setOutfitDirty( true ); + } +} //static void LLPanelEditWearable::onRevertButtonClicked(void* userdata) @@ -922,7 +940,7 @@ void LLPanelEditWearable::onCommitSexChange() } bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; - LLWearable* wearable = gAgentWearables.getWearable(type, index); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); if (wearable) { wearable->setVisualParamWeight(param->getID(), is_new_sex_male, FALSE); @@ -1007,13 +1025,11 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) return; bool is_modifiable = false; - bool is_copyable = false; if(mWearableItem) { const LLPermissions& perm = mWearableItem->getPermissions(); is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); - is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()); } if (is_modifiable) @@ -1030,6 +1046,11 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) } } +void LLPanelEditWearable::incrementCofVersionLegacy() +{ + +} + void LLPanelEditWearable::saveChanges(bool force_save_as) { if (!mWearablePtr || !isDirty()) @@ -1041,17 +1062,50 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) U32 index = gAgentWearables.getWearableIndex(mWearablePtr); std::string new_name = mNameEditor->getText(); + + // Find an existing link to this wearable's inventory item, if any, and its description field. + LLInventoryItem *link_item = NULL; + std::string description; + LLInventoryModel::item_array_t links = + LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); + if (links.size()>0) + { + link_item = links.get(0).get(); + if (link_item && link_item->getIsLinkType()) + { + description = link_item->getActualDescription(); + } + } + if (force_save_as) { // the name of the wearable has changed, re-save wearable with new name - LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),false); - gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, FALSE); + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); + gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); mNameEditor->setText(mWearableItem->getName()); } else { + // Make another copy of this link, with the same + // description. This is needed to bump the COF + // version so texture baking service knows appearance has changed. + if (link_item) + { + // Create new link + link_inventory_item( gAgent.getID(), + link_item->getLinkedUUID(), + LLAppearanceMgr::instance().getCOF(), + link_item->getName(), + description, + LLAssetType::AT_LINK, + NULL); + // Remove old link + gInventory.purgeObject(link_item->getUUID()); + } gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } + + } void LLPanelEditWearable::revertChanges() @@ -1069,7 +1123,7 @@ void LLPanelEditWearable::revertChanges() gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE); } -void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch) +void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch) { if (!wearable) { @@ -1440,12 +1494,11 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value { panel_list->clearPanels(); value_map_t::iterator end = sorted_params.end(); - S32 height = 0; for(value_map_t::iterator it = sorted_params.begin(); it != end; ++it) { LLPanel::Params p; p.name("LLScrollingPanelParam"); - LLWearable *wearable = this->getWearable(); + LLViewerWearable *wearable = this->getWearable(); LLScrollingPanelParamBase *panel_param = NULL; if (wearable && wearable->getType() == LLWearableType::WT_PHYSICS) // Hack to show a different panel for physics. Should generalize this later. { @@ -1455,7 +1508,7 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value { panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp); } - height = panel_list->addPanel( panel_param ); + panel_list->addPanel( panel_param ); } } } @@ -1505,7 +1558,7 @@ void LLPanelEditWearable::updateVerbs() } } -void LLPanelEditWearable::configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name) +void LLPanelEditWearable::configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name) { LLCheckBoxCtrl* checkbox = mPanelAlpha->getChild<LLCheckBoxCtrl>(name); checkbox->setCommitCallback(boost::bind(&LLPanelEditWearable::onInvisibilityCommit, this, checkbox, te)); @@ -1513,7 +1566,7 @@ void LLPanelEditWearable::configureAlphaCheckbox(LLVOAvatarDefines::ETextureInde mAlphaCheckbox2Index[name] = te; } -void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te) +void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te) { if (!checkbox_ctrl) return; if (!getWearable()) return; @@ -1557,7 +1610,7 @@ void LLPanelEditWearable::updateAlphaCheckboxes() for(string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin(); iter != mAlphaCheckbox2Index.end(); ++iter ) { - LLVOAvatarDefines::ETextureIndex te = (LLVOAvatarDefines::ETextureIndex)iter->second; + LLAvatarAppearanceDefines::ETextureIndex te = (LLAvatarAppearanceDefines::ETextureIndex)iter->second; LLCheckBoxCtrl* ctrl = mPanelAlpha->getChild<LLCheckBoxCtrl>(iter->first); if (ctrl) { @@ -1575,7 +1628,7 @@ void LLPanelEditWearable::initPreviousAlphaTextures() initPreviousAlphaTextureEntry(TEX_LOWER_ALPHA); } -void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te) +void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefines::ETextureIndex te) { LLLocalTextureObject *lto = getWearable()->getLocalTextureObject(te); if (lto) diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 692a7ce90f..6533d55f2f 100755 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -30,12 +30,12 @@ #include "llpanel.h" #include "llscrollingpanellist.h" #include "llmodaldialog.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "llwearabletype.h" class LLAccordionCtrl; class LLCheckBoxCtrl; -class LLWearable; +class LLViewerWearable; class LLTextBox; class LLViewerInventoryItem; class LLViewerVisualParam; @@ -54,12 +54,13 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ BOOL isDirty() const; // LLUICtrl /*virtual*/ void draw(); + void onClose(); // changes camera angle to default for selected subpart void changeCamera(U8 subpart); - LLWearable* getWearable() { return mWearablePtr; } - void setWearable(LLWearable *wearable, BOOL disable_camera_switch = FALSE); + LLViewerWearable* getWearable() { return mWearablePtr; } + void setWearable(LLViewerWearable *wearable, BOOL disable_camera_switch = FALSE); void saveChanges(bool force_save_as = false); void revertChanges(); @@ -70,17 +71,17 @@ public: void updateScrollingPanelList(); static void onRevertButtonClicked(void* userdata); + static void onBackButtonClicked(void* userdata); void onCommitSexChange(); void onSaveAsButtonClicked(); void saveAsCallback(const LLSD& notification, const LLSD& response); virtual void setVisible(BOOL visible); - private: typedef std::map<F32, LLViewerVisualParam*> value_map_t; - void showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE); + void showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE); void updateScrollingPanelUI(); LLPanel* getPanel(LLWearableType::EType type); void getSortedParams(value_map_t &sorted_params, const std::string &edit_group); @@ -94,17 +95,17 @@ private: void toggleTypeSpecificControls(LLWearableType::EType type); void updateTypeSpecificControls(LLWearableType::EType type); - //alpha mask checkboxes - void configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name); - void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te); + // alpha mask checkboxes + void configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name); + void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te); void updateAlphaCheckboxes(); void initPreviousAlphaTextures(); - void initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te); + void initPreviousAlphaTextureEntry(LLAvatarAppearanceDefines::ETextureIndex te); // callback for HeightUnits parameter. bool changeHeightUnits(const LLSD& new_value); - // updates current metric and replacemet metric label text + // updates current metric and replacement metric label text void updateMetricLayout(BOOL new_value); // updates avatar height label @@ -114,8 +115,11 @@ private: void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel); + // *HACK Remove this when serverside texture baking is available on all regions. + void incrementCofVersionLegacy(); + // the pointer to the wearable we're editing. NULL means we're not editing a wearable. - LLWearable *mWearablePtr; + LLViewerWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; // these are constant no matter what wearable we're editing @@ -128,7 +132,7 @@ private: LLTextBox *mTxtAvatarHeight; - // localized and parametrized strings that used to build avatar_height_label + // localized and parameterized strings that used to build avatar_height_label std::string mMeters; std::string mFeet; std::string mHeigth; @@ -151,7 +155,7 @@ private: LLPanel *mPanelEyes; LLPanel *mPanelHair; - //clothes + // clothes LLPanel *mPanelShirt; LLPanel *mPanelPants; LLPanel *mPanelShoes; @@ -165,10 +169,10 @@ private: LLPanel *mPanelTattoo; LLPanel *mPanelPhysics; - typedef std::map<std::string, LLVOAvatarDefines::ETextureIndex> string_texture_index_map_t; + typedef std::map<std::string, LLAvatarAppearanceDefines::ETextureIndex> string_texture_index_map_t; string_texture_index_map_t mAlphaCheckbox2Index; - typedef std::map<LLVOAvatarDefines::ETextureIndex, LLUUID> s32_uuid_map_t; + typedef std::map<LLAvatarAppearanceDefines::ETextureIndex, LLUUID> s32_uuid_map_t; s32_uuid_map_t mPreviousAlphaTexture; }; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 202be9671b..445c0d811f 100755 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -84,7 +84,6 @@ BOOL LLPanelFace::postBuild() childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this); childSetAction("button align",&LLPanelFace::onClickAutoFix,this); - LLRect rect = this->getRect(); LLTextureCtrl* mTextureCtrl; LLColorSwatchCtrl* mColorSwatch; diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 37755fb851..c927aeacb3 100755 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -1383,13 +1383,11 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg, S32 cur_land_tax; S32 cur_group_tax; S32 cur_parcel_dir_fee; - S32 cur_total_tax; S32 proj_object_tax; S32 proj_light_tax; S32 proj_land_tax; S32 proj_group_tax; S32 proj_parcel_dir_fee; - S32 proj_total_tax; S32 non_exempt_members; msg->getS32Fast(_PREHASH_MoneyData, _PREHASH_IntervalDays, interval_days ); @@ -1413,8 +1411,6 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg, msg->getStringFast(_PREHASH_MoneyData, _PREHASH_LastTaxDate, last_stipend_date); msg->getStringFast(_PREHASH_MoneyData, _PREHASH_TaxDate, next_stipend_date); - cur_total_tax = cur_object_tax + cur_light_tax + cur_land_tax + cur_group_tax + cur_parcel_dir_fee; - proj_total_tax = proj_object_tax + proj_light_tax + proj_land_tax + proj_group_tax + proj_parcel_dir_fee; if (interval_days != mImplementationp->mIntervalLength || current_interval != mImplementationp->mCurrentInterval) diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 93b108efcc..522ba5afae 100755 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -35,6 +35,7 @@ #include "llviewerinventory.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llagent.h" diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp index 04c1a86f69..5321ebc777 100755 --- a/indra/newview/llpanelland.cpp +++ b/indra/newview/llpanelland.cpp @@ -166,7 +166,7 @@ void LLPanelLandInfo::refresh() getChildView("button abandon land")->setEnabled(owner_release || manager_releaseable || gAgent.isGodlike()); // only mainland sims are subdividable by owner - if (regionp->getRegionFlags() && REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (regionp->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) { getChildView("button subdivide land")->setEnabled(owner_divide || manager_divideable || gAgent.isGodlike()); } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index c57746ec00..5c9b968ac9 100755 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -209,24 +209,6 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); } - S32 region_x; - S32 region_y; - S32 region_z; - - // If the region position is zero, grab position from the global - if(mPosRegion.isExactlyZero()) - { - region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; - region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; - region_z = llround(parcel_data.global_z); - } - else - { - region_x = llround(mPosRegion.mV[VX]); - region_y = llround(mPosRegion.mV[VY]); - region_z = llround(mPosRegion.mV[VZ]); - } - LLSD info; info["update_verbs"] = true; info["global_x"] = parcel_data.global_x; diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index d87b565b32..25ef9a3d6a 100755 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -439,10 +439,9 @@ void LLPanelObject::getState( ) mCtrlRotY->setEnabled( enable_rotate ); mCtrlRotZ->setEnabled( enable_rotate ); - BOOL owners_identical; LLUUID owner_id; std::string owner_name; - owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); + LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); // BUG? Check for all objects being editable? S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 7555ac7b2c..d7130820ab 100755 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -47,6 +47,7 @@ #include "llfolderview.h" #include "llinventorybridge.h" #include "llinventorydefines.h" +#include "llinventoryicon.h" #include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llpreviewanim.h" diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index e641370d2e..131e8e9359 100755 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -365,10 +365,8 @@ void LLPanelPermissions::refresh() // Update creator text field getChildView("Creator:")->setEnabled(TRUE); - BOOL creators_identical; std::string creator_name; - creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, - creator_name); + LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); getChild<LLUICtrl>("Creator Name")->setValue(creator_name); getChildView("Creator Name")->setEnabled(TRUE); diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 83b70d9f29..5d9971c16c 100755 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -568,7 +568,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, mTerraformLimitsText->setText(parcel->getAllowTerraform() ? on : off); - if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) { mSubdivideText->setText(getString("can_change")); } @@ -576,7 +576,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, { mSubdivideText->setText(getString("can_not_change")); } - if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) { mResaleText->setText(getString("can_not_resell")); } diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index 343c140bbb..9dd665198f 100755 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -417,11 +417,11 @@ void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon) case SCRIPTS_ICON: { LLViewerRegion* region = gAgent.getRegion(); - if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) + if(region && region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsStopped"); } - else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) + else if(region && region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsNotRunning"); } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 13b746dbab..02d363d795 100755 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -252,10 +252,9 @@ void LLPanelVolume::getState( ) return; } - BOOL owners_identical; LLUUID owner_id; std::string owner_name; - owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); + LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); // BUG? Check for all objects being editable? BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 3b9934d4be..aa3ed22bee 100755 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -77,11 +77,7 @@ private: { uuid_vec_t selected_uuids; mPanelWearing->getSelectedItemsUUIDs(selected_uuids); - - for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it) - { - LLAppearanceMgr::instance().removeItemFromAvatar(*it); - } + LLAppearanceMgr::instance().removeItemsFromAvatar(selected_uuids); } LLToggleableMenu* mMenu; @@ -97,12 +93,11 @@ protected: { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1); - registrar.add("Wearing.Edit", boost::bind(&edit_outfit)); - registrar.add("Wearing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs)); - registrar.add("Wearing.Detach", boost::bind(handleMultiple, take_off, mUUIDs)); - + registrar.add("Wearing.TakeOff", + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + registrar.add("Wearing.Detach", + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); LLContextMenu* menu = createFromFile("menu_wearing_tab.xml"); updateMenuItemsVisibility(menu); diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index 2dd01e931e..c277359133 100755 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -108,7 +108,7 @@ public: virtual ~NavMeshStatusResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); protected: @@ -130,7 +130,7 @@ public: virtual ~NavMeshResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); protected: @@ -151,7 +151,7 @@ public: virtual ~AgentStateResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); protected: @@ -170,7 +170,7 @@ public: virtual ~NavMeshRebakeResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string& pReason); + virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); protected: @@ -190,9 +190,11 @@ public: virtual ~LinksetsResponder(); void handleObjectLinksetsResult(const LLSD &pContent); - void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL); + void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, + const LLSD& pContent, const std::string &pURL); void handleTerrainLinksetsResult(const LLSD &pContent); - void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL); + void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, + const LLSD& pContent, const std::string &pURL); protected: @@ -230,7 +232,7 @@ public: virtual ~ObjectLinksetsResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string &pReason); + virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); protected: @@ -250,7 +252,7 @@ public: virtual ~TerrainLinksetsResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string &pReason); + virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); protected: @@ -270,7 +272,7 @@ public: virtual ~CharactersResponder(); virtual void result(const LLSD &pContent); - virtual void error(U32 pStatus, const std::string &pReason); + virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); protected: @@ -800,9 +802,9 @@ void NavMeshStatusResponder::result(const LLSD &pContent) LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } -void NavMeshStatusResponder::error(U32 pStatus, const std::string& pReason) +void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) { - llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "NavMeshStatusResponder error [status:" << pStatus << "]: " << pContent << llendl; LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID); LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } @@ -828,9 +830,9 @@ void NavMeshResponder::result(const LLSD &pContent) mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion); } -void NavMeshResponder::error(U32 pStatus, const std::string& pReason) +void NavMeshResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) { - mNavMeshPtr->handleNavMeshError(pStatus, pReason, mCapabilityURL, mNavMeshVersion); + mNavMeshPtr->handleNavMeshError(pStatus, pReason, pContent, mCapabilityURL, mNavMeshVersion); } //--------------------------------------------------------------------------- @@ -855,9 +857,9 @@ void AgentStateResponder::result(const LLSD &pContent) LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); } -void AgentStateResponder::error(U32 pStatus, const std::string &pReason) +void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) { - llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "AgentStateResponder error [status:" << pStatus << "]: " << pContent << llendl; LLPathfindingManager::getInstance()->handleAgentState(FALSE); } @@ -881,9 +883,9 @@ void NavMeshRebakeResponder::result(const LLSD &pContent) mRebakeNavMeshCallback(true); } -void NavMeshRebakeResponder::error(U32 pStatus, const std::string &pReason) +void NavMeshRebakeResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) { - llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "NavMeshRebakeResponder error [status:" << pStatus << "]: " << pContent << llendl; mRebakeNavMeshCallback(false); } @@ -916,9 +918,11 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL) +void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason, + const LLSD& pContent, const std::string &pURL) { - llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:" + << pStatus << "]: " << pContent << llendl; mObjectMessagingState = kReceivedError; if (mTerrainMessagingState != kWaiting) { @@ -937,8 +941,11 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL) +void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, + const LLSD& pContent, const std::string &pURL) { + llwarns << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:" + << pStatus << "]: " << pContent << llendl; mTerrainMessagingState = kReceivedError; if (mObjectMessagingState != kWaiting) { @@ -988,9 +995,9 @@ void ObjectLinksetsResponder::result(const LLSD &pContent) mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent); } -void ObjectLinksetsResponder::error(U32 pStatus, const std::string &pReason) +void ObjectLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) { - mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, mCapabilityURL); + mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, pContent, mCapabilityURL); } //--------------------------------------------------------------------------- @@ -1013,9 +1020,9 @@ void TerrainLinksetsResponder::result(const LLSD &pContent) mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent); } -void TerrainLinksetsResponder::error(U32 pStatus, const std::string &pReason) +void TerrainLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) { - mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, mCapabilityURL); + mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, pContent, mCapabilityURL); } //--------------------------------------------------------------------------- @@ -1040,9 +1047,9 @@ void CharactersResponder::result(const LLSD &pContent) mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr); } -void CharactersResponder::error(U32 pStatus, const std::string &pReason) +void CharactersResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) { - llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "CharactersResponder error [status:" << pStatus << "]: " << pContent << llendl; LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList()); mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr); diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp index e01dd3a152..0c23e5ac92 100755 --- a/indra/newview/llpathfindingnavmesh.cpp +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -184,9 +184,10 @@ void LLPathfindingNavMesh::handleNavMeshError() setRequestStatus(kNavMeshRequestError); } -void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion) +void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion) { - llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + llwarns << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:" + << pStatus << "]: " << pContent << llendl; if (mNavMeshStatus.getVersion() == pNavMeshVersion) { handleNavMeshError(); diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h index 7a844f54ce..b872ccad7c 100755 --- a/indra/newview/llpathfindingnavmesh.h +++ b/indra/newview/llpathfindingnavmesh.h @@ -74,7 +74,7 @@ public: void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion); void handleNavMeshNotEnabled(); void handleNavMeshError(); - void handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion); + void handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion); protected: diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index cb6989c9dd..3ee0746412 100755 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -166,7 +166,7 @@ protected: } - void setParamValue(LLViewerVisualParam *param, + void setParamValue(const LLViewerVisualParam *param, const F32 new_value_local, F32 behavior_maxeffect); @@ -428,14 +428,13 @@ F32 LLPhysicsMotion::toLocal(const LLVector3 &world) F32 LLPhysicsMotion::calculateVelocity_local() { const F32 world_to_model_scale = 100.0f; - LLJoint *joint = mJointState->getJoint(); - const LLVector3 position_world = joint->getWorldPosition(); - const LLQuaternion rotation_world = joint->getWorldRotation(); - const LLVector3 last_position_world = mPosition_world; + LLJoint *joint = mJointState->getJoint(); + const LLVector3 position_world = joint->getWorldPosition(); + const LLVector3 last_position_world = mPosition_world; const LLVector3 positionchange_world = (position_world-last_position_world) * world_to_model_scale; - const LLVector3 velocity_world = positionchange_world; - const F32 velocity_local = toLocal(velocity_world); - return velocity_local; + const LLVector3 velocity_world = positionchange_world; + const F32 velocity_local = toLocal(velocity_world); + return velocity_local; } F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local) @@ -673,12 +672,10 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) 0, FALSE); } - for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); - iter != driver_param->mDriven.end(); - ++iter) + S32 num_driven = driver_param->getDrivenParamsCount(); + for (S32 i = 0; i < num_driven; ++i) { - LLDrivenEntry &entry = (*iter); - LLViewerVisualParam *driven_param = entry.mParam; + const LLViewerVisualParam *driven_param = driver_param->getDrivenParam(i); setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); } } @@ -758,7 +755,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) } // Range of new_value_local is assumed to be [0 , 1] normalized. -void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param, +void LLPhysicsMotion::setParamValue(const LLViewerVisualParam *param, F32 new_value_normalized, F32 behavior_maxeffect) { diff --git a/indra/newview/llpipelinelistener.cpp b/indra/newview/llpipelinelistener.cpp new file mode 100644 index 0000000000..20759239bf --- /dev/null +++ b/indra/newview/llpipelinelistener.cpp @@ -0,0 +1,216 @@ +/** + * @file llpipelinelistener.h + * @author Don Kjer + * @date 2012-07-09 + * @brief Implementation for LLPipelineListener + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" + +#include "llpipelinelistener.h" + +#include "pipeline.h" +#include "stringize.h" +#include <sstream> +#include "llviewermenu.h" + + +namespace { + // Render Types + void toggle_render_types_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["types"].beginArray(); + iter != request["types"].endArray(); + ++iter) + { + U32 render_type = render_type_from_string( iter->asString() ); + if ( render_type != 0 ) + { + LLPipeline::toggleRenderTypeControl( (void*) render_type ); + } + } + } + + void has_render_type_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 render_type = render_type_from_string( request["type"].asString() ); + if ( render_type != 0 ) + { + response["value"] = LLPipeline::hasRenderTypeControl( (void*) render_type ); + } + else + { + response.error(STRINGIZE("unknown type '" << request["type"].asString() << "'")); + } + } + + void disable_all_render_types_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderTypes(); + } + + void enable_all_render_types_wrapper(LLSD const& request) + { + gPipeline.setAllRenderTypes(); + } + + // Render Features + void toggle_render_features_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["features"].beginArray(); + iter != request["features"].endArray(); + ++iter) + { + U32 render_feature = feature_from_string( iter->asString() ); + if ( render_feature != 0 ) + { + LLPipeline::toggleRenderDebugControl( (void*) render_feature ); + } + } + } + + void has_render_feature_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 render_feature = feature_from_string( request["feature"].asString() ); + if ( render_feature != 0 ) + { + response["value"] = gPipeline.hasRenderDebugFeatureMask(render_feature); + } + else + { + response.error(STRINGIZE("unknown feature '" << request["feature"].asString() << "'")); + } + } + + void disable_all_render_features_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderDebugFeatures(); + } + + void enable_all_render_features_wrapper(LLSD const& request) + { + gPipeline.setAllRenderDebugFeatures(); + } + + // Render Info Displays + void toggle_info_displays_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["displays"].beginArray(); + iter != request["displays"].endArray(); + ++iter) + { + U32 info_display = info_display_from_string( iter->asString() ); + if ( info_display != 0 ) + { + LLPipeline::toggleRenderDebug( (void*) info_display ); + } + } + } + + void has_info_display_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 info_display = info_display_from_string( request["display"].asString() ); + if ( info_display != 0 ) + { + response["value"] = gPipeline.hasRenderDebugMask(info_display); + } + else + { + response.error(STRINGIZE("unknown display '" << request["display"].asString() << "'")); + } + } + + void disable_all_info_displays_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderDebugDisplays(); + } + + void enable_all_info_displays_wrapper(LLSD const& request) + { + gPipeline.setAllRenderDebugDisplays(); + } + +} + + +LLPipelineListener::LLPipelineListener(): + LLEventAPI("LLPipeline", + "API to te rendering pipeline.") +{ + // Render Types + add("toggleRenderTypes", + "Toggle rendering [\"types\"]:\n" + "See: llviewermenu.cpp:render_type_from_string for list of available types.", + &toggle_render_types_wrapper); + add("hasRenderType", + "Check if rendering [\"type\"] is enabled:\n" + "See: llviewermenu.cpp:render_type_from_string for list of available types.", + &has_render_type_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderTypes", + "Turn off all rendering types.", + &disable_all_render_types_wrapper); + add("enableAllRenderTypes", + "Turn on all rendering types.", + &enable_all_render_types_wrapper); + + // Render Features + add("toggleRenderFeatures", + "Toggle rendering [\"features\"]:\n" + "See: llviewermenu.cpp:feature_from_string for list of available features.", + &toggle_render_features_wrapper); + add("hasRenderFeature", + "Check if rendering [\"feature\"] is enabled:\n" + "See: llviewermenu.cpp:render_feature_from_string for list of available features.", + &has_render_feature_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderFeatures", + "Turn off all rendering features.", + &disable_all_render_features_wrapper); + add("enableAllRenderFeatures", + "Turn on all rendering features.", + &enable_all_render_features_wrapper); + + // Render Info Displays + add("toggleRenderInfoDisplays", + "Toggle info [\"displays\"]:\n" + "See: llviewermenu.cpp:info_display_from_string for list of available displays.", + &toggle_info_displays_wrapper); + add("hasRenderInfoDisplay", + "Check if info [\"display\"] is enabled:\n" + "See: llviewermenu.cpp:info_display_from_string for list of available displays.", + &has_info_display_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderInfoDisplays", + "Turn off all info displays.", + &disable_all_info_displays_wrapper); + add("enableAllRenderInfoDisplays", + "Turn on all info displays.", + &enable_all_info_displays_wrapper); +} + diff --git a/indra/newview/llpipelinelistener.h b/indra/newview/llpipelinelistener.h new file mode 100644 index 0000000000..da1898e57b --- /dev/null +++ b/indra/newview/llpipelinelistener.h @@ -0,0 +1,41 @@ +/** + * @file llpipelinelistener.h + * @author Don Kjer + * @date 2012-07-09 + * @brief Wrap subset of LLPipeline API in event API + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLPIPELINELISTENER_H) +#define LL_LLPIPELINELISTENER_H + +#include "lleventapi.h" + +/// Listen on an LLEventPump with specified name for LLPipeline request events. +class LLPipelineListener: public LLEventAPI +{ +public: + LLPipelineListener(); +}; + +#endif /* ! defined(LL_LLPIPELINELISTENER_H) */ diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp index 4f2d6da7e5..aebe636f59 100755 --- a/indra/newview/llpostcard.cpp +++ b/indra/newview/llpostcard.cpp @@ -35,6 +35,7 @@ #include "message.h" #include "llagent.h" +#include "llassetstorage.h" #include "llassetuploadresponders.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 3ff5a05d81..91a98792eb 100755 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -70,7 +70,7 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mAspectRatio(0.f), mPreviewToSave(FALSE), mImage(NULL), - mImageOldBoostLevel(LLViewerTexture::BOOST_NONE) + mImageOldBoostLevel(LLGLTexture::BOOST_NONE) { updateImageID(); if (key.has("save_as")) @@ -468,9 +468,9 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) void LLPreviewTexture::loadAsset() { - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mImageOldBoostLevel = mImage->getBoostLevel(); - mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); mImage->forceToSaveRawImage(0) ; mAssetStatus = PREVIEW_ASSET_LOADING; mUpdateDimensions = TRUE; diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp index 93bf8b2328..1390000fc5 100755 --- a/indra/newview/llproductinforequest.cpp +++ b/indra/newview/llproductinforequest.cpp @@ -43,10 +43,10 @@ public: } //If we get back an error (not found, etc...), handle it here - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "LLProductInfoRequest::error(" - << status << ": " << reason << ")" << llendl; + llwarns << "LLProductInfoRequest error [status:" + << status << ":] " << content << llendl; } }; diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp index 698c4f9bb9..590e246482 100755 --- a/indra/newview/llregioninfomodel.cpp +++ b/indra/newview/llregioninfomodel.cpp @@ -119,7 +119,7 @@ void LLRegionInfoModel::sendRegionTerrain(const LLUUID& invoice) const bool LLRegionInfoModel::getUseFixedSun() const { - return mRegionFlags & REGION_FLAGS_SUN_FIXED; + return ((mRegionFlags & REGION_FLAGS_SUN_FIXED) != 0); } void LLRegionInfoModel::setUseFixedSun(bool fixed) @@ -141,7 +141,6 @@ void LLRegionInfoModel::update(LLMessageSystem* msg) msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, mSimName); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, mEstateID); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, mParentEstateID); - msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, mRegionFlags); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess, mSimAccess); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents, mAgentLimit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, mObjectBonusFactor); @@ -159,6 +158,17 @@ void LLRegionInfoModel::update(LLMessageSystem* msg) msg->getF32(_PREHASH_RegionInfo, _PREHASH_SunHour, mSunHour); LL_DEBUGS("Windlight Sync") << "Got region sun hour: " << mSunHour << LL_ENDL; + if (msg->has(_PREHASH_RegionInfo3)) + { + msg->getU64Fast(_PREHASH_RegionInfo3, _PREHASH_RegionFlagsExtended, mRegionFlags); + } + else + { + U32 flags = 0; + msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); + mRegionFlags = flags; + } + // the only reasonable way to decide if we actually have any data is to // check to see if any of these fields have nonzero sizes if (msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductSKU) > 0 || diff --git a/indra/newview/llregioninfomodel.h b/indra/newview/llregioninfomodel.h index 89efd82767..d22a0de463 100755 --- a/indra/newview/llregioninfomodel.h +++ b/indra/newview/llregioninfomodel.h @@ -52,7 +52,7 @@ public: U8 mSimAccess; U8 mAgentLimit; - U32 mRegionFlags; + U64 mRegionFlags; U32 mEstateID; U32 mParentEstateID; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 3862dac340..500dec7ee5 100755 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -62,10 +62,10 @@ void LLRemoteParcelRequestResponder::result(const LLSD& content) //If we get back an error (not found, etc...), handle it here //virtual -void LLRemoteParcelRequestResponder::error(U32 status, const std::string& reason) +void LLRemoteParcelRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llinfos << "LLRemoteParcelRequest::error(" - << status << ": " << reason << ")" << llendl; + llwarns << "LLRemoteParcelRequest error [status:" + << status << "]: " << content << llendl; // Panel inspecting the information may be closed and destroyed // before this response is received. diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index 74cf1616df..b87056573b 100755 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -44,7 +44,7 @@ public: /*virtual*/ void result(const LLSD& content); //If we get back an error (not found, etc...), handle it here - /*virtual*/ void error(U32 status, const std::string& reason); + /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: LLHandle<LLRemoteParcelInfoObserver> mObserverHandle; diff --git a/indra/newview/llsaveoutfitcombobtn.cpp b/indra/newview/llsaveoutfitcombobtn.cpp index cbad85cfd3..32295cd96f 100755 --- a/indra/newview/llsaveoutfitcombobtn.cpp +++ b/indra/newview/llsaveoutfitcombobtn.cpp @@ -76,8 +76,8 @@ void LLSaveOutfitComboBtn::saveOutfit(bool as_new) if (panel_outfits_inventory) { panel_outfits_inventory->onSave(); - } - + } + //*TODO how to get to know when base outfit is updated or new outfit is created? } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 154555b261..168a941ec3 100755 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -730,7 +730,6 @@ void LLScreenChannel::showToastsTop() LLRect toast_rect; S32 top = channel_rect.mTop; - S32 toast_margin = 0; std::vector<ToastElem>::reverse_iterator it; updateRect(); @@ -753,7 +752,7 @@ void LLScreenChannel::showToastsTop() } top = toast->getRect().mBottom - toast->getTopPad(); - toast_margin = gSavedSettings.getS32("ToastGap"); + gSavedSettings.getS32("ToastGap"); } LLToast* toast = it->getToast(); diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index 05b82ba967..a7e24b86b1 100755 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -267,7 +267,7 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint ) && new_percent < slider->getMaxValue()) { mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE); - mWearable->writeToAvatar(); + mWearable->writeToAvatar(gAgentAvatarp); gAgentAvatarp->updateVisualParams(); slider->setValue( weightToPercent( new_weight ) ); @@ -300,7 +300,7 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata ) && new_percent < slider->getMaxValue()) { self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); - self->mWearable->writeToAvatar(); + self->mWearable->writeToAvatar(gAgentAvatarp); slider->setValue( self->weightToPercent( new_weight ) ); } } @@ -334,7 +334,7 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata ) && new_percent < slider->getMaxValue()) { self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); - self->mWearable->writeToAvatar(); + self->mWearable->writeToAvatar(gAgentAvatarp); slider->setValue( self->weightToPercent( new_weight ) ); } } diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp index 62e3039d2f..8e083ddb6c 100755 --- a/indra/newview/llscrollingpanelparambase.cpp +++ b/indra/newview/llscrollingpanelparambase.cpp @@ -94,7 +94,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata) if (current_weight != new_weight ) { self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE ); - self->mWearable->writeToAvatar(); + self->mWearable->writeToAvatar(gAgentAvatarp); gAgentAvatarp->updateVisualParams(); } } diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 30400a4c6a..928d26646b 100755 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1239,7 +1239,6 @@ void LLSecAPIBasicHandler::_readProtectedData() llifstream::binary); if (!protected_data_stream.fail()) { - int offset; U8 salt[STORE_SALT_SIZE]; U8 buffer[BUFFER_READ_SIZE]; U8 decrypted_buffer[BUFFER_READ_SIZE]; @@ -1250,7 +1249,6 @@ void LLSecAPIBasicHandler::_readProtectedData() // read in the salt and key protected_data_stream.read((char *)salt, STORE_SALT_SIZE); - offset = 0; if (protected_data_stream.gcount() < STORE_SALT_SIZE) { throw LLProtectedDataException("Config file too short."); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 343316d30a..4681efd3e5 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1180,7 +1180,6 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) { //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject()); - LLBBox bbox = mSavedSelectionBBox; mGridOrigin = mSavedSelectionBBox.getCenterAgent(); mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f; @@ -1198,7 +1197,6 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & 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(); LLVector4a min_extents(F32_MAX); LLVector4a max_extents(-F32_MAX); @@ -1605,7 +1603,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) // 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, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } return true; } @@ -1771,7 +1769,7 @@ BOOL LLSelectMgr::selectionRevertTextures() } else { - object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } } @@ -5185,7 +5183,7 @@ void LLSelectMgr::updateSilhouettes() if (!mSilhouetteImagep) { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI); + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI); } mHighlightedObjects->cleanupNodes(); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index adb97ac800..74fa5a87bb 100755 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -47,7 +47,7 @@ #include "llviewercontrol.h" #include "llviewerregion.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance"); @@ -198,7 +198,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) if (is_outfit_edit_visible || is_wearable_edit_visible) { - const LLWearable *wearable_ptr = mEditWearable->getWearable(); + const LLViewerWearable *wearable_ptr = mEditWearable->getWearable(); if (!wearable_ptr) { llwarns << "Visibility change to invalid wearable" << llendl; @@ -206,12 +206,9 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) } // Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar // when editing its physics. - const BOOL disable_camera_motion = LLWearableType::getDisableCameraSwitch(wearable_ptr->getType()); - if (!gAgentCamera.cameraCustomizeAvatar() && - !disable_camera_motion && - gSavedSettings.getBOOL("AppearanceCameraMovement")) + if (!gAgentCamera.cameraCustomizeAvatar()) { - gAgentCamera.changeCameraToCustomizeAvatar(); + LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); } if (is_wearable_edit_visible) { @@ -234,7 +231,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) { gAgentCamera.changeCameraToDefault(); gAgentCamera.resetView(); - } + } } } @@ -283,7 +280,7 @@ void LLSidepanelAppearance::onEditAppearanceButtonClicked() { if (gAgentWearables.areWearablesLoaded()) { - gAgentCamera.changeCameraToCustomizeAvatar(); + LLVOAvatarSelf::onCustomizeStart(); } } @@ -329,7 +326,7 @@ void LLSidepanelAppearance::showOutfitEditPanel() toggleOutfitEditPanel(TRUE); } -void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/, BOOL disable_camera_switch) +void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) { toggleMyOutfitsPanel(FALSE); toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode @@ -371,19 +368,19 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam if (visible) { mOutfitEdit->onOpen(LLSD()); - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); } - else if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) + else { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. + { + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); + LLAppearanceMgr::getInstance()->updateIsDirty(); + } } } -void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable, BOOL disable_camera_switch) +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { if (!mEditWearable || mEditWearable->getVisible() == visible) { @@ -393,7 +390,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we if (!wearable) { - wearable = gAgentWearables.getWearable(LLWearableType::WT_SHAPE, 0); + wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); } if (!wearable) { @@ -405,10 +402,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we if (visible) { - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); mEditWearable->setWearable(wearable, disable_camera_switch); mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency } @@ -416,10 +410,10 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we { // Save changes if closing. mEditWearable->saveChanges(); - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) + LLAppearanceMgr::getInstance()->updateIsDirty(); + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); } } } @@ -453,13 +447,12 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) } //static -void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch) +void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch) { LLFloaterSidePanelContainer::showPanel("appearance", LLSD()); LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data); if (panel) { - panel->showOutfitsInventoryPanel(); panel->showWearableEditPanel(wearable, disable_camera_switch); } } diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 6dd3520266..762f557a80 100755 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -36,7 +36,7 @@ class LLFilterEditor; class LLCurrentlyWornFetchObserver; class LLPanelEditWearable; -class LLWearable; +class LLViewerWearable; class LLPanelOutfitsInventory; class LLSidepanelAppearance : public LLPanel @@ -47,11 +47,11 @@ public: virtual ~LLSidepanelAppearance(); /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onOpen(const LLSD& key); void refreshCurrentOutfitName(const std::string& name = ""); - static void editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE); + static void editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE); void fetchInventory(); void inventoryFetched(); @@ -59,11 +59,12 @@ public: void showOutfitsInventoryPanel(); void showOutfitEditPanel(); - void showWearableEditPanel(LLWearable *wearable = NULL, BOOL disable_camera_switch = FALSE); + void showWearableEditPanel(LLViewerWearable *wearable = NULL, BOOL disable_camera_switch = FALSE); void setWearablesLoading(bool val); void showDefaultSubpart(); void updateScrollingPanelList(); void updateToVisibility( const LLSD& new_visibility ); + LLPanelEditWearable* getWearable(){ return mEditWearable; } private: void onFilterEdit(const std::string& search_string); @@ -74,7 +75,7 @@ private: void toggleMyOutfitsPanel(BOOL visible); void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE); - void toggleWearableEditPanel(BOOL visible, LLWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); + void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 5532bdc71a..ad7c939728 100755 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -370,10 +370,8 @@ void LLSidepanelTaskInfo::refresh() // Update creator text field getChildView("Creator:")->setEnabled(TRUE); - BOOL creators_identical; std::string creator_name; - creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, - creator_name); + LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); getChild<LLUICtrl>("Creator Name")->setValue(creator_name); getChildView("Creator Name")->setEnabled(TRUE); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 3ed6e24498..f85e855fd3 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3544,9 +3544,9 @@ void renderTexturePriority(LLDrawable* drawable) drawBox(center, size); /*S32 boost = imagep->getBoostLevel(); - if (boost>LLViewerTexture::BOOST_NONE) + if (boost>LLGLTexture::BOOST_NONE) { - F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1); + F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); LLVector4 col = lerp(boost_cold, boost_hot, t); LLGLEnable blend_on(GL_BLEND); gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); @@ -3998,7 +3998,7 @@ void renderAgentTarget(LLVOAvatar* avatar) { renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); - renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); + renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); } } @@ -4062,9 +4062,6 @@ public: return; } - LLVector4a nodeCenter = group->mBounds[0]; - LLVector4a octCenter = group->mOctreeNode->getCenter(); - group->rebuildGeom(); group->rebuildMesh(); @@ -4539,9 +4536,6 @@ public: virtual bool check(LLDrawable* drawable) { - LLVector3 local_start = mStart; - LLVector3 local_end = mEnd; - if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) { return false; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 8783d99b11..a4582071e8 100755 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -853,7 +853,10 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) } } } - +/*prep# + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + llwarns << "ModerationResponder error [status:" << status << "]: " << content << llendl; + */ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) { LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 37e6ded986..9d5fd46a1d 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -37,8 +37,8 @@ #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" -#ifdef LL_FMOD -# include "llaudioengine_fmod.h" +#ifdef LL_FMODEX +# include "llaudioengine_fmodex.h" #endif #ifdef LL_OPENAL @@ -316,7 +316,6 @@ bool idle_startup() { const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); static LLTimer timeout; - static S32 timeout_count = 0; static LLTimer login_time; @@ -332,7 +331,6 @@ bool idle_startup() // last location by default static S32 agent_location_id = START_LOCATION_ID_LAST; - static S32 location_which = START_LOCATION_ID_LAST; static bool show_connect_box = true; @@ -625,32 +623,32 @@ bool idle_startup() { gAudiop = NULL; -#ifdef LL_OPENAL +#ifdef LL_FMODEX if (!gAudiop #if !LL_WINDOWS - && NULL == getenv("LL_BAD_OPENAL_DRIVER") + && NULL == getenv("LL_BAD_FMODEX_DRIVER") #endif // !LL_WINDOWS ) { - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable")); } #endif -#ifdef LL_FMOD +#ifdef LL_OPENAL if (!gAudiop #if !LL_WINDOWS - && NULL == getenv("LL_BAD_FMOD_DRIVER") + && NULL == getenv("LL_BAD_OPENAL_DRIVER") #endif // !LL_WINDOWS ) { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); } #endif - + if (gAudiop) { #if LL_WINDOWS - // FMOD on Windows needs the window handle to stop playing audio + // FMOD Ex on Windows needs the window handle to stop playing audio // when window is minimized. JC void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); #else @@ -744,8 +742,6 @@ bool idle_startup() gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - timeout_count = 0; - // Login screen needs menus for preferences, but we can enter // this startup phase more than once. if (gLoginMenuBarView == NULL) @@ -772,10 +768,6 @@ bool idle_startup() gUserCredential = gLoginHandler.initializeLoginInfo(); display_startup(); } - if (gHeadlessClient) - { - LL_WARNS("AppInit") << "Waiting at connection box in headless client. Did you mean to add autologin params?" << LL_ENDL; - } // Make sure the process dialog doesn't hide things display_startup(); gViewerWindow->setShowProgress(FALSE); @@ -993,15 +985,12 @@ bool idle_startup() { case LLSLURL::LOCATION: agent_location_id = START_LOCATION_ID_URL; - location_which = START_LOCATION_ID_LAST; break; case LLSLURL::LAST_LOCATION: agent_location_id = START_LOCATION_ID_LAST; - location_which = START_LOCATION_ID_LAST; break; default: agent_location_id = START_LOCATION_ID_HOME; - location_which = START_LOCATION_ID_HOME; break; } @@ -1254,6 +1243,9 @@ bool idle_startup() LLPostProcess::initClass(); display_startup(); + LLAvatarAppearance::initClass(); + display_startup(); + LLViewerObject::initVOClasses(); display_startup(); @@ -2588,12 +2580,17 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, } else { + // FIXME SH-3860 - this creates a race condition, where COF + // changes (base outfit link added) after appearance update + // request has been submitted. sWearablesLoadedCon = gAgentWearables.addLoadedCallback(LLStartUp::saveInitialOutfit); bool do_copy = true; bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); - LLAppearanceMgr::instance().wearInventoryCategory(cat, do_copy, do_append); + // Need to fetch cof contents before we can wear. + callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), + boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); lldebugs << "initial outfit category id: " << cat_id << llendl; } @@ -3455,6 +3452,14 @@ bool process_login_success_response() } + // set the location of the Agent Appearance service, from which we can request + // avatar baked textures if they are supported by the current region + std::string agent_appearance_url = response["agent_appearance_service"]; + if (!agent_appearance_url.empty()) + { + LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url); + } + // Set the location of the snapshot sharing config endpoint std::string snapshot_config_url = response["snapshot_config_url"]; if(!snapshot_config_url.empty()) @@ -3499,13 +3504,6 @@ bool process_login_success_response() void transition_back_to_login_panel(const std::string& emsg) { - if (gHeadlessClient && gSavedSettings.getBOOL("AutoLogin")) - { - LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL; - LL_WARNS("AppInit") << emsg << LL_ENDL; - exit(0); - } - // Bounce back to the login screen. reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); gSavedSettings.setBOOL("AutoLogin", FALSE); diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index ec11a23eb8..93c7f54101 100755 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -1246,8 +1246,6 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, y_end = tex_width; } - LLVector3d origin_global = from_region_handle(getRegion()->getHandle()); - // OK, for now, just have the composition value equal the height at the point. LLVector3 location; LLColor4U coloru; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 007eb8e33f..e2d0fdf357 100755 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -571,8 +571,8 @@ void LLFloaterTexturePicker::draw() mTexturep = NULL; if(mImageAssetID.notNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); - mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID); + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); } if (mTentativeLabel) @@ -1442,9 +1442,9 @@ void LLTextureCtrl::draw() } else if (!mImageAssetID.isNull()) { - LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES,LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); texture->forceToSaveRawImage(0) ; mTexturep = texture; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 7de66b139f..be5fde9e2b 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -389,7 +389,8 @@ public: virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); protected: - LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, + LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, + const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 discard, S32 size); private: @@ -501,11 +502,13 @@ private: }; static const char* sStateDescs[]; e_state mState; + void setState(e_state new_state); e_write_to_cache_state mWriteToCacheState; LLTextureFetch* mFetcher; LLPointer<LLImageFormatted> mFormattedImage; LLPointer<LLImageRaw> mRawImage; LLPointer<LLImageRaw> mAuxImage; + FTType mFTType; LLUUID mID; LLHost mHost; std::string mUrl; @@ -827,6 +830,7 @@ volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data bre // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, + FTType f_type, // Fetched image type const std::string& url, // Optional URL const LLUUID& id, // Image UUID const LLHost& host, // Simulator host @@ -838,6 +842,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mState(INIT), mWriteToCacheState(NOT_WRITE), mFetcher(fetcher), + mFTType(f_type), mID(id), mHost(host), mUrl(url), @@ -1024,7 +1029,7 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size) mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); if ((prioritize && mState == INIT) || mState == DONE) { - mState = INIT; + setState(INIT); U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; setPriority(work_priority); } @@ -1088,12 +1093,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR) { + LL_DEBUGS("Texture") << mID << " abort: mImagePriority < F_ALMOST_ZERO" << llendl; return true; // abort } } if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP) { //nowhere to get data, abort. + LL_WARNS("Texture") << mID << " abort, nowhere to get data" << llendl; return true ; } @@ -1136,7 +1143,7 @@ bool LLTextureFetchWorker::doWork(S32 param) clearPackets(); // TODO: Shouldn't be necessary mCacheReadHandle = LLTextureCache::nullHandle(); mCacheWriteHandle = LLTextureCache::nullHandle(); - mState = LOAD_FROM_TEXTURE_CACHE; + setState(LOAD_FROM_TEXTURE_CACHE); mInCache = FALSE; mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) @@ -1153,7 +1160,7 @@ bool LLTextureFetchWorker::doWork(S32 param) S32 size = mDesiredSize - offset; if (size <= 0) { - mState = CACHE_POST; + setState(CACHE_POST); return false; } mFileSize = 0; @@ -1171,6 +1178,8 @@ bool LLTextureFetchWorker::doWork(S32 param) offset, size, responder); mCacheReadTimer.reset(); } +/* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */ +/* else if ((mUrl.empty()||mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache()) */ else if (mUrl.empty() && mFetcher->canLoadFromCache()) { setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it @@ -1183,18 +1192,13 @@ bool LLTextureFetchWorker::doWork(S32 param) } else if(!mUrl.empty() && mCanUseHTTP) { - if (!(mUrl.compare(0, 7, "http://") == 0)) - { - // *TODO:?remove this warning - llwarns << "Unknown URL Type: " << mUrl << llendl; - } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = WAIT_HTTP_RESOURCE; + setState(WAIT_HTTP_RESOURCE); } else { setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = LOAD_FROM_NETWORK; + setState(LOAD_FROM_NETWORK); } } @@ -1204,7 +1208,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mFetcher->mTextureCache->readComplete(mCacheReadHandle, false)) { mCacheReadHandle = LLTextureCache::nullHandle(); - mState = CACHE_POST; + setState(CACHE_POST); // fall through } else @@ -1212,6 +1216,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // //This should never happen // + LL_DEBUGS("Texture") << mID << " this should never happen" << llendl; return false; } } @@ -1230,7 +1235,12 @@ bool LLTextureFetchWorker::doWork(S32 param) // we have enough data, decode it llassert_always(mFormattedImage->getDataSize() > 0); mLoadedDiscard = mDesiredDiscard; - mState = DECODE_IMAGE; + if (mLoadedDiscard < 0) + { + LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << llendl; + } + setState(DECODE_IMAGE); mInCache = TRUE; mWriteToCacheState = NOT_WRITE ; LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() @@ -1243,13 +1253,14 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mUrl.compare(0, 7, "file://") == 0) { // failed to load local file, we're done. + LL_WARNS("Texture") << mID << ": abort, failed to load local file " << mUrl << LL_ENDL; return true; } // need more data else { LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; - mState = LOAD_FROM_NETWORK; + setState(LOAD_FROM_NETWORK); } // fall through @@ -1290,9 +1301,15 @@ bool LLTextureFetchWorker::doWork(S32 param) mCanUseHTTP = false; } } +#if 0 /* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */ + if (mFTType == FTT_SERVER_BAKE) + { + mWriteToCacheState = CAN_WRITE; + } +#endif if (mCanUseHTTP && !mUrl.empty()) { - mState = WAIT_HTTP_RESOURCE; + setState(WAIT_HTTP_RESOURCE); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if(mWriteToCacheState != NOT_WRITE) { @@ -1322,6 +1339,8 @@ bool LLTextureFetchWorker::doWork(S32 param) //mFetcher->addToNetworkQueue(this); //recordTextureStart(false); //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + + LL_DEBUGS("Texture") << mID << " does this happen?" << llendl; return false; } } @@ -1340,10 +1359,16 @@ bool LLTextureFetchWorker::doWork(S32 param) { // processSimulatorPackets() failed // llwarns << "processSimulatorPackets() failed to load buffer" << llendl; + LL_WARNS("Texture") << mID << " processSimulatorPackets() failed to load buffer" << llendl; return true; // failed } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = DECODE_IMAGE; + if (mLoadedDiscard < 0) + { + LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << llendl; + } + setState(DECODE_IMAGE); mWriteToCacheState = SHOULD_WRITE; recordTextureDone(false); } @@ -1367,14 +1392,14 @@ bool LLTextureFetchWorker::doWork(S32 param) // Otherwise, advance into the HTTP states. if (mFetcher->getHttpWaitersCount() || ! acquireHttpSemaphore()) { - mState = WAIT_HTTP_RESOURCE2; + setState(WAIT_HTTP_RESOURCE2); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); mFetcher->addHttpWaiter(this->mID); ++mResourceWaitCount; return false; } - mState = SEND_HTTP_REQ; + setState(SEND_HTTP_REQ); // *NOTE: You must invoke releaseHttpSemaphore() if you transition // to a state other than SEND_HTTP_REQ or WAIT_HTTP_REQ or abort // the request. @@ -1391,6 +1416,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (! mCanUseHTTP) { releaseHttpSemaphore(); + LL_WARNS("Texture") << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << llendl; return true; // abort } @@ -1407,13 +1433,19 @@ bool LLTextureFetchWorker::doWork(S32 param) // We already have all the data, just decode it mLoadedDiscard = mFormattedImage->getDiscardLevel(); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = DECODE_IMAGE; + if (mLoadedDiscard < 0) + { + LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << llendl; + } + setState(DECODE_IMAGE); releaseHttpSemaphore(); return false; } else { releaseHttpSemaphore(); + LL_WARNS("Texture") << mID << " SEND_HTTP_REQ abort: cur_size " << cur_size << " <=0" << llendl; return true; // abort. } } @@ -1471,7 +1503,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mFetcher->addToHTTPQueue(mID); recordTextureStart(true); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - mState = WAIT_HTTP_REQ; + setState(WAIT_HTTP_REQ); // fall through } @@ -1489,8 +1521,9 @@ bool LLTextureFetchWorker::doWork(S32 param) { if(mWriteToCacheState == NOT_WRITE) //map tiles { - mState = DONE; + setState(DONE); releaseHttpSemaphore(); + LL_DEBUGS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; return true; // failed, means no map tile on the empty region. } @@ -1499,7 +1532,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // roll back to try UDP if (mCanUseNET) { - mState = INIT; + setState(INIT); mCanUseHTTP = false; mUrl.clear(); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); @@ -1530,15 +1563,21 @@ bool LLTextureFetchWorker::doWork(S32 param) // Use available data mLoadedDiscard = mFormattedImage->getDiscardLevel(); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = DECODE_IMAGE; + if (mLoadedDiscard < 0) + { + LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << llendl; + } + setState(DECODE_IMAGE); releaseHttpSemaphore(); return false; } // Fail harder resetFormattedData(); - mState = DONE; + setState(DONE); releaseHttpSemaphore(); + LL_WARNS("Texture") << mID << " abort: fail harder" << llendl; return true; // failed } @@ -1547,6 +1586,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // next time the texture is requested, even if the data have already been fetched. if(mWriteToCacheState != NOT_WRITE) { + // Why do we want to keep url if NOT_WRITE - is this a proxy for map tiles? mUrl.clear(); } @@ -1560,7 +1600,8 @@ bool LLTextureFetchWorker::doWork(S32 param) } // abort. - mState = DONE; + setState(DONE); + LL_WARNS("Texture") << mID << " abort: no data received" << llendl; releaseHttpSemaphore(); return true; } @@ -1578,7 +1619,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { LL_WARNS("Texture") << "Partial HTTP response produces break in image data for texture " << mID << ". Aborting load." << LL_ENDL; - mState = DONE; + setState(DONE); releaseHttpSemaphore(); return true; } @@ -1626,7 +1667,12 @@ bool LLTextureFetchWorker::doWork(S32 param) mHttpReplyOffset = 0; mLoadedDiscard = mRequestedDiscard; - mState = DECODE_IMAGE; + if (mLoadedDiscard < 0) + { + LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << llendl; + } + setState(DECODE_IMAGE); if (mWriteToCacheState != NOT_WRITE) { mWriteToCacheState = SHOULD_WRITE ; @@ -1657,31 +1703,34 @@ bool LLTextureFetchWorker::doWork(S32 param) if (textures_decode_disabled) { // for debug use, don't decode - mState = DONE; + setState(DONE); return true; } if (mDesiredDiscard < 0) { // We aborted, don't decode - mState = DONE; + setState(DONE); + LL_DEBUGS("Texture") << mID << " DECODE_IMAGE abort: desired discard " << mDesiredDiscard << "<0" << llendl; return true; } if (mFormattedImage->getDataSize() <= 0) { - //llerrs << "Decode entered with invalid mFormattedImage. ID = " << mID << llendl; + llwarns << "Decode entered with invalid mFormattedImage. ID = " << mID << llendl; //abort, don't decode - mState = DONE; + setState(DONE); + LL_DEBUGS("Texture") << mID << " DECODE_IMAGE abort: (mFormattedImage->getDataSize() <= 0)" << llendl; return true; } if (mLoadedDiscard < 0) { - //llerrs << "Decode entered with invalid mLoadedDiscard. ID = " << mID << llendl; + llwarns << "Decode entered with invalid mLoadedDiscard. ID = " << mID << llendl; //abort, don't decode - mState = DONE; + setState(DONE); + LL_DEBUGS("Texture") << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << llendl; return true; } @@ -1691,7 +1740,7 @@ bool LLTextureFetchWorker::doWork(S32 param) S32 discard = mHaveAllData ? 0 : mLoadedDiscard; U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; - mState = DECODE_IMAGE_UPDATE; + setState(DECODE_IMAGE_UPDATE); LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, @@ -1719,13 +1768,13 @@ bool LLTextureFetchWorker::doWork(S32 param) mFormattedImage = NULL; ++mRetryAttempt; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = INIT; + setState(INIT); return false; } else { // llwarns << "UNABLE TO LOAD TEXTURE: " << mID << " RETRIES: " << mRetryAttempt << llendl; - mState = DONE; // failed + setState(DONE); // failed } } else @@ -1734,7 +1783,7 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS("Texture") << mID << ": Decoded. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - mState = WRITE_TO_CACHE; + setState(WRITE_TO_CACHE); } // fall through } @@ -1750,7 +1799,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { // If we're in a local cache or we didn't actually receive any new data, // or we failed to load anything, skip - mState = DONE; + setState(DONE); return false; } S32 datasize = mFormattedImage->getDataSize(); @@ -1769,7 +1818,7 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it U32 cache_priority = mWorkPriority; mWritten = FALSE; - mState = WAIT_ON_WRITE; + setState(WAIT_ON_WRITE); ++mCacheWriteCount; CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID); mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority, @@ -1782,7 +1831,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (writeToCacheComplete()) { - mState = DONE; + setState(DONE); // fall through } else @@ -1803,7 +1852,10 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard) { // More data was requested, return to INIT - mState = INIT; + setState(INIT); + LL_DEBUGS("Texture") << mID << " more data requested, returning to INIT: " + << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard + << "<" << " mDecodedDiscard " << mDecodedDiscard << llendl; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); return false; } @@ -1843,10 +1895,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe bool partial = false; LLCore::HttpStatus status(response->getStatus()); - lldebugs << "HTTP COMPLETE: " << mID - << " status: " << status.toHex() - << " '" << status.toString() << "'" - << llendl; + LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID + << " status: " << status.toHex() + << " '" << status.toString() << "'" + << llendl; // unsigned int offset(0), length(0), full_length(0); // response->getRange(&offset, &length, &full_length); // llwarns << "HTTP COMPLETE: " << mID << " handle: " << handle @@ -2401,7 +2453,7 @@ LLTextureFetch::~LLTextureFetch() // ~LLQueuedThread() called here } -bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, +bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { if(mFetcherLocked) @@ -2430,6 +2482,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con std::string exten = gDirUtilp->getExtension(url); if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) { + LL_DEBUGS("Texture") << "full request for " << id << " exten is not J2C: " << exten << llendl; // Only do partial requests for J2C at the moment desired_size = MAX_IMAGE_DATA_SIZE; desired_discard = 0; @@ -2472,7 +2525,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con worker->setCanUseHTTP(can_use_http) ; if (!worker->haveWork()) { - worker->mState = LLTextureFetchWorker::INIT; + worker->setState(LLTextureFetchWorker::INIT); worker->unlockWorkMutex(); // -Mw worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); @@ -2484,7 +2537,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con } else { - worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); lockQueue(); // +Mfq mRequestMap[id] = worker; unlockQueue(); // -Mfq @@ -2496,7 +2549,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con worker->unlockWorkMutex(); // -Mw } -// llinfos << "REQUESTED: " << id << " Discard: " << desired_discard << llendl; + LL_DEBUGS("Texture") << "REQUESTED: " << id << " Discard: " << desired_discard << " size " << desired_size << llendl; return true; } @@ -3165,6 +3218,30 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) return true; } +void LLTextureFetchWorker::setState(e_state new_state) +{ + static const char* e_state_name[] = + { + "INVALID", + "INIT", + "LOAD_FROM_TEXTURE_CACHE", + "CACHE_POST", + "LOAD_FROM_NETWORK", + "LOAD_FROM_SIMULATOR", + "WAIT_HTTP_RESOURCE", + "WAIT_HTTP_RESOURCE2", + "SEND_HTTP_REQ", + "WAIT_HTTP_REQ", + "DECODE_IMAGE", + "DECODE_IMAGE_UPDATE", + "WRITE_TO_CACHE", + "WAIT_ON_WRITE", + "DONE" + }; + LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; + mState = new_state; +} + // Threads: T* bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data) @@ -3221,7 +3298,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); res = worker->insertPacket(0, data, data_size); worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); - worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; + worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); worker->unlockWorkMutex(); // -Mw return res; } @@ -3271,7 +3348,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 (worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK)) { worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); - worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; + worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); } else { @@ -3534,7 +3611,7 @@ void LLTextureFetch::releaseHttpWaiters() break; } - worker->mState = LLTextureFetchWorker::SEND_HTTP_REQ; + worker->setState(LLTextureFetchWorker::SEND_HTTP_REQ); worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->unlockWorkMutex(); // -Mw diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 5ea3c14e1a..902a3d7a25 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -44,8 +44,8 @@ #include "httpoptions.h" #include "httpheaders.h" #include "httphandler.h" +#include "llviewertexture.h" -class LLViewerTexture; class LLTextureFetchWorker; class LLImageDecodeThread; class LLHost; @@ -77,7 +77,7 @@ public: void shutDownImageDecodeThread(); // Threads: T* (but Tmain mostly) - bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, + bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); // Requests that a fetch operation be deleted from the queue. diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 16c42dbd43..e80136b286 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -40,7 +40,7 @@ #include "lltooltip.h" #include "llappviewer.h" #include "llselectmgr.h" -#include "lltexlayer.h" +#include "llviewertexlayer.h" #include "lltexturecache.h" #include "lltexturefetch.h" #include "llviewercontrol.h" @@ -170,7 +170,7 @@ void LLTextureBar::draw() { color = LLColor4::green4; } - else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE) + else if (mImagep->getBoostLevel() > LLGLTexture::BOOST_NONE) { color = LLColor4::magenta; } @@ -420,14 +420,14 @@ void LLAvatarTexBar::draw() LLColor4 color; U32 line_num = 1; - for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); if (!layerset) continue; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) continue; LLColor4 text_color = LLColor4::white; diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 4dc0d424ac..beb45e8179 100755 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -33,6 +33,7 @@ #include "llbutton.h" #include "lliconctrl.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llnotifications.h" #include "llviewertexteditor.h" diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 4ef5ad845c..8bfde2bcf1 100755 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -207,8 +207,6 @@ void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 void LLToastNotifyPanel::adjustPanelForTipNotice() { - LLRect info_rect = mInfoPanel->getRect(); - LLRect this_rect = getRect(); //we don't need display ControlPanel for tips because they doesn't contain any buttons. mControlPanel->setVisible(FALSE); reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight()); diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index aba43a9715..08d82ea9cb 100755 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -657,7 +657,7 @@ bool LLToolBrushLand::canTerraform(LLViewerRegion* regionp) const { if (!regionp) return false; if (regionp->canManageEstate()) return true; - return !(regionp->getRegionFlags() & REGION_FLAGS_BLOCK_TERRAFORM); + return !regionp->getRegionFlag(REGION_FLAGS_BLOCK_TERRAFORM); } // static diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 923fbecb1a..5270c3d33f 100755 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -471,7 +471,7 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask) mObjectPlacedOnMouseDown = TRUE; - return TRUE; + return handled; } void LLToolCompCreate::pickCallback(const LLPickInfo& pick_info) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 94c97158a8..e085834326 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1247,7 +1247,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, if (!item || !item->isFinished()) return; //if (regionp - // && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)) + // && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))) //{ // LLFirstUse::useSandbox(); //} @@ -1741,7 +1741,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( { if(mSource == SOURCE_LIBRARY) { - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); copy_inventory_item( gAgent.getID(), item->getPermissions().getOwner(), @@ -2094,7 +2094,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture( { // create item based on that one, and put it on if that // was a success. - LLPointer<LLInventoryCallback> cb = new ActivateGestureCallback(); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(activate_gesture_cb); copy_inventory_item( gAgent.getID(), item->getPermissions().getOwner(), diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index a754d8ee7e..857b0f0714 100755 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -314,8 +314,6 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask) S32 dx = gViewerWindow->getCurrentMouseDX(); S32 dy = gViewerWindow->getCurrentMouseDY(); - BOOL moved_outside_slop = FALSE; - if (hasMouseCapture() && mValidClickPoint) { mAccumX += llabs(dx); @@ -323,19 +321,11 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask) if (mAccumX >= SLOP_RANGE) { - if (!mOutsideSlopX) - { - moved_outside_slop = TRUE; - } mOutsideSlopX = TRUE; } if (mAccumY >= SLOP_RANGE) { - if (!mOutsideSlopY) - { - moved_outside_slop = TRUE; - } mOutsideSlopY = TRUE; } } diff --git a/indra/newview/lltoolgun.cpp b/indra/newview/lltoolgun.cpp index 857d105361..c1735adc9c 100755 --- a/indra/newview/lltoolgun.cpp +++ b/indra/newview/lltoolgun.cpp @@ -42,7 +42,7 @@ #include "llhudmanager.h" #include "lltoolmgr.h" #include "lltoolgrab.h" - +#include "lluiimage.h" // Linden library includes #include "llwindow.h" // setMouseClipping() diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 0d5daf129f..148e5a015b 100755 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -34,6 +34,7 @@ #include "llaudioengine.h" #include "llviewercontrol.h" #include "llfontgl.h" +#include "llwearable.h" #include "sound_ids.h" #include "v3math.h" #include "v3color.h" diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index f24891baf6..fc9a316759 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -791,14 +791,10 @@ BOOL LLToolPie::handleTooltipLand(std::string line, std::string tooltip_msg) LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); LLUUID owner; - S32 width = 0; - S32 height = 0; if ( hover_parcel ) { owner = hover_parcel->getOwnerID(); - width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth()); - height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight()); } // Line: "Land" @@ -1593,9 +1589,6 @@ BOOL LLToolPie::handleRightClickPick() // didn't click in any UI object, so must have clicked in the world LLViewerObject *object = mPick.getObject(); - LLViewerObject *parent = NULL; - if(object) - parent = object->getRootEdit(); // Can't ignore children here. LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 93ba3b2558..641fbc5042 100755 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -182,7 +182,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) return FALSE; } - if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX) + if (regionp->getRegionFlag(REGION_FLAGS_SANDBOX)) { //LLFirstUse::useSandbox(); } @@ -485,7 +485,7 @@ BOOL LLToolPlacer::addDuplicate(S32 x, S32 y) FALSE); // select copy if (regionp - && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)) + && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))) { //LLFirstUse::useSandbox(); } diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp index 5a6a17fbca..1d777b3f7f 100755 --- a/indra/newview/lluploadfloaterobservers.cpp +++ b/indra/newview/lluploadfloaterobservers.cpp @@ -33,9 +33,10 @@ LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHan { } -void LLUploadModelPremissionsResponder::error(U32 status, const std::string& reason) +void LLUploadModelPremissionsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - llwarns << "LLUploadModelPremissionsResponder::error("<< status << ": " << reason << ")" << llendl; + llwarns << "LLUploadModelPremissionsResponder error [status:" + << status << "]: " << content << llendl; LLUploadPermissionsObserver* observer = mObserverHandle.get(); diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h index 79aad282d7..b43ddb44d9 100755 --- a/indra/newview/lluploadfloaterobservers.h +++ b/indra/newview/lluploadfloaterobservers.h @@ -86,7 +86,7 @@ public: LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer); - void error(U32 status, const std::string& reason); + void errorWithContent(U32 status, const std::string& reason, const LLSD& content); void result(const LLSD& content); diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index edec30f8c4..dd17068be5 100755 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -112,8 +112,6 @@ void LLURLHistory::addURL(const std::string& collection, const std::string& url) // static void LLURLHistory::removeURL(const std::string& collection, const std::string& url) { - LLSD::array_iterator iter = sHistorySD[collection].beginArray(); - LLSD::array_iterator end = sHistorySD[collection].endArray(); for(int index = 0; index < sHistorySD[collection].size(); index++) { if(sHistorySD[collection].get(index).asString() == url) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 4c59fd0371..aaa81c57d4 100755 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -160,9 +160,7 @@ LLViewerAssetStats::LLViewerAssetStats() LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) : mRegionHandle(src.mRegionHandle), - mResetTimestamp(src.mResetTimestamp), - mPhaseStats(src.mPhaseStats), - mAvatarRezStates(src.mAvatarRezStates) + mResetTimestamp(src.mResetTimestamp) { const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) @@ -258,17 +256,6 @@ LLViewerAssetStats::recordFPS(F32 fps) mCurRegionStats->mFPS.record(fps); } -void -LLViewerAssetStats::recordAvatarStats() -{ - std::vector<S32> rez_counts; - LLVOAvatar::getNearbyRezzedStats(rez_counts); - mAvatarRezStates = rez_counts; - mPhaseStats.clear(); - mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud"); - mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray"); -} - LLSD LLViewerAssetStats::asLLSD(bool compact_output) { @@ -299,11 +286,6 @@ LLViewerAssetStats::asLLSD(bool compact_output) static const LLSD::String max_tag("max"); static const LLSD::String mean_tag("mean"); - // Avatar sub-tags - static const LLSD::String avatar_tag("avatar"); - static const LLSD::String avatar_nearby_tag("nearby"); - static const LLSD::String avatar_phase_stats_tag("phase_stats"); - const duration_t now = LLViewerAssetStatsFF::get_timestamp(); mCurRegionStats->accumulateTime(now); @@ -362,16 +344,6 @@ LLViewerAssetStats::asLLSD(bool compact_output) LLSD ret = LLSD::emptyMap(); ret["regions"] = regions; ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); - LLSD avatar_info; - avatar_info[avatar_nearby_tag] = LLSD::emptyArray(); - for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat) - { - std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); - avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat]; - } - avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData(); - avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData(); - ret[avatar_tag] = avatar_info; return ret; } @@ -470,15 +442,6 @@ record_fps_main(F32 fps) gViewerAssetStatsMain->recordFPS(fps); } -void -record_avatar_stats() -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->recordAvatarStats(); -} - // 'thread1' - should be for TextureFetch thread void diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 8319752230..e4581d2120 100755 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -256,10 +256,6 @@ protected: // Time of last reset duration_t mResetTimestamp; - - // Nearby avatar stats - std::vector<S32> mAvatarRezStates; - LLViewerStats::phase_stats_t mPhaseStats; }; @@ -318,8 +314,6 @@ void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_t void record_fps_main(F32 fps); -void record_avatar_stats(); - /** * Region context, event and duration loggers for Thread 1. */ diff --git a/indra/newview/llviewerattachmenu.cpp b/indra/newview/llviewerattachmenu.cpp index db7dc3fea6..3975292ed3 100755 --- a/indra/newview/llviewerattachmenu.cpp +++ b/indra/newview/llviewerattachmenu.cpp @@ -121,7 +121,7 @@ void LLViewerAttachMenu::attachObjects(const uuid_vec_t& items, const std::strin else if(item && item->isFinished()) { // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, attachmentp)); copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(), diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 564bf7997a..094694dc06 100755 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -44,6 +44,8 @@ #include "llparcel.h" #include "llviewermessage.h" +#include "llstreamingaudio.h" + ///////////////////////////////////////////////////////// LLViewerAudio::LLViewerAudio() : @@ -102,6 +104,11 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI) else { mFadeState = FADE_IN; + + LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl(); + if(stream && stream->supportsAdjustableBufferSizes()) + stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize")); + gAudiop->startInternetStream(mNextStreamURI); startFading(); registerIdleListener(); @@ -157,6 +164,11 @@ bool LLViewerAudio::onIdleUpdate() if (!mNextStreamURI.empty()) { mFadeState = FADE_IN; + + LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl(); + if(stream && stream->supportsAdjustableBufferSizes()) + stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize")); + gAudiop->startInternetStream(mNextStreamURI); startFading(); } @@ -386,7 +398,12 @@ void audio_update_volume(bool force_update) gAudiop->setMasterGain ( master_volume ); gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler")); - gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); + + if(!LLViewerCamera::getInstance()->cameraUnderWater()) + gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); + else + gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelUnderwaterRolloff")); + gAudiop->setMuted(mute_audio || progress_view_visible); //Play any deferred sounds when unmuted @@ -473,44 +490,22 @@ void audio_update_listener() void audio_update_wind(bool force_update) { #ifdef kAUDIO_ENABLE_WIND - // - // Extract height above water to modulate filter by whether above/below water - // + LLViewerRegion* region = gAgent.getRegion(); if (region) { - static F32 last_camera_water_height = -1000.f; - LLVector3 camera_pos = gAgentCamera.getCameraPositionAgent(); - F32 camera_water_height = camera_pos.mV[VZ] - region->getWaterHeight(); - - // - // Don't update rolloff factor unless water surface has been crossed - // - if (force_update || (last_camera_water_height * camera_water_height) < 0.f) - { - static LLUICachedControl<F32> rolloff("AudioLevelRolloff", 1.0f); - if (camera_water_height < 0.f) - { - gAudiop->setRolloffFactor(rolloff * LL_ROLLOFF_MULTIPLIER_UNDER_WATER); - } - else - { - gAudiop->setRolloffFactor(rolloff); - } - } - - // Scale down the contribution of weather-simulation wind to the - // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s - // whereas steady-state avatar walk velocity is only 3.2 m/s. - // Without this the world feels desolate on first login when you are - // standing still. - static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); - LLVector3 scaled_wind_vec = gWindVec * wind_level; - - // Mix in the avatar's motion, subtract because when you walk north, - // the apparent wind moves south. - LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); - + // Scale down the contribution of weather-simulation wind to the + // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s + // whereas steady-state avatar walk velocity is only 3.2 m/s. + // Without this the world feels desolate on first login when you are + // standing still. + static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); + LLVector3 scaled_wind_vec = gWindVec * wind_level; + + // Mix in the avatar's motion, subtract because when you walk north, + // the apparent wind moves south. + LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); + // rotate the wind vector to be listener (agent) relative gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec ); @@ -543,8 +538,7 @@ void audio_update_wind(bool force_update) gAudiop->mMaxWindGain = llmax(gAudiop->mMaxWindGain - volume_delta, 0.f); } - last_camera_water_height = camera_water_height; - gAudiop->updateWind(gRelativeWindVec, camera_water_height); + gAudiop->updateWind(gRelativeWindVec, gAgentCamera.getCameraPositionAgent()[VZ] - gAgent.getRegion()->getWaterHeight()); } #endif } diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index a437a8b3b5..b5aa0ac92a 100755 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -136,9 +136,6 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, mLastPointOfInterest = point_of_interest; - // constrain to max distance from avatar - LLVector3 camera_offset = center - gAgent.getPositionAgent(); - LLViewerRegion * regp = gAgent.getRegion(); F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f; @@ -318,7 +315,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection, { F32 fov_y, aspect; fov_y = RAD_TO_DEG * getView(); - BOOL z_default_near, z_default_far = FALSE; + BOOL z_default_far = FALSE; if (z_far <= 0) { z_default_far = TRUE; @@ -326,7 +323,6 @@ void LLViewerCamera::setPerspective(BOOL for_selection, } if (z_near <= 0) { - z_default_near = TRUE; z_near = getNear(); } aspect = getAspect(); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 051f5f4485..a62f73deef 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -655,6 +655,7 @@ void settings_setup_listeners() gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); + gSavedSettings.getControl("AudioLevelUnderwaterRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 40577118ba..cf59e67955 100755 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1424,7 +1424,7 @@ void render_ui_2d() gGL.pushMatrix(); S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); - gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); + gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f); gGL.translatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgentCamera.mHUDCurZoom; gGL.scalef(zoom,zoom,1.f); @@ -1462,10 +1462,10 @@ void render_ui_2d() LLUI::sDirtyRect = last_rect; last_rect = t_rect; - last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]); - last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]); - last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]); - last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]); + last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); + last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); + last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); + last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]); LLRect clip_rect(last_rect); diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 6bd5631df6..f81206ffec 100755 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -60,8 +60,10 @@ class LLSetDisplayNameResponder : public LLHTTPClient::Responder { public: // only care about errors - /*virtual*/ void error(U32 status, const std::string& reason) + /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { + llwarns << "LLSetDisplayNameResponder error [status:" + << status << "]: " << content << llendl; LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index a187318eb7..fff9821e86 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -64,6 +64,11 @@ #include "llavatarnamecache.h" #include "llavataractions.h" #include "lllogininstance.h" +#include "llfavoritesbar.h" + +// Two do-nothing ops for use in callbacks. +void no_op_inventory_func(const LLUUID&) {} +void no_op() {} ///---------------------------------------------------------------------------- /// Helper class to store special inventory item names and their localized values. @@ -588,7 +593,7 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego { copyCategory(other); mOwnerID = other->mOwnerID; - mVersion = other->mVersion; + setVersion(other->getVersion()); mDescendentCount = other->mDescendentCount; mDescendentsRequested = other->mDescendentsRequested; } @@ -656,9 +661,19 @@ void LLViewerInventoryCategory::removeFromServer( void ) gAgent.sendReliableMessage(); } +S32 LLViewerInventoryCategory::getVersion() const +{ + return mVersion; +} + +void LLViewerInventoryCategory::setVersion(S32 version) +{ + mVersion = version; +} + bool LLViewerInventoryCategory::fetch() { - if((VERSION_UNKNOWN == mVersion) + if((VERSION_UNKNOWN == getVersion()) && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads. { LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; @@ -949,46 +964,7 @@ void LLInventoryCallbackManager::fire(U32 callback_id, const LLUUID& item_id) } } -void WearOnAvatarCallback::fire(const LLUUID& inv_item) -{ - if (inv_item.isNull()) - return; - - LLViewerInventoryItem *item = gInventory.getItem(inv_item); - if (item) - { - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item, true, mReplace); - } -} - -void ModifiedCOFCallback::fire(const LLUUID& inv_item) -{ - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - - // Start editing the item if previously requested. - gAgentWearables.editWearableIfRequested(inv_item); - - // TODO: camera mode may not be changed if a debug setting is tweaked - if( gAgentCamera.cameraCustomizeAvatar() ) - { - // If we're in appearance editing mode, the current tab may need to be refreshed - LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); - if (panel) - { - panel->showDefaultSubpart(); - } - } -} - -RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp) -{ - mAttach = attachmentp; -} -RezAttachmentCallback::~RezAttachmentCallback() -{ -} - -void RezAttachmentCallback::fire(const LLUUID& inv_item) +void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp) { if (inv_item.isNull()) return; @@ -996,11 +972,11 @@ void RezAttachmentCallback::fire(const LLUUID& inv_item) LLViewerInventoryItem *item = gInventory.getItem(inv_item); if (item) { - rez_attachment(item, mAttach); + rez_attachment(item, attachmentp); } } -void ActivateGestureCallback::fire(const LLUUID& inv_item) +void activate_gesture_cb(const LLUUID& inv_item) { if (inv_item.isNull()) return; @@ -1013,7 +989,7 @@ void ActivateGestureCallback::fire(const LLUUID& inv_item) LLGestureMgr::instance().activateGesture(inv_item); } -void CreateGestureCallback::fire(const LLUUID& inv_item) +void create_gesture_cb(const LLUUID& inv_item) { if (inv_item.isNull()) return; @@ -1031,7 +1007,6 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) } - LLInventoryCallbackManager gInventoryCallbacks; void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, @@ -1157,6 +1132,11 @@ void link_inventory_item( } } +#if 1 // debugging stuff + LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id); + lldebugs << "cat: " << cat << llendl; + +#endif LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_LinkInventoryItem); msg->nextBlock(_PREHASH_AgentData); @@ -1283,7 +1263,7 @@ void create_new_item(const std::string& name, if (inv_type == LLInventoryType::IT_GESTURE) { - LLPointer<LLInventoryCallback> cb = new CreateGestureCallback(); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(create_gesture_cb); create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type, NOT_WEARABLE, next_owner_perm, cb); @@ -1444,6 +1424,28 @@ const std::string& LLViewerInventoryItem::getName() const return LLInventoryItem::getName(); } +S32 LLViewerInventoryItem::getSortField() const +{ + return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); +} + +//void LLViewerInventoryItem::setSortField(S32 sortField) +//{ +// LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); +// getSLURL(); +//} + +void LLViewerInventoryItem::getSLURL() +{ + LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); +} + +const LLPermissions& LLViewerInventoryItem::getPermissions() const +{ + // Use the actual permissions of the symlink, not its parent. + return LLInventoryItem::getPermissions(); +} + const LLUUID& LLViewerInventoryItem::getCreatorUUID() const { if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1514,6 +1516,17 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK); } + +time_t LLViewerInventoryItem::getCreationDate() const +{ + return LLInventoryItem::getCreationDate(); +} + +U32 LLViewerInventoryItem::getCRC32() const +{ + return LLInventoryItem::getCRC32(); +} + // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 static char getSeparator() { return '@'; } BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 3cf03c3bc5..61b1b8d846 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -35,6 +35,7 @@ #include <boost/signals2.hpp> // boost::signals2::trackable class LLInventoryPanel; +class LLFolderView; class LLFolderBridge; class LLViewerInventoryCategory; @@ -60,6 +61,10 @@ public: virtual const LLUUID& getAssetUUID() const; virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user virtual const std::string& getName() const; + virtual S32 getSortField() const; + //virtual void setSortField(S32 sortField); + virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. + virtual const LLPermissions& getPermissions() const; virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied virtual const LLUUID& getCreatorUUID() const; virtual const std::string& getDescription() const; @@ -68,11 +73,8 @@ public: virtual bool isWearableType() const; virtual LLWearableType::EType getWearableType() const; virtual U32 getFlags() const; - - using LLInventoryItem::getPermissions; - using LLInventoryItem::getCreationDate; - using LLInventoryItem::setCreationDate; - using LLInventoryItem::getCRC32; + virtual time_t getCreationDate() const; + virtual U32 getCRC32() const; // really more of a checksum. static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -204,13 +206,13 @@ public: // Version handling enum { VERSION_UNKNOWN = -1, VERSION_INITIAL = 1 }; - S32 getVersion() const { return mVersion; } - void setVersion(S32 version) { mVersion = version; } + S32 getVersion() const; + void setVersion(S32 version); // Returns true if a fetch was issued. bool fetch(); - // used to help make cacheing more robust - for example, if + // used to help make caching more robust - for example, if // someone is getting 4 packets but logs out after 3. the viewer // may never know the cache is wrong. enum { DESCENDENT_COUNT_UNKNOWN = -1 }; @@ -218,7 +220,7 @@ public: void setDescendentCount(S32 descendents) { mDescendentCount = descendents; } // file handling on the viewer. These are not meant for anything - // other than cacheing. + // other than caching. bool exportFileLocal(LLFILE* fp) const; bool importFileLocal(LLFILE* fp); void determineFolderType(); @@ -241,47 +243,60 @@ public: virtual void fire(const LLUUID& inv_item) = 0; }; -class WearOnAvatarCallback : public LLInventoryCallback +class LLViewerJointAttachment; + +void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp); + +void activate_gesture_cb(const LLUUID& inv_item); + +void create_gesture_cb(const LLUUID& inv_item); + +class AddFavoriteLandmarkCallback : public LLInventoryCallback { public: - WearOnAvatarCallback(bool do_replace = false) : mReplace(do_replace) {} - + AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} + void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: void fire(const LLUUID& inv_item); -protected: - bool mReplace; + LLUUID mTargetLandmarkId; }; -class ModifiedCOFCallback : public LLInventoryCallback -{ - void fire(const LLUUID& inv_item); -}; +typedef boost::function<void(const LLUUID&)> inventory_func_type; +void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func -class LLViewerJointAttachment; +typedef boost::function<void()> nullary_func_type; +void no_op(); // A do-nothing nullary func. -class RezAttachmentCallback : public LLInventoryCallback +// Shim between inventory callback and boost function/callable +class LLBoostFuncInventoryCallback: public LLInventoryCallback { public: - RezAttachmentCallback(LLViewerJointAttachment *attachmentp); - void fire(const LLUUID& inv_item); -protected: - ~RezAttachmentCallback(); + LLBoostFuncInventoryCallback(inventory_func_type fire_func, + nullary_func_type destroy_func = no_op): + mFireFunc(fire_func), + mDestroyFunc(destroy_func) + { + } -private: - LLViewerJointAttachment* mAttach; -}; + // virtual + void fire(const LLUUID& item_id) + { + mFireFunc(item_id); + } -class ActivateGestureCallback : public LLInventoryCallback -{ -public: - void fire(const LLUUID& inv_item); -}; + // virtual + ~LLBoostFuncInventoryCallback() + { + mDestroyFunc(); + } + -class CreateGestureCallback : public LLInventoryCallback -{ -public: - void fire(const LLUUID& inv_item); +private: + inventory_func_type mFireFunc; + nullary_func_type mDestroyFunc; }; // misc functions diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index a907f102f8..e46299f9d2 100755 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -35,50 +35,26 @@ #include "llrender.h" #include "llmath.h" #include "llglheaders.h" -#include "llrendersphere.h" #include "llvoavatar.h" #include "pipeline.h" -#define DEFAULT_LOD 0.0f - -const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -BOOL LLViewerJoint::sDisableLOD = FALSE; +static const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; //----------------------------------------------------------------------------- // LLViewerJoint() -// Class Constructor +// Class Constructors //----------------------------------------------------------------------------- -LLViewerJoint::LLViewerJoint() - : LLJoint() -{ - init(); -} +LLViewerJoint::LLViewerJoint() : + LLAvatarJoint() +{ } +LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) : + LLAvatarJoint(name, parent) +{ } -//----------------------------------------------------------------------------- -// LLViewerJoint() -// Class Constructor -//----------------------------------------------------------------------------- -LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) - : LLJoint(name, parent) -{ - init(); -} - - -void LLViewerJoint::init() -{ - mValid = FALSE; - mComponents = SC_JOINT | SC_BONE | SC_AXES; - mMinPixelArea = DEFAULT_LOD; - mPickName = PN_DEFAULT; - mVisible = TRUE; - mMeshID = 0; -} +LLViewerJoint::LLViewerJoint(S32 joint_num) : + LLAvatarJoint(joint_num) +{ } //----------------------------------------------------------------------------- @@ -89,154 +65,6 @@ LLViewerJoint::~LLViewerJoint() { } - -//-------------------------------------------------------------------- -// setValid() -//-------------------------------------------------------------------- -void LLViewerJoint::setValid( BOOL valid, BOOL recursive ) -{ - //---------------------------------------------------------------- - // set visibility for this joint - //---------------------------------------------------------------- - mValid = valid; - - //---------------------------------------------------------------- - // set visibility for children - //---------------------------------------------------------------- - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setValid(valid, TRUE); - } - } - -} - -//-------------------------------------------------------------------- -// renderSkeleton() -// DEBUG (UNUSED) -//-------------------------------------------------------------------- -// void LLViewerJoint::renderSkeleton(BOOL recursive) -// { -// F32 nc = 0.57735f; - -// //---------------------------------------------------------------- -// // push matrix stack -// //---------------------------------------------------------------- -// gGL.pushMatrix(); - -// //---------------------------------------------------------------- -// // render the bone to my parent -// //---------------------------------------------------------------- -// if (mComponents & SC_BONE) -// { -// drawBone(); -// } - -// //---------------------------------------------------------------- -// // offset to joint position and -// // rotate to our orientation -// //---------------------------------------------------------------- -// gGL.loadIdentity(); -// gGL.multMatrix( &getWorldMatrix().mMatrix[0][0] ); - -// //---------------------------------------------------------------- -// // render joint axes -// //---------------------------------------------------------------- -// if (mComponents & SC_AXES) -// { -// gGL.begin(LLRender::LINES); -// gGL.color3f( 1.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.1f, 0.0f, 0.0f ); - -// gGL.color3f( 0.0f, 1.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.1f, 0.0f ); - -// gGL.color3f( 0.0f, 0.0f, 1.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.1f ); -// gGL.end(); -// } - -// //---------------------------------------------------------------- -// // render the joint graphic -// //---------------------------------------------------------------- -// if (mComponents & SC_JOINT) -// { -// gGL.color3f( 1.0f, 1.0f, 0.0f ); - -// gGL.begin(LLRender::TRIANGLES); - -// // joint top half -// glNormal3f(nc, nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); - -// glNormal3f(-nc, nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); - -// glNormal3f(-nc, -nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); - -// glNormal3f(nc, -nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); - -// // joint bottom half -// glNormal3f(nc, nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); - -// glNormal3f(-nc, nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); - -// glNormal3f(-nc, -nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); - -// glNormal3f(nc, -nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); - -// gGL.end(); -// } - -// //---------------------------------------------------------------- -// // render children -// //---------------------------------------------------------------- -// if (recursive) -// { -// for (child_list_t::iterator iter = mChildren.begin(); -// iter != mChildren.end(); ++iter) -// { -// LLViewerJoint* joint = (LLViewerJoint*)(*iter); -// joint->renderSkeleton(); -// } -// } - -// //---------------------------------------------------------------- -// // pop matrix stack -// //---------------------------------------------------------------- -// gGL.popMatrix(); -// } - - //-------------------------------------------------------------------- // render() //-------------------------------------------------------------------- @@ -317,13 +145,13 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); + LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter); F32 jointLOD = joint->getLOD(); if (pixelArea >= jointLOD || sDisableLOD) { triangle_count += joint->render( pixelArea, TRUE, is_dummy ); - if (jointLOD != DEFAULT_LOD) + if (jointLOD != DEFAULT_AVATAR_JOINT_LOD) { break; } @@ -333,72 +161,6 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) return triangle_count; } - -//-------------------------------------------------------------------- -// drawBone() -// DEBUG (UNUSED) -//-------------------------------------------------------------------- -// void LLViewerJoint::drawBone() -// { -// if ( mParent == NULL ) -// return; - -// F32 boneSize = 0.02f; - -// // rotate to point to child (bone direction) -// gGL.pushMatrix(); - -// LLVector3 boneX = getPosition(); -// F32 length = boneX.normVec(); - -// LLVector3 boneZ(1.0f, 0.0f, 1.0f); - -// LLVector3 boneY = boneZ % boneX; -// boneY.normVec(); - -// boneZ = boneX % boneY; - -// LLMatrix4 rotateMat; -// rotateMat.setFwdRow( boneX ); -// rotateMat.setLeftRow( boneY ); -// rotateMat.setUpRow( boneZ ); -// gGL.multMatrix( &rotateMat.mMatrix[0][0] ); - -// // render the bone -// gGL.color3f( 0.5f, 0.5f, 0.0f ); - -// gGL.begin(LLRender::TRIANGLES); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, boneSize, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, boneSize); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, -boneSize); -// gGL.vertex3f( 0.0f, boneSize, 0.0f); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, -boneSize, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, -boneSize); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, boneSize); -// gGL.vertex3f( 0.0f, -boneSize, 0.0f); - -// gGL.end(); - -// // restore matrix -// gGL.popMatrix(); -// } - -//-------------------------------------------------------------------- -// isTransparent() -//-------------------------------------------------------------------- -BOOL LLViewerJoint::isTransparent() -{ - return FALSE; -} - //-------------------------------------------------------------------- // drawShape() //-------------------------------------------------------------------- @@ -407,213 +169,4 @@ U32 LLViewerJoint::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) return 0; } -//-------------------------------------------------------------------- -// setSkeletonComponents() -//-------------------------------------------------------------------- -void LLViewerJoint::setSkeletonComponents( U32 comp, BOOL recursive ) -{ - mComponents = comp; - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setSkeletonComponents(comp, recursive); - } - } -} - -void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceSizes(num_vertices, num_indices, pixel_area); - } -} - -void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceData(face, pixel_area, damp_wind, terse_update); - } -} - -void LLViewerJoint::updateJointGeometry() -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateJointGeometry(); - } -} - - -BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate) -{ - BOOL lod_changed = FALSE; - BOOL found_lod = FALSE; - - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - F32 jointLOD = joint->getLOD(); - - if (found_lod || jointLOD == DEFAULT_LOD) - { - // we've already found a joint to enable, so enable the rest as alternatives - lod_changed |= joint->updateLOD(pixel_area, TRUE); - } - else - { - if (pixel_area >= jointLOD || sDisableLOD) - { - lod_changed |= joint->updateLOD(pixel_area, TRUE); - found_lod = TRUE; - } - else - { - lod_changed |= joint->updateLOD(pixel_area, FALSE); - } - } - } - return lod_changed; -} - -void LLViewerJoint::dump() -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->dump(); - } -} - -void LLViewerJoint::setVisible(BOOL visible, BOOL recursive) -{ - mVisible = visible; - - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setVisible(visible, recursive); - } - } -} - - -void LLViewerJoint::setMeshesToChildren() -{ - removeAllChildren(); - for (std::vector<LLViewerJointMesh*>::iterator iter = mMeshParts.begin(); - iter != mMeshParts.end(); iter++) - { - addChild((LLViewerJointMesh *) *iter); - } -} -//----------------------------------------------------------------------------- -// LLViewerJointCollisionVolume() -//----------------------------------------------------------------------------- - -LLViewerJointCollisionVolume::LLViewerJointCollisionVolume() -{ - mUpdateXform = FALSE; -} - -LLViewerJointCollisionVolume::LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent) : LLViewerJoint(name, parent) -{ - -} - -void LLViewerJointCollisionVolume::renderCollision() -{ - updateWorldMatrix(); - - gGL.pushMatrix(); - gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); - - gGL.diffuseColor3f( 0.f, 0.f, 1.f ); - - gGL.begin(LLRender::LINES); - - LLVector3 v[] = - { - LLVector3(1,0,0), - LLVector3(-1,0,0), - LLVector3(0,1,0), - LLVector3(0,-1,0), - - LLVector3(0,0,-1), - LLVector3(0,0,1), - }; - - //sides - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[3].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[3].mV); - - - //top - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[4].mV); - - - //bottom - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[5].mV); - - gGL.end(); - - gGL.popMatrix(); -} - -LLVector3 LLViewerJointCollisionVolume::getVolumePos(LLVector3 &offset) -{ - mUpdateXform = TRUE; - - LLVector3 result = offset; - result.scaleVec(getScale()); - result.rotVec(getWorldRotation()); - result += getWorldPosition(); - - return result; -} - // End diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 76e3833acb..fd262b6e80 100755 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -30,7 +30,8 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include "lljoint.h" +#include "llavatarjoint.h" +#include "lljointpickname.h" class LLFace; class LLViewerJointMesh; @@ -39,124 +40,25 @@ class LLViewerJointMesh; // class LLViewerJoint //----------------------------------------------------------------------------- class LLViewerJoint : - public LLJoint + public virtual LLAvatarJoint { public: LLViewerJoint(); + LLViewerJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLViewerJoint(const std::string &name, LLJoint *parent = NULL); virtual ~LLViewerJoint(); - // Gets the validity of this joint - BOOL getValid() { return mValid; } - - // Sets the validity of this joint - virtual void setValid( BOOL valid, BOOL recursive=FALSE ); - - // Primarily for debugging and character setup - // Derived classes may add text/graphic output. - // Draw skeleton graphic for debugging and character setup - void renderSkeleton(BOOL recursive=TRUE); // debug only (unused) - - // Draws a bone graphic to the parent joint. - // Derived classes may add text/graphic output. - // Called by renderSkeleton(). - void drawBone(); // debug only (unused) - // Render character hierarchy. // Traverses the entire joint hierarchy, setting up // transforms and calling the drawShape(). // Derived classes may add text/graphic output. virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); // Returns triangle count - // Returns true if this object is transparent. - // This is used to determine in which order to draw objects. - virtual BOOL isTransparent(); - - // Returns true if this object should inherit scale modifiers from its immediate parent - virtual BOOL inheritScale() { return FALSE; } - // Draws the shape attached to a joint. // Called by render(). virtual U32 drawShape( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); virtual void drawNormals() {} - - enum Components - { - SC_BONE = 1, - SC_JOINT = 2, - SC_AXES = 4 - }; - - // Selects which skeleton components to draw - void setSkeletonComponents( U32 comp, BOOL recursive = TRUE ); - - // Returns which skeleton components are enables for drawing - U32 getSkeletonComponents() { return mComponents; } - - // Sets the level of detail for this node as a minimum - // pixel area threshold. If the current pixel area for this - // object is less than the specified threshold, the node is - // not traversed. In addition, if a value is specified (not - // default of 0.0), and the pixel area is larger than the - // specified minimum, the node is rendered, but no other siblings - // of this node under the same parent will be. - F32 getLOD() { return mMinPixelArea; } - void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } - - // Sets the OpenGL selection stack name that is pushed and popped - // with this joint state. The default value indicates that no name - // should be pushed/popped. - enum PickName - { - PN_DEFAULT = -1, - PN_0 = 0, - PN_1 = 1, - PN_2 = 2, - PN_3 = 3, - PN_4 = 4, - PN_5 = 5 - }; - void setPickName(PickName name) { mPickName = name; } - PickName getPickName() { return mPickName; } - - virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); - virtual BOOL updateLOD(F32 pixel_area, BOOL activate); - virtual void updateJointGeometry(); - virtual void dump(); - - void setVisible( BOOL visible, BOOL recursive ); - - // Takes meshes in mMeshParts and sets each one as a child joint - void setMeshesToChildren(); - -public: - static BOOL sDisableLOD; - std::vector<LLViewerJointMesh*> mMeshParts; - void setMeshID( S32 id ) {mMeshID = id;} - -protected: - void init(); - - BOOL mValid; - U32 mComponents; - F32 mMinPixelArea; - PickName mPickName; - BOOL mVisible; - S32 mMeshID; -}; - -class LLViewerJointCollisionVolume : public LLViewerJoint -{ -public: - LLViewerJointCollisionVolume(); - LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent = NULL); - virtual ~LLViewerJointCollisionVolume() {}; - - virtual BOOL inheritScale() { return TRUE; } - - void renderCollision(); - LLVector3 getVolumePos(LLVector3 &offset); }; #endif // LL_LLVIEWERJOINT_H diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 5d1aa870a3..64454a03d1 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -42,7 +42,7 @@ #include "llface.h" #include "llgldbg.h" #include "llglheaders.h" -#include "lltexlayer.h" +#include "llviewertexlayer.h" #include "llviewercamera.h" #include "llviewercontrol.h" #include "llviewertexturelist.h" @@ -67,101 +67,20 @@ static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLViewerJointMesh::LLSkinJoint -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::LLSkinJoint() -{ - mJoint = NULL; -} - -//----------------------------------------------------------------------------- -// ~LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::~LLSkinJoint() -{ - mJoint = NULL; -} - - -//----------------------------------------------------------------------------- -// LLSkinJoint::setupSkinJoint() -//----------------------------------------------------------------------------- -BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint) -{ - // find the named joint - mJoint = joint; - if ( !mJoint ) - { - llinfos << "Can't find joint" << llendl; - } - - // compute the inverse root skin matrix - mRootToJointSkinOffset.clearVec(); - - LLVector3 rootSkinOffset; - while (joint) - { - rootSkinOffset += joint->getSkinOffset(); - joint = (LLViewerJoint*)joint->getParent(); - } - - mRootToJointSkinOffset = -rootSkinOffset; - mRootToParentJointSkinOffset = mRootToJointSkinOffset; - mRootToParentJointSkinOffset += mJoint->getSkinOffset(); - - return TRUE; -} - - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLViewerJointMesh //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -BOOL LLViewerJointMesh::sPipelineRender = FALSE; -EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; -U32 LLViewerJointMesh::sClothingMaskImageName = 0; -LLColor4 LLViewerJointMesh::sClothingInnerColor; //----------------------------------------------------------------------------- // LLViewerJointMesh() //----------------------------------------------------------------------------- LLViewerJointMesh::LLViewerJointMesh() : - mTexture( NULL ), - mLayerSet( NULL ), - mTestImageName( 0 ), - mFaceIndexCount(0), - mIsTransparent(FALSE) + LLAvatarJointMesh() { - - mColor[0] = 1.0f; - mColor[1] = 1.0f; - mColor[2] = 1.0f; - mColor[3] = 1.0f; - mShiny = 0.0f; - mCullBackFaces = TRUE; - - mMesh = NULL; - - mNumSkinJoints = 0; - mSkinJoints = NULL; - - mFace = NULL; - - mMeshID = 0; - mUpdateXform = FALSE; - - mValid = FALSE; } @@ -171,199 +90,6 @@ LLViewerJointMesh::LLViewerJointMesh() //----------------------------------------------------------------------------- LLViewerJointMesh::~LLViewerJointMesh() { - mMesh = NULL; - mTexture = NULL; - freeSkinData(); -} - - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::allocateSkinData() -//----------------------------------------------------------------------------- -BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints ) -{ - mSkinJoints = new LLSkinJoint[ numSkinJoints ]; - mNumSkinJoints = numSkinJoints; - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::freeSkinData() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::freeSkinData() -{ - mNumSkinJoints = 0; - delete [] mSkinJoints; - mSkinJoints = NULL; -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getColor() -//-------------------------------------------------------------------- -void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) -{ - *red = mColor[0]; - *green = mColor[1]; - *blue = mColor[2]; - *alpha = mColor[3]; -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setColor() -//-------------------------------------------------------------------- -void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) -{ - mColor[0] = red; - mColor[1] = green; - mColor[2] = blue; - mColor[3] = alpha; -} - - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getTexture() -//-------------------------------------------------------------------- -//LLViewerTexture *LLViewerJointMesh::getTexture() -//{ -// return mTexture; -//} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setTexture() -//-------------------------------------------------------------------- -void LLViewerJointMesh::setTexture( LLViewerTexture *texture ) -{ - mTexture = texture; - - // texture and dynamic_texture are mutually exclusive - if( texture ) - { - mLayerSet = NULL; - //texture->bindTexture(0); - //texture->setClamp(TRUE, TRUE); - } -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setLayerSet() -// Sets the shape texture (takes precedence over normal texture) -//-------------------------------------------------------------------- -void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set ) -{ - mLayerSet = layer_set; - - // texture and dynamic_texture are mutually exclusive - if( layer_set ) - { - mTexture = NULL; - } -} - - - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getMesh() -//-------------------------------------------------------------------- -LLPolyMesh *LLViewerJointMesh::getMesh() -{ - return mMesh; -} - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::setMesh() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::setMesh( LLPolyMesh *mesh ) -{ - // set the mesh pointer - mMesh = mesh; - - // release any existing skin joints - freeSkinData(); - - if ( mMesh == NULL ) - { - return; - } - - // acquire the transform from the mesh object - setPosition( mMesh->getPosition() ); - setRotation( mMesh->getRotation() ); - setScale( mMesh->getScale() ); - - // create skin joints if necessary - if ( mMesh->hasWeights() && !mMesh->isLOD()) - { - U32 numJointNames = mMesh->getNumJointNames(); - - allocateSkinData( numJointNames ); - std::string *jointNames = mMesh->getJointNames(); - - U32 jn; - for (jn = 0; jn < numJointNames; jn++) - { - //llinfos << "Setting up joint " << jointNames[jn] << llendl; - LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) ); - mSkinJoints[jn].setupSkinJoint( joint ); - } - } - - // setup joint array - if (!mMesh->isLOD()) - { - setupJoint((LLViewerJoint*)getRoot()); - } - -// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl; -} - -//----------------------------------------------------------------------------- -// setupJoint() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint) -{ -// llinfos << "Mesh: " << getName() << llendl; - -// S32 joint_count = 0; - U32 sj; - for (sj=0; sj<mNumSkinJoints; sj++) - { - LLSkinJoint &js = mSkinJoints[sj]; - - if (js.mJoint != current_joint) - { - continue; - } - - // we've found a skinjoint for this joint.. - - // is the last joint in the array our parent? - if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) - { - // ...then just add ourselves - LLViewerJoint* jointp = js.mJoint; - mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); -// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl; -// joint_count++; - } - // otherwise add our parent and ourselves - else - { - mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); -// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl; -// joint_count++; - mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); -// llinfos << "joint " << joint_count << current_joint->getName() << llendl; -// joint_count++; - } - } - - // depth-first traversal - for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); - iter != current_joint->mChildren.end(); ++iter) - { - LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); - setupJoint(child_joint); - } } const S32 NUM_AXES = 3; @@ -475,21 +201,6 @@ void LLViewerJointMesh::uploadJointMatrices() } //-------------------------------------------------------------------- -// LLViewerJointMesh::drawBone() -//-------------------------------------------------------------------- -void LLViewerJointMesh::drawBone() -{ -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::isTransparent() -//-------------------------------------------------------------------- -BOOL LLViewerJointMesh::isTransparent() -{ - return mIsTransparent; -} - -//-------------------------------------------------------------------- // DrawElementsBLEND and utility code //-------------------------------------------------------------------- @@ -544,6 +255,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; + LLViewerTexLayerSet *layerset = dynamic_cast<LLViewerTexLayerSet*>(mLayerSet); if (mTestImageName) { gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); @@ -558,11 +270,11 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } - else if( !is_dummy && mLayerSet ) + else if( !is_dummy && layerset ) { - if( mLayerSet->hasComposite() ) + if( layerset->hasComposite() ) { - gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); + gGL.getTexUnit(diffuse_channel)->bind(layerset->getViewerComposite()); } else { diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index dd5dae1dc1..0db2836e15 100755 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -1,6 +1,6 @@ /** * @file llviewerjointmesh.h - * @brief Implementation of LLViewerJointMesh class + * @brief Declaration of LLViewerJointMesh class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -29,64 +29,20 @@ #include "llviewerjoint.h" #include "llviewertexture.h" +#include "llavatarjointmesh.h" #include "llpolymesh.h" #include "v4color.h" class LLDrawable; class LLFace; class LLCharacter; -class LLTexLayerSet; - -typedef enum e_avatar_render_pass -{ - AVATAR_RENDER_PASS_SINGLE, - AVATAR_RENDER_PASS_CLOTHING_INNER, - AVATAR_RENDER_PASS_CLOTHING_OUTER -} EAvatarRenderPass; - -class LLSkinJoint -{ -public: - LLSkinJoint(); - ~LLSkinJoint(); - BOOL setupSkinJoint( LLViewerJoint *joint); - - LLViewerJoint *mJoint; - LLVector3 mRootToJointSkinOffset; - LLVector3 mRootToParentJointSkinOffset; -}; +class LLViewerTexLayerSet; //----------------------------------------------------------------------------- // class LLViewerJointMesh //----------------------------------------------------------------------------- -class LLViewerJointMesh : public LLViewerJoint +class LLViewerJointMesh : public LLAvatarJointMesh, public LLViewerJoint { - friend class LLVOAvatar; -protected: - LLColor4 mColor; // color value -// LLColor4 mSpecular; // specular color (always white for now) - F32 mShiny; // shiny value - LLPointer<LLViewerTexture> mTexture; // ptr to a global texture - LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar - U32 mTestImageName; // handle to a temporary texture for previewing uploads - LLPolyMesh* mMesh; // ptr to a global polymesh - BOOL mCullBackFaces; // true by default - LLFace* mFace; // ptr to a face w/ AGP copy of mesh - - U32 mFaceIndexCount; - BOOL mIsTransparent; - - U32 mNumSkinJoints; - LLSkinJoint* mSkinJoints; - S32 mMeshID; - -public: - static BOOL sPipelineRender; - //RN: this is here for testing purposes - static U32 sClothingMaskImageName; - static EAvatarRenderPass sRenderPass; - static LLColor4 sClothingInnerColor; - public: // Constructor LLViewerJointMesh(); @@ -94,67 +50,28 @@ public: // Destructor virtual ~LLViewerJointMesh(); - // Gets the shape color - void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); - - // Sets the shape color - void setColor( F32 red, F32 green, F32 blue, F32 alpha ); - - // Sets the shininess - void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; - - // Sets the shape texture - void setTexture( LLViewerTexture *texture ); - - void setTestTexture( U32 name ) { mTestImageName = name; } - - // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) - void setLayerSet( LLTexLayerSet* layer_set ); - - // Gets the poly mesh - LLPolyMesh *getMesh(); - - // Sets the poly mesh - void setMesh( LLPolyMesh *mesh ); - - // Sets up joint matrix data for rendering - void setupJoint(LLViewerJoint* current_joint); - // Render time method to upload batches of joint matrices void uploadJointMatrices(); - // Sets ID for picking - void setMeshID( S32 id ) {mMeshID = id;} - - // Gets ID for picking - S32 getMeshID() { return mMeshID; } - // overloaded from base class - /*virtual*/ void drawBone(); - /*virtual*/ BOOL isTransparent(); /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ); + // necessary because MS's compiler warns on function inheritance via dominance in the diamond inheritance here. + // warns even though LLViewerJoint holds the only non virtual implementation. + /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) { return LLViewerJoint::render(pixelArea,first_pass,is_dummy);} + /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); /*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate); /*virtual*/ void updateJointGeometry(); /*virtual*/ void dump(); - void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } - /*virtual*/ BOOL isAnimatable() const { return FALSE; } private: //copy mesh into given face's vertex buffer, applying current animation pose static void updateGeometry(LLFace* face, LLPolyMesh* mesh); - -private: - // Allocate skin data - BOOL allocateSkinData( U32 numSkinJoints ); - - // Free skin data - void freeSkinData(); }; #endif // LL_LLVIEWERJOINTMESH_H diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index 4543a1ba9a..297906803b 100755 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -406,11 +406,9 @@ void LLViewerMediaFocus::update() LLViewerObject *viewer_object = getFocusedObject(); S32 face = mFocusedObjectFace; LLVector3 normal = mFocusedObjectNormal; - bool focus = true; if(!media_impl || !viewer_object) { - focus = false; media_impl = getHoverMediaImpl(); viewer_object = getHoverObject(); face = mHoverObjectFace; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 66db0ac8f3..beca08203f 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -125,7 +125,7 @@ #include "llpathfindingmanager.h" #include "boost/unordered_map.hpp" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; typedef LLPointer<LLViewerObject> LLViewerObjectPtr; @@ -1577,11 +1577,26 @@ class LLAdvancedEnableGrabBakedTexture : public view_listener_t /////////////////////// +class LLAdvancedEnableAppearanceToXML : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); + } +}; + class LLAdvancedAppearanceToXML : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLVOAvatar::dumpArchetypeXML(NULL); + std::string emptyname; + LLVOAvatar* avatar = + find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if (!avatar) + { + avatar = gAgentAvatarp; + } + avatar->dumpArchetypeXML(emptyname); return true; } }; @@ -2827,7 +2842,7 @@ class LLSelfRemoveAllAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLAgentWearables::userRemoveAllAttachments(); + LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar(); return true; } }; @@ -6437,23 +6452,21 @@ class LLAttachmentDetachFromPoint : public view_listener_t { bool handleEvent(const LLSD& user_data) { + uuid_vec_t ids_to_remove; const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL); if (attachment->getNumObjects() > 0) { - gMessageSystem->newMessage("ObjectDetach"); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin(); iter != attachment->mAttachedObjects.end(); iter++) { LLViewerObject *attached_object = (*iter); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID()); + ids_to_remove.push_back(attached_object->getAttachmentItemID()); } - gMessageSystem->sendReliable( gAgent.getRegionHost() ); + } + if (!ids_to_remove.empty()) + { + LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); } return true; } @@ -6526,17 +6539,8 @@ class LLAttachmentDetach : public view_listener_t return true; } - // The sendDetach() method works on the list of selected - // objects. Thus we need to clear the list, make sure it only - // contains the object the user clicked, send the message, - // then clear the list. - // We use deselectAll to update the simulator's notion of what's - // selected, and removeAll just to change things locally. - //RN: I thought it was more useful to detach everything that was selected - if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) - { - LLSelectMgr::getInstance()->sendDetach(); - } + LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID()); + return true; } }; @@ -7391,7 +7395,7 @@ void handle_grab_baked_texture(void* data) if(folder_id.notNull()) { std::string name; - name = "Baked " + LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; + name = "Baked " + LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; LLUUID item_id; item_id.generate(); @@ -7650,6 +7654,10 @@ void handle_rebake_textures(void*) // Slam pending upload count to "unstick" things bool slam_for_debug = true; gAgentAvatarp->forceBakeAllTextures(slam_for_debug); + if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) + { + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } } void toggle_visibility(void* user_data) @@ -7932,7 +7940,7 @@ class LLEditTakeOff : public view_listener_t { std::string clothing = userdata.asString(); if (clothing == "all") - LLWearableBridge::removeAllClothesFromAvatar(); + LLAppearanceMgr::instance().removeAllClothesFromAvatar(); else { LLWearableType::EType type = LLWearableType::typeNameToType(clothing); @@ -7942,8 +7950,8 @@ class LLEditTakeOff : public view_listener_t { // MULTI-WEARABLES: assuming user wanted to remove top shirt. U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; - LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,wearable_index)); - LLWearableBridge::removeItemFromAvatar(item); + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); } } @@ -8283,8 +8291,6 @@ void initialize_menus() view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); - - commit.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::showAgentInventory)); enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); // Agent @@ -8503,6 +8509,7 @@ void initialize_menus() // Advanced > Character > Character Tests view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML"); + view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML"); view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry"); view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 01534503f3..143420e227 100755 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -138,6 +138,11 @@ bool handle_go_to(); // Export to XML or Collada void handle_export_selected( void * ); +// Convert strings to internal types +U32 render_type_from_string(std::string render_type); +U32 feature_from_string(std::string feature); +U32 info_display_from_string(std::string info_display); + class LLViewerMenuHolderGL : public LLMenuHolderGL { public: diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a13c793899..3c0d6189ac 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -633,7 +633,6 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain) bool join_group_response(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - BOOL delete_context_data = TRUE; bool accept_invite = false; LLUUID group_id = notification["payload"]["group_id"].asUUID(); @@ -662,7 +661,6 @@ bool join_group_response(const LLSD& notification, const LLSD& response) } else { - delete_context_data = FALSE; LLSD args; args["NAME"] = name; LLNotificationsUtil::add("JoinedTooManyGroupsMember", args, notification["payload"]); @@ -675,7 +673,6 @@ bool join_group_response(const LLSD& notification, const LLSD& response) // sure the user is sure they want to join. if (fee > 0) { - delete_context_data = FALSE; LLSD args; args["COST"] = llformat("%d", fee); // Set the fee for next time to 0, so that we don't keep @@ -3444,7 +3441,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLColor4 color(1.0f, 1.0f, 1.0f, 1.0f); LLUUID from_id; LLUUID owner_id; - BOOL is_owned_by_me = FALSE; LLViewerObject* chatter; msg->getString("ChatData", "FromName", from_name); @@ -3529,13 +3525,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) gAgent.heardChat(chat.mFromID); } } - - is_owned_by_me = chatter->permYouOwner(); } if (is_audible) { - BOOL visible_in_chat_bubble = FALSE; + //BOOL visible_in_chat_bubble = FALSE; color.setVec(1.f,1.f,1.f,1.f); msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); @@ -3618,7 +3612,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) if (!is_muted && !is_do_not_disturb) { - visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles"); + //visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles"); std::string formated_msg = ""; LLViewerChat::formatChatMsg(chat, formated_msg); LLChat chat_bubble = chat; @@ -4958,9 +4952,19 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) // Various hacks that aren't statistics, but are being handled here. // U32 max_tasks_per_region; - U32 region_flags; + U64 region_flags; msg->getU32("Region", "ObjectCapacity", max_tasks_per_region); - msg->getU32("Region", "RegionFlags", region_flags); + + if (msg->has(_PREHASH_RegionInfo)) + { + msg->getU64("RegionInfo", "RegionFlagsExtended", region_flags); + } + else + { + U32 flags = 0; + msg->getU32("Region", "RegionFlags", flags); + region_flags = flags; + } LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b1a60197a2..670272e7be 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2697,24 +2697,33 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS if(ft && (0 == error_code) && (object = gObjectList.findObject(ft->mTaskID))) { - object->loadTaskInvFile(ft->mFilename); + if (object->loadTaskInvFile(ft->mFilename)) + { - LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); - std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; + LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); + std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; - for (; it != end && pending_lst.size(); ++it) - { - LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); - if(item && item->getType() != LLAssetType::AT_CATEGORY) + for (; it != end && pending_lst.size(); ++it) { - std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); - if (id_it != pending_lst.end()) + LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); + if(item && item->getType() != LLAssetType::AT_CATEGORY) { - pending_lst.erase(id_it); + std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + if (id_it != pending_lst.end()) + { + pending_lst.erase(id_it); + } } } } + else + { + // MAINT-2597 - crash when trying to edit a no-mod object + // Somehow get an contents inventory response, but with an invalid stream (possibly 0 size?) + // Stated repro was specific to no-mod objects so failing without user interaction should be safe. + llwarns << "Trying to load invalid task inventory file. Ignoring file contents." << llendl; + } } else { @@ -2726,7 +2735,7 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS delete ft; } -void LLViewerObject::loadTaskInvFile(const std::string& filename) +BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) { std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); llifstream ifs(filename_and_local_path); @@ -2773,8 +2782,11 @@ void LLViewerObject::loadTaskInvFile(const std::string& filename) { llwarns << "unable to load task inventory: " << filename_and_local_path << llendl; + return FALSE; } doInventoryCallback(); + + return TRUE; } void LLViewerObject::doInventoryCallback() @@ -3266,14 +3278,14 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) S32 tex_count = getNumTEs(); for (i = 0; i < tex_count; i++) { - getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (isSculpted() && !isMesh()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (boost_children) @@ -4016,7 +4028,7 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) // if (mDrawable.notNull() && mDrawable->isVisible()) // { const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); // } } @@ -4034,15 +4046,15 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) } } - -S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host) +S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { + const LLUUID& uuid = image->getID(); S32 retval = 0; if (uuid != getTE(te)->getID() || uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + mTEImages[te] = image; setChanged(TEXTURE); if (mDrawable.notNull()) { @@ -4065,7 +4077,9 @@ void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim - return setTETextureCore(te, uuid, LLHost::invalid); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTETextureCore(te,image); } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 97cf0a4850..316dbce7d0 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -301,7 +301,7 @@ public: /*virtual*/ void setNumTEs(const U8 num_tes); /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); - S32 setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host); + S32 setTETextureCore(const U8 te, LLViewerTexture *image); /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); @@ -656,7 +656,7 @@ protected: // static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); - void loadTaskInvFile(const std::string& filename); + BOOL loadTaskInvFile(const std::string& filename); void doInventoryCallback(); BOOL isOnMap(); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 4049e31472..11d34ad084 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -284,7 +284,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { LLFastTimer t(FTM_PROCESS_OBJECTS); - LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); LLViewerObject *objectp; S32 num_objects; U32 local_id; @@ -303,6 +302,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { //llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl; gTerseObjectUpdates += num_objects; + /* S32 size; if (mesgsys->getReceiveCompressedSize()) { @@ -312,10 +312,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { size = mesgsys->getReceiveSize(); } - //llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + */ } else { + /* S32 size; if (mesgsys->getReceiveCompressedSize()) { @@ -326,7 +328,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, size = mesgsys->getReceiveSize(); } - // llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + */ gFullObjectUpdates += num_objects; } @@ -688,12 +691,12 @@ public: } } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { llwarns << "Transport error requesting object cost " - << "HTTP status: " << statusNum << ", reason: " - << reason << "." << llendl; + << "[status: " << statusNum << "]: " + << content << llendl; // TODO*: Error message to user // For now just clear the request from the pending list @@ -777,12 +780,12 @@ public: } } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { llwarns << "Transport error requesting object physics flags " - << "HTTP status: " << statusNum << ", reason: " - << reason << "." << llendl; + << "[status: " << statusNum << "]: " + << content << llendl; // TODO*: Error message to user // For now just clear the request from the pending list diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 90fbc41daa..386b2fd400 100755 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -85,7 +85,6 @@ void LLViewerParcelMedia::update(LLParcel* parcel) } // we're in a parcel - bool new_parcel = false; S32 parcelid = parcel->getLocalID(); LLUUID regionid = gAgent.getRegion()->getRegionID(); @@ -94,7 +93,6 @@ void LLViewerParcelMedia::update(LLParcel* parcel) LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL; sMediaParcelLocalID = parcelid; sMediaRegionID = regionid; - new_parcel = true; } std::string mediaUrl = std::string ( parcel->getMediaURL () ); diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 77e382b8c7..4cdb568d17 100755 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -696,8 +696,8 @@ bool LLViewerParcelMgr::allowAgentScripts(const LLViewerRegion* region, const LL // This mirrors the traditional menu bar parcel icon code, but is not // technically correct. return region - && !(region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) - && !(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) + && !region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS) + && !region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS) && parcel && parcel->getAllowOtherScripts(); } @@ -2057,7 +2057,7 @@ void LLViewerParcelMgr::startReleaseLand() return; } /* - if ((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL) && !gAgent.isGodlike()) { LLSD args; @@ -2302,7 +2302,7 @@ void LLViewerParcelMgr::startDeedLandToGroup() /* if(!gAgent.isGodlike()) { - if((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + if(region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL) && (mCurrentParcel->getOwnerID() != region->getOwner())) { LLSD args; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e4234a538d..b8b53aa6e4 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -142,7 +142,8 @@ public: LLUUID mCacheID; CapabilityMap mCapabilities; - + CapabilityMap mSecondCapabilitiesTracker; + LLEventPoll* mEventPoll; S32 mSeedCapMaxAttempts; @@ -209,9 +210,9 @@ public: virtual ~BaseCapabilitiesComplete() { } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; + LL_WARNS2("AppInit", "Capabilities") << "[status:" << statusNum << ":] " << content << LL_ENDL; LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if (regionp) { @@ -219,7 +220,7 @@ public: } } - void result(const LLSD& content) + void result(const LLSD& content) { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if(!regionp) //region was removed @@ -237,6 +238,7 @@ public: for(iter = content.beginMap(); iter != content.endMap(); ++iter) { regionp->setCapability(iter->first, iter->second); + LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " << iter->first << LL_ENDL; @@ -265,6 +267,62 @@ private: S32 mID; }; +class BaseCapabilitiesCompleteTracker : public LLHTTPClient::Responder +{ + LOG_CLASS(BaseCapabilitiesCompleteTracker); +public: + BaseCapabilitiesCompleteTracker( U64 region_handle) + : mRegionHandle(region_handle) + { } + + virtual ~BaseCapabilitiesCompleteTracker() + { } + + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + { + llwarns << "BaseCapabilitiesCompleteTracker error [status:" + << statusNum << "]: " << content << llendl; + } + + void result(const LLSD& content) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if( !regionp ) + { + return ; + } + LLSD::map_const_iterator iter; + for(iter = content.beginMap(); iter != content.endMap(); ++iter) + { + regionp->setCapabilityDebug(iter->first, iter->second); + //llinfos<<"BaseCapabilitiesCompleteTracker New Caps "<<iter->first<<" "<< iter->second<<llendl; + } + + if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() ) + { + llinfos<<"BaseCapabilitiesCompleteTracker "<<"Sim sent duplicate seed caps that differs in size - most likely content."<<llendl; + //todo#add cap debug versus original check? + /*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin(); + while (iter!=regionp->getRegionImpl()->mCapabilities.end() ) + { + llinfos<<"BaseCapabilitiesCompleteTracker Original "<<iter->first<<" "<< iter->second<<llendl; + ++iter; + } + */ + regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); + } + + } + + static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) + { + return new BaseCapabilitiesCompleteTracker( region_handle ); + } + +private: + U64 mRegionHandle; +}; + LLViewerRegion::LLViewerRegion(const U64 &handle, const LLHost &host, @@ -278,9 +336,11 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mZoning(""), mIsEstateManager(FALSE), mRegionFlags( REGION_FLAGS_DEFAULT ), + mRegionProtocols( 0 ), mSimAccess( SIM_ACCESS_MIN ), mBillableFactor(1.0), mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), + mCentralBakeVersion(0), mClassID(0), mCPURatio(0), mColoName("unknown"), @@ -453,18 +513,6 @@ void LLViewerRegion::sendReliableMessage() gMessageSystem->sendReliable(mImpl->mHost); } -void LLViewerRegion::setFlags(BOOL b, U32 flags) -{ - if (b) - { - mRegionFlags |= flags; - } - else - { - mRegionFlags &= ~flags; - } -} - void LLViewerRegion::setWaterHeight(F32 water_level) { mImpl->mLandp->setWaterHeight(water_level); @@ -477,10 +525,10 @@ F32 LLViewerRegion::getWaterHeight() const BOOL LLViewerRegion::isVoiceEnabled() const { - return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); + return getRegionFlag(REGION_FLAGS_ALLOW_VOICE); } -void LLViewerRegion::setRegionFlags(U32 flags) +void LLViewerRegion::setRegionFlags(U64 flags) { mRegionFlags = flags; } @@ -573,7 +621,7 @@ std::string LLViewerRegion::getLocalizedSimProductName() const } // static -std::string LLViewerRegion::regionFlagsToString(U32 flags) +std::string LLViewerRegion::regionFlagsToString(U64 flags) { std::string result; @@ -1388,7 +1436,8 @@ void LLViewerRegion::unpackRegionHandshake() { LLMessageSystem *msg = gMessageSystem; - U32 region_flags; + U64 region_flags = 0; + U64 region_protocols = 0; U8 sim_access; std::string sim_name; LLUUID sim_owner; @@ -1397,7 +1446,6 @@ void LLViewerRegion::unpackRegionHandshake() F32 billable_factor; LLUUID cache_id; - msg->getU32 ("RegionInfo", "RegionFlags", region_flags); msg->getU8 ("RegionInfo", "SimAccess", sim_access); msg->getString ("RegionInfo", "SimName", sim_name); msg->getUUID ("RegionInfo", "SimOwner", sim_owner); @@ -1406,7 +1454,20 @@ void LLViewerRegion::unpackRegionHandshake() msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); msg->getUUID ("RegionInfo", "CacheID", cache_id ); + if (msg->has(_PREHASH_RegionInfo4)) + { + msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionFlagsExtended, region_flags); + msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionProtocols, region_protocols); + } + else + { + U32 flags = 0; + msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); + region_flags = flags; + } + setRegionFlags(region_flags); + setRegionProtocols(region_protocols); setSimAccess(sim_access); setRegionNameAndZone(sim_name); setOwner(sim_owner); @@ -1445,6 +1506,8 @@ void LLViewerRegion::unpackRegionHandshake() mProductName = productName; } + + mCentralBakeVersion = region_protocols & 1; // was (S32)gSavedSettings.getBOOL("UseServerTextureBaking"); LLVLComposition *compp = getComposition(); if (compp) { @@ -1524,11 +1587,12 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EventQueueGet"); if (gSavedSettings.getBOOL("UseHTTPInventory")) - { + { capabilityNames.append("FetchLib2"); capabilityNames.append("FetchLibDescendents2"); capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); + capabilityNames.append("IncrementCOFVersion"); } capabilityNames.append("GetDisplayNames"); @@ -1542,7 +1606,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("LandResources"); capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); - capabilityNames.append("MeshUploadFlag"); + capabilityNames.append("MeshUploadFlag"); capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("ObjectMedia"); @@ -1571,6 +1635,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateAvatarAppearance"); capabilityNames.append("UpdateGestureAgentInventory"); capabilityNames.append("UpdateGestureTaskInventory"); capabilityNames.append("UpdateNotecardAgentInventory"); @@ -1581,7 +1646,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ViewerMetrics"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); - + // Please add new capabilities alphabetically to reduce // merge conflicts. } @@ -1589,8 +1654,14 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) void LLViewerRegion::setSeedCapability(const std::string& url) { if (getCapability("Seed") == url) - { - // llwarns << "Ignoring duplicate seed capability" << llendl; + { + //llwarns << "Ignoring duplicate seed capability" << llendl; + //Instead of just returning we build up a second set of seed caps and compare them + //to the "original" seed cap received and determine why there is problem! + LLSD capabilityNames = LLSD::emptyArray(); + mImpl->buildCapabilityNames( capabilityNames ); + LLHTTPClient::post( url, capabilityNames, BaseCapabilitiesCompleteTracker::build(getHandle() ), + LLSD(), CAP_REQUEST_TIMEOUT ); return; } @@ -1663,9 +1734,9 @@ public: { } - void error(U32 statusNum, const std::string& reason) + void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) { - LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; + LL_WARNS2("AppInit", "SimulatorFeatures") << "[status:" << statusNum << "]: " << content << LL_ENDL; retry(); } @@ -1726,6 +1797,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u } } +void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url) +{ + mImpl->mSecondCapabilitiesTracker[name] = url; +} + bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) { return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; @@ -1733,6 +1809,11 @@ bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) std::string LLViewerRegion::getCapability(const std::string& name) const { + if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + { + llwarns << "getCapability called before caps received" << llendl; + } + CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); if(iter == mImpl->mCapabilities.end()) { @@ -1792,7 +1873,7 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) // the viewer can not yet distinquish between normal- and estate-owned objects // so we collapse these two bits and enable the UI if either are set -const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT +const U64 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const @@ -1800,7 +1881,7 @@ bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector< return (mParcelOverlay != NULL) && (mParcelOverlay->isOwnedSelf(pos) || mParcelOverlay->isOwnedGroup(pos) - || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) + || (getRegionFlag(ALLOW_RETURN_ENCROACHING_OBJECT) && mParcelOverlay->encroachesOwned(boxes)) ); } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c9fffaf30e..b5fe4677b7 100755 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -109,13 +109,13 @@ public: //void setAgentOffset(const LLVector3d &offset); void updateRenderMatrix(); - void setAllowDamage(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_DAMAGE); } - void setAllowLandmark(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_LANDMARK); } - void setAllowSetHome(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_SET_HOME); } - void setResetHomeOnTeleport(BOOL b) { setFlags(b, REGION_FLAGS_RESET_HOME_ON_TELEPORT); } - void setSunFixed(BOOL b) { setFlags(b, REGION_FLAGS_SUN_FIXED); } - void setBlockFly(BOOL b) { setFlags(b, REGION_FLAGS_BLOCK_FLY); } - void setAllowDirectTeleport(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_DIRECT_TELEPORT); } + void setAllowDamage(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DAMAGE, b); } + void setAllowLandmark(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_LANDMARK, b); } + void setAllowSetHome(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_SET_HOME, b); } + void setResetHomeOnTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_RESET_HOME_ON_TELEPORT, b); } + void setSunFixed(BOOL b) { setRegionFlag(REGION_FLAGS_SUN_FIXED, b); } + void setBlockFly(BOOL b) { setRegionFlag(REGION_FLAGS_BLOCK_FLY, b); } + void setAllowDirectTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, b); } inline BOOL getAllowDamage() const; @@ -156,8 +156,15 @@ public: LLViewerParcelOverlay *getParcelOverlay() const { return mParcelOverlay; } - void setRegionFlags(U32 flags); - U32 getRegionFlags() const { return mRegionFlags; } + inline void setRegionFlag(U64 flag, BOOL on); + inline BOOL getRegionFlag(U64 flag) const; + void setRegionFlags(U64 flags); + U64 getRegionFlags() const { return mRegionFlags; } + + inline void setRegionProtocol(U64 protocol, BOOL on); + BOOL getRegionProtocol(U64 protocol) const; + void setRegionProtocols(U64 protocols) { mRegionProtocols = protocols; } + U64 getRegionProtocols() const { return mRegionProtocols; } void setTimeDilation(F32 time_dilation); F32 getTimeDilation() const { return mTimeDilation; } @@ -195,7 +202,7 @@ public: std::string getLocalizedSimProductName() const; // Returns "Sandbox", "Expensive", etc. - static std::string regionFlagsToString(U32 flags); + static std::string regionFlagsToString(U64 flags); // Returns translated version of "Mature", "PG", "Adult", etc. static std::string accessToString(U8 sim_access); @@ -234,6 +241,7 @@ public: void failedSeedCapability(); S32 getNumSeedCapRetries(); void setCapability(const std::string& name, const std::string& url); + void setCapabilityDebug(const std::string& name, const std::string& url); // implements LLCapabilityProvider virtual std::string getCapability(const std::string& name) const; @@ -278,6 +286,8 @@ public: F32 getLandHeightRegion(const LLVector3& region_pos); + U8 getCentralBakeVersion() { return mCentralBakeVersion; } + void getInfo(LLSD& info); bool meshRezEnabled() const; @@ -330,7 +340,9 @@ public: void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ); void getNeighboringRegionsStatus( std::vector<S32>& regions ); - + const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } + LLViewerRegionImpl * getRegionImplNC() { return mImpl; } + public: struct CompareDistance { @@ -345,7 +357,6 @@ public: protected: void disconnectAllNeighbors(); void initStats(); - void setFlags(BOOL b, U32 flags); public: LLWind mWind; @@ -390,11 +401,13 @@ private: U32 mPingDelay; F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc - U32 mRegionFlags; // includes damage flags + U64 mRegionFlags; // includes damage flags + U64 mRegionProtocols; // protocols supported by this region U8 mSimAccess; F32 mBillableFactor; U32 mMaxTasks; // max prim count F32 mCameraDistanceSquared; // updated once per frame + U8 mCentralBakeVersion; // Information for Homestead / CR-53 S32 mClassID; @@ -423,6 +436,40 @@ private: LLSD mSimulatorFeatures; }; +inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const +{ + return ((mRegionProtocols & protocol) != 0); +} + +inline void LLViewerRegion::setRegionProtocol(U64 protocol, BOOL on) +{ + if (on) + { + mRegionProtocols |= protocol; + } + else + { + mRegionProtocols &= ~protocol; + } +} + +inline BOOL LLViewerRegion::getRegionFlag(U64 flag) const +{ + return ((mRegionFlags & flag) != 0); +} + +inline void LLViewerRegion::setRegionFlag(U64 flag, BOOL on) +{ + if (on) + { + mRegionFlags |= flag; + } + else + { + mRegionFlags &= ~flag; + } +} + inline BOOL LLViewerRegion::getAllowDamage() const { return ((mRegionFlags & REGION_FLAGS_ALLOW_DAMAGE) !=0); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index d6dd645e8c..e3d28f2f5c 100755 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -229,7 +229,6 @@ extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; -extern LLGLSLShader gAlphaMaskProgram; //output tex0[tc0] + tex1[tc1] extern LLGLSLShader gTwoTextureAddProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 35839ae459..35bba4184e 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -752,25 +752,6 @@ void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name) timer.unpause(); } -void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name) -{ - phase_map_t::iterator iter = mPhaseMap.find(phase_name); - if (iter != mPhaseMap.end()) - { - if (iter->second.getStarted()) - { - // Going from started to paused state - record stats. - recordPhaseStat(phase_name,iter->second.getElapsedTimeF32()); - } - lldebugs << "stopPhase " << phase_name << llendl; - iter->second.pause(); - } - else - { - lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl; - } -} - void LLViewerStats::PhaseMap::stopAllPhases() { for (phase_map_t::iterator iter = mPhaseMap.begin(); @@ -814,6 +795,19 @@ LLViewerStats::PhaseMap::PhaseMap() { } + +void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter != mPhaseMap.end()) + { + if (iter->second.getStarted()) + { + // Going from started to stopped state - record stats. + iter->second.stop(); + } + } +} // static LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) { @@ -833,3 +827,18 @@ void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32 stats.push(value); } + +bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter != mPhaseMap.end()) + { + elapsed = iter->second.getElapsedTimeF32(); + completed = !iter->second.getStarted(); + return true; + } + else + { + return false; + } +} diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index e02a4ccdc7..6b2461be41 100755 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -289,6 +289,7 @@ public: public: PhaseMap(); LLFrameTimer& getPhaseTimer(const std::string& phase_name); + bool getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed); void startPhase(const std::string& phase_name); void stopPhase(const std::string& phase_name); void stopAllPhases(); @@ -296,8 +297,11 @@ public: LLSD dumpPhases(); static StatsAccumulator& getPhaseStats(const std::string& phase_name); static void recordPhaseStat(const std::string& phase_name, F32 value); + phase_map_t::iterator begin() { return mPhaseMap.begin(); } + phase_map_t::iterator end() { return mPhaseMap.end(); } }; + private: F64 mStats[ST_COUNT]; diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp new file mode 100755 index 0000000000..777e1f9c76 --- /dev/null +++ b/indra/newview/llviewertexlayer.cpp @@ -0,0 +1,748 @@ +/** + * @file llviewertexlayer.cpp + * @brief Viewer texture layer. Used for avatars. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewertexlayer.h" + +#include "llagent.h" +#include "llimagej2c.h" +#include "llnotificationsutil.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llviewerregion.h" +#include "llglslshader.h" +#include "llvoavatarself.h" +#include "pipeline.h" +#include "llassetuploadresponders.h" +#include "llviewercontrol.h" + +static const S32 BAKE_UPLOAD_ATTEMPTS = 7; +static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt + +// runway consolidate +extern std::string self_av_string(); + + +//----------------------------------------------------------------------------- +// LLBakedUploadData() +//----------------------------------------------------------------------------- +LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLViewerTexLayerSet* layerset, + const LLUUID& id, + bool highest_res) : + mAvatar(avatar), + mTexLayerSet(layerset), + mID(id), + mStartTime(LLFrameTimer::getTotalTime()), // Record starting time + mIsHighestRes(highest_res) +{ +} + +//----------------------------------------------------------------------------- +// LLViewerTexLayerSetBuffer +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. +//----------------------------------------------------------------------------- + +// static +S32 LLViewerTexLayerSetBuffer::sGLByteCount = 0; + +LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner, + S32 width, S32 height) : + // ORDER_LAST => must render these after the hints are created. + LLTexLayerSetBuffer(owner), + LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), + mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates + mNeedsUpload(FALSE), + mNumLowresUploads(0), + mUploadFailCount(0), + mNeedsUpdate(TRUE), + mNumLowresUpdates(0) +{ + LLViewerTexLayerSetBuffer::sGLByteCount += getSize(); + mNeedsUploadTimer.start(); + mNeedsUpdateTimer.start(); +} + +LLViewerTexLayerSetBuffer::~LLViewerTexLayerSetBuffer() +{ + LLViewerTexLayerSetBuffer::sGLByteCount -= getSize(); + destroyGLTexture(); + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. + } +} + +//virtual +S8 LLViewerTexLayerSetBuffer::getType() const +{ + return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ; +} + +//virtual +void LLViewerTexLayerSetBuffer::restoreGLTexture() +{ + LLViewerDynamicTexture::restoreGLTexture() ; +} + +//virtual +void LLViewerTexLayerSetBuffer::destroyGLTexture() +{ + LLViewerDynamicTexture::destroyGLTexture() ; +} + +// static +void LLViewerTexLayerSetBuffer::dumpTotalByteCount() +{ + llinfos << "Composite System GL Buffers: " << (LLViewerTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; +} + +void LLViewerTexLayerSetBuffer::requestUpdate() +{ + restartUpdateTimer(); + mNeedsUpdate = TRUE; + mNumLowresUpdates = 0; + // If we're in the middle of uploading a baked texture, we don't care about it any more. + // When it's downloaded, ignore it. + mUploadID.setNull(); +} + +void LLViewerTexLayerSetBuffer::requestUpload() +{ + conditionalRestartUploadTimer(); + mNeedsUpload = TRUE; + mNumLowresUploads = 0; + mUploadPending = TRUE; +} + +void LLViewerTexLayerSetBuffer::conditionalRestartUploadTimer() +{ + // If we requested a new upload but haven't even uploaded + // a low res version of our last upload request, then + // keep the timer ticking instead of resetting it. + if (mNeedsUpload && (mNumLowresUploads == 0)) + { + mNeedsUploadTimer.unpause(); + } + else + { + mNeedsUploadTimer.reset(); + mNeedsUploadTimer.start(); + } +} + +void LLViewerTexLayerSetBuffer::restartUpdateTimer() +{ + mNeedsUpdateTimer.reset(); + mNeedsUpdateTimer.start(); +} + +void LLViewerTexLayerSetBuffer::cancelUpload() +{ + mNeedsUpload = FALSE; + mUploadPending = FALSE; + mNeedsUploadTimer.pause(); + mUploadRetryTimer.reset(); +} + +// virtual +BOOL LLViewerTexLayerSetBuffer::needsRender() +{ + llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp); + if (!isAgentAvatarValid()) return FALSE; + + const BOOL upload_now = mNeedsUpload && isReadyToUpload(); + const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); + + // Don't render if we don't want to (or aren't ready to) upload or update. + if (!(update_now || upload_now)) + { + return FALSE; + } + + // Don't render if we're animating our appearance. + if (gAgentAvatarp->getIsAppearanceAnimating()) + { + return FALSE; + } + + // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. + if (gAgentAvatarp->getBakedTE(getViewerTexLayerSet()) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && + !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) + { + cancelUpload(); + return FALSE; + } + + // Render if we have at least minimal level of detail for each local texture. + return getViewerTexLayerSet()->isLocalTextureDataAvailable(); +} + +// virtual +void LLViewerTexLayerSetBuffer::preRenderTexLayerSet() +{ + LLTexLayerSetBuffer::preRenderTexLayerSet(); + + // keep depth buffer, we don't need to clear it + LLViewerDynamicTexture::preRender(FALSE); +} + +// virtual +void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) +{ + + LLTexLayerSetBuffer::postRenderTexLayerSet(success); + LLViewerDynamicTexture::postRender(success); +} + +// virtual +void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success) +{ + // do we need to upload, and do we have sufficient data to create an uploadable composite? + // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero? + const BOOL upload_now = mNeedsUpload && isReadyToUpload(); + const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); + + if(upload_now) + { + if (!success) + { + llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl; + mUploadPending = FALSE; + } + else + { + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + if (layer_set->isVisible()) + { + layer_set->getAvatar()->debugBakedTextureUpload(layer_set->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. + doUpload(); + } + else + { + mUploadPending = FALSE; + mNeedsUpload = FALSE; + mNeedsUploadTimer.pause(); + layer_set->getAvatar()->setNewBakedTexture(layer_set->getBakedTexIndex(),IMG_INVISIBLE); + } + } + } + + if (update_now) + { + doUpdate(); + } + + // *TODO: Old logic does not check success before setGLTextureCreated + // we have valid texture data now + mGLTexturep->setGLTextureCreated(true); +} + +BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const +{ + return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); +} + +BOOL LLViewerTexLayerSetBuffer::uploadPending() const +{ + return mUploadPending; +} + +BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const +{ + return mNeedsUpload; +} + +BOOL LLViewerTexLayerSetBuffer::uploadInProgress() const +{ + return !mUploadID.isNull(); +} + +BOOL LLViewerTexLayerSetBuffer::isReadyToUpload() const +{ + if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) return FALSE; // Don't upload if avatar is being edited. + + BOOL ready = FALSE; + if (getViewerTexLayerSet()->isLocalTextureDataFinal()) + { + // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) + if (mUploadFailCount == 0) + { + ready = TRUE; + } + else + { + ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1)); + } + } + else + { + // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure + // we aren't doing uploads too frequently. + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); + if (texture_timeout != 0) + { + // The timeout period increases exponentially between every lowres upload in order to prevent + // spamming the server with frequent uploads. + const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); + + // If we hit our timeout and have textures available at even lower resolution, then upload. + const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; + const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable(); + ready = has_lower_lod && is_upload_textures_timeout; + } + } + + return ready; +} + +BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const +{ + // If we requested an update and have the final LOD ready, then update. + if (getViewerTexLayerSet()->isLocalTextureDataFinal()) return TRUE; + + // If we haven't done an update yet, then just do one now regardless of state of textures. + if (mNumLowresUpdates == 0) return TRUE; + + // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small + // since render unnecessarily doesn't cost much. + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout"); + if (texture_timeout != 0) + { + // If we hit our timeout and have textures available at even lower resolution, then update. + const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; + const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable(); + if (has_lower_lod && is_update_textures_timeout) return TRUE; + } + + return FALSE; +} + +BOOL LLViewerTexLayerSetBuffer::requestUpdateImmediate() +{ + mNeedsUpdate = TRUE; + BOOL result = FALSE; + + if (needsRender()) + { + preRender(FALSE); + result = render(); + postRender(result); + } + + return result; +} + +// Create the baked texture, send it out to the server, then wait for it to come +// back so we can switch to using it. +void LLViewerTexLayerSetBuffer::doUpload() +{ + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + LL_DEBUGS("Avatar") << "Uploading baked " << layer_set->getBodyRegionName() << llendl; + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); + + // Don't need caches since we're baked now. (note: we won't *really* be baked + // until this image is sent to the server and the Avatar Appearance message is received.) + layer_set->deleteCaches(); + + // Get the COLOR information from our texture + U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; + glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); + stop_glerror(); + + // Get the MASK information from our texture + LLGLSUIDefault gls_ui; + LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); + U8* baked_mask_data = baked_mask_image->getData(); + layer_set->gatherMorphMaskAlpha(baked_mask_data, + mOrigin.mX, mOrigin.mY, + mFullWidth, mFullHeight); + + + // Create the baked image from our color and mask information + const S32 baked_image_components = 5; // red green blue [bump] clothing + LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); + U8* baked_image_data = baked_image->getData(); + S32 i = 0; + for (S32 u=0; u < mFullWidth; u++) + { + for (S32 v=0; v < mFullHeight; v++) + { + baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; + baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; + baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; + baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. + baked_image_data[5*i + 4] = baked_mask_data[i]; + i++; + } + } + + LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; + const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) + if (compressedImage->encode(baked_image, comment_text)) + { + LLTransactionID tid; + tid.generate(); + const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), + gVFS, asset_id, LLAssetType::AT_TEXTURE)) + { + // Read back the file and validate. + BOOL valid = FALSE; + LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; + S32 file_size = 0; + LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE); + file_size = file.getSize(); + U8* data = integrity_test->allocateData(file_size); + file.read(data, file_size); + if (data) + { + valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' + } + else + { + integrity_test->setLastError("Unable to read entire file"); + } + + if (valid) + { + const bool highest_lod = layer_set->isLocalTextureDataFinal(); + // Baked_upload_data is owned by the responder and deleted after the request completes. + LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, + layer_set, + asset_id, + highest_lod); + // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. + mUploadID = asset_id; + + // Upload the image + const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); + if(!url.empty() + && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method + && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. + { + LLSD body = LLSD::emptyMap(); + // The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete() + LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); + llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; + } + else + { + gAssetStorage->storeAssetData(tid, + LLAssetType::AT_TEXTURE, + LLViewerTexLayerSetBuffer::onTextureUploadComplete, + baked_upload_data, + TRUE, // temp_file + TRUE, // is_priority + TRUE); // store_local + llinfos << "Baked texture upload via Asset Store." << llendl; + } + + if (highest_lod) + { + // Sending the final LOD for the baked texture. All done, pause + // the upload timer so we know how long it took. + mNeedsUpload = FALSE; + mNeedsUploadTimer.pause(); + } + else + { + // Sending a lower level LOD for the baked texture. Restart the upload timer. + mNumLowresUploads++; + mNeedsUploadTimer.unpause(); + mNeedsUploadTimer.reset(); + } + + // Print out notification that we uploaded this texture. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); + args["BODYREGION"] = layer_set->getBodyRegionName(); + args["RESOLUTION"] = lod_str; + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); + LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + } + } + else + { + // The read back and validate operation failed. Remove the uploaded file. + mUploadPending = FALSE; + LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); + file.remove(); + llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl; + } + } + } + else + { + // The VFS write file operation failed. + mUploadPending = FALSE; + llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl; + } + + delete [] baked_color_data; +} + +// Mostly bookkeeping; don't need to actually "do" anything since +// render() will actually do the update. +void LLViewerTexLayerSetBuffer::doUpdate() +{ + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + const BOOL highest_lod = layer_set->isLocalTextureDataFinal(); + if (highest_lod) + { + mNeedsUpdate = FALSE; + } + else + { + mNumLowresUpdates++; + } + + restartUpdateTimer(); + + // need to switch to using this layerset if this is the first update + // after getting the lowest LOD + layer_set->getAvatar()->updateMeshTextures(); + + // Print out notification that we updated this texture. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + const BOOL highest_lod = layer_set->isLocalTextureDataFinal(); + const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); + args["BODYREGION"] = layer_set->getBodyRegionName(); + args["RESOLUTION"] = lod_str; + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); + LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + } +} + +// static +void LLViewerTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (not fixed) +{ + LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; + + if (isAgentAvatarValid() && + !gAgentAvatarp->isDead() && + (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures. + (baked_upload_data->mTexLayerSet->hasComposite())) + { + LLViewerTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getViewerComposite(); + S32 failures = layerset_buffer->mUploadFailCount; + layerset_buffer->mUploadFailCount = 0; + + if (layerset_buffer->mUploadID.isNull()) + { + // The upload got canceled, we should be in the + // process of baking a new texture so request an + // upload with the new data + + // BAP: does this really belong in this callback, as + // opposed to where the cancellation takes place? + // suspect this does nothing. + layerset_buffer->requestUpload(); + } + else if (baked_upload_data->mID == layerset_buffer->mUploadID) + { + // This is the upload we're currently waiting for. + layerset_buffer->mUploadID.setNull(); + const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName()); + const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res "; + if (result >= 0) + { + layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later + LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->getViewerTexLayerSet()); + // Update baked texture info with the new UUID + U64 now = LLFrameTimer::getTotalTime(); // Record starting time + llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; + gAgentAvatarp->setNewBakedTexture(baked_te, uuid); + } + else + { + ++failures; + S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes + llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl; + if (failures < max_attempts) + { + layerset_buffer->mUploadFailCount = failures; + layerset_buffer->mUploadRetryTimer.start(); + layerset_buffer->requestUpload(); + } + } + } + else + { + llinfos << "Received baked texture out of date, ignored." << llendl; + } + + gAgentAvatarp->dirtyMesh(); + } + else + { + // Baked texture failed to upload (in which case since we + // didn't set the new baked texture, it means that they'll try + // and rebake it at some point in the future (after login?)), + // or this response to upload is out of date, in which case a + // current response should be on the way or already processed. + llwarns << "Baked upload failed" << llendl; + } + + delete baked_upload_data; +} + +//----------------------------------------------------------------------------- +// LLViewerTexLayerSet +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +LLViewerTexLayerSet::LLViewerTexLayerSet(LLAvatarAppearance* const appearance) : + LLTexLayerSet(appearance), + mUpdatesEnabled( FALSE ) +{ +} + +// virtual +LLViewerTexLayerSet::~LLViewerTexLayerSet() +{ +} + +// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. +BOOL LLViewerTexLayerSet::isLocalTextureDataAvailable() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + return getAvatar()->isLocalTextureDataAvailable(this); +} + + +// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. +BOOL LLViewerTexLayerSet::isLocalTextureDataFinal() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + return getAvatar()->isLocalTextureDataFinal(this); +} + +// virtual +void LLViewerTexLayerSet::requestUpdate() +{ + if( mUpdatesEnabled ) + { + createComposite(); + getViewerComposite()->requestUpdate(); + } +} + +void LLViewerTexLayerSet::requestUpload() +{ + createComposite(); + getViewerComposite()->requestUpload(); +} + +void LLViewerTexLayerSet::cancelUpload() +{ + if(mComposite) + { + getViewerComposite()->cancelUpload(); + } +} + +void LLViewerTexLayerSet::updateComposite() +{ + createComposite(); + getViewerComposite()->requestUpdateImmediate(); +} + +// virtual +void LLViewerTexLayerSet::createComposite() +{ + if(!mComposite) + { + S32 width = mInfo->getWidth(); + S32 height = mInfo->getHeight(); + // Composite other avatars at reduced resolution + if( !mAvatarAppearance->isSelf() ) + { + llerrs << "composites should not be created for non-self avatars!" << llendl; + } + mComposite = new LLViewerTexLayerSetBuffer( this, width, height ); + } +} + +void LLViewerTexLayerSet::setUpdatesEnabled( BOOL b ) +{ + mUpdatesEnabled = b; +} + +LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() +{ + return dynamic_cast<LLVOAvatarSelf*> (mAvatarAppearance); +} + +const LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const +{ + return dynamic_cast<const LLVOAvatarSelf*> (mAvatarAppearance); +} + +LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() +{ + return dynamic_cast<LLViewerTexLayerSetBuffer*> (getComposite()); +} + +const LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() const +{ + return dynamic_cast<const LLViewerTexLayerSetBuffer*> (getComposite()); +} + + +const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const +{ + if (!isAgentAvatarValid()) return ""; + + const BOOL is_high_res = !mNeedsUpload; + const U32 num_low_res = mNumLowresUploads; + const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32(); + const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet()); + + std::string status = "CREATING "; + if (!uploadNeeded()) status = "DONE "; + if (uploadInProgress()) status = "UPLOADING"; + + std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s", + status.c_str(), + is_high_res, num_low_res, + upload_time, + local_texture_info.c_str()); + return text; +} diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h new file mode 100644 index 0000000000..959c883da8 --- /dev/null +++ b/indra/newview/llviewertexlayer.h @@ -0,0 +1,180 @@ +/** + * @file llviewertexlayer.h + * @brief Viewer Texture layer classes. Used for avatars. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_VIEWER_TEXLAYER_H +#define LL_VIEWER_TEXLAYER_H + +#include "lldynamictexture.h" +#include "llextendedstatus.h" +#include "lltexlayer.h" + +class LLVOAvatarSelf; +class LLViewerTexLayerSetBuffer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLViewerTexLayerSet +// +// An ordered set of texture layers that gets composited into a single texture. +// Only exists for llavatarappearanceself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLViewerTexLayerSet : public LLTexLayerSet +{ +public: + LLViewerTexLayerSet(LLAvatarAppearance* const appearance); + virtual ~LLViewerTexLayerSet(); + + /*virtual*/void requestUpdate(); + void requestUpload(); + void cancelUpload(); + BOOL isLocalTextureDataAvailable() const; + BOOL isLocalTextureDataFinal() const; + void updateComposite(); + /*virtual*/void createComposite(); + void setUpdatesEnabled(BOOL b); + BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } + + LLVOAvatarSelf* getAvatar(); + const LLVOAvatarSelf* getAvatar() const; + LLViewerTexLayerSetBuffer* getViewerComposite(); + const LLViewerTexLayerSetBuffer* getViewerComposite() const; + +private: + BOOL mUpdatesEnabled; + +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLViewerTexLayerSetBuffer +// +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDynamicTexture +{ + LOG_CLASS(LLViewerTexLayerSetBuffer); + +public: + LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); + virtual ~LLViewerTexLayerSetBuffer(); + +public: + /*virtual*/ S8 getType() const; + BOOL isInitialized(void) const; + static void dumpTotalByteCount(); + const std::string dumpTextureInfo() const; + virtual void restoreGLTexture(); + virtual void destroyGLTexture(); +private: + LLViewerTexLayerSet* getViewerTexLayerSet() + { return dynamic_cast<LLViewerTexLayerSet*> (mTexLayerSet); } + const LLViewerTexLayerSet* getViewerTexLayerSet() const + { return dynamic_cast<const LLViewerTexLayerSet*> (mTexLayerSet); } + static S32 sGLByteCount; + + //-------------------------------------------------------------------- + // Tex Layer Render + //-------------------------------------------------------------------- + virtual void preRenderTexLayerSet(); + virtual void midRenderTexLayerSet(BOOL success); + virtual void postRenderTexLayerSet(BOOL success); + virtual S32 getCompositeOriginX() const { return getOriginX(); } + virtual S32 getCompositeOriginY() const { return getOriginY(); } + virtual S32 getCompositeWidth() const { return getFullWidth(); } + virtual S32 getCompositeHeight() const { return getFullHeight(); } + + //-------------------------------------------------------------------- + // Dynamic Texture Interface + //-------------------------------------------------------------------- +public: + /*virtual*/ BOOL needsRender(); +protected: + // Pass these along for tex layer rendering. + virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); } + virtual void postRender(BOOL success) { postRenderTexLayerSet(success); } + virtual BOOL render() { return renderTexLayerSet(); } + + //-------------------------------------------------------------------- + // Uploads + //-------------------------------------------------------------------- +public: + void requestUpload(); + void cancelUpload(); + BOOL uploadNeeded() const; // We need to upload a new texture + BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result + BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point + static void onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, LLExtStat ext_status); +protected: + BOOL isReadyToUpload() const; + void doUpload(); // Does a read back and upload. + void conditionalRestartUploadTimer(); +private: + BOOL mNeedsUpload; // Whether we need to send our baked textures to the server + U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server + BOOL mUploadPending; // Whether we have received back the new baked textures + LLUUID mUploadID; // The current upload process (null if none). + LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed. + S32 mUploadFailCount; // Number of consecutive upload failures + LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure. + + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- +public: + void requestUpdate(); + BOOL requestUpdateImmediate(); +protected: + BOOL isReadyToUpdate() const; + void doUpdate(); + void restartUpdateTimer(); +private: + BOOL mNeedsUpdate; // Whether we need to locally update our baked textures + U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures + LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed. +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLBakedUploadData +// +// Used by LLTexLayerSetBuffer for a callback. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +struct LLBakedUploadData +{ + LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLViewerTexLayerSet* layerset, + const LLUUID& id, + bool highest_res); + ~LLBakedUploadData() {} + const LLUUID mID; + const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer + LLViewerTexLayerSet* mTexLayerSet; + const U64 mStartTime; // for measuring baked texture upload time + const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res +}; + +#endif // LL_VIEWER_TEXLAYER_H + diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 122d8f4a96..8036a4e258 100755 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -1052,8 +1052,6 @@ void LLViewerTextEditor::findEmbeddedItemSegments(S32 start, S32 end) { LLWString text = getWText(); - LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() ); - // Start with i just after the first embedded item for(S32 idx = start; idx < end; idx++ ) { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 08fcb60d03..eb6c453e76 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -58,6 +58,7 @@ #include "lltextureatlas.h" #include "lltextureatlasmanager.h" #include "lltextureentry.h" +#include "lltexturemanagerbridge.h" #include "llmediaentry.h" #include "llvovolume.h" #include "llviewermedia.h" @@ -231,7 +232,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipma if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } @@ -241,14 +242,14 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) @@ -257,13 +258,14 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -271,11 +273,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( LLGLenum primary_format, LLHost request_from_host) { - return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + return gTextureList.getImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( - const std::string& filename, + const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -283,11 +286,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( LLGLenum primary_format, const LLUUID& force_id) { - return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromFile(filename, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; } //static -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -296,14 +300,34 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const s const LLUUID& force_id ) { - return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) { - return gTextureList.getImageFromHost(image_id, host) ; + return gTextureList.getImageFromHost(image_id, f_type, host) ; } +// Create a bridge to the viewer texture manager. +class LLViewerTextureManagerBridge : public LLTextureManagerBridge +{ + /*virtual*/ LLPointer<LLGLTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(usemipmaps, generate_gl_tex); + } + + /*virtual*/ LLPointer<LLGLTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(width, height, components, usemipmaps, generate_gl_tex); + } + + /*virtual*/ LLGLTexture* getFetchedTexture(const LLUUID &image_id) + { + return LLViewerTextureManager::getFetchedTexture(image_id); + } +}; + + void LLViewerTextureManager::init() { { @@ -349,12 +373,12 @@ void LLViewerTextureManager::init() imagep->setCachedRawImage(0, image_raw) ; image_raw = NULL; #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); #endif LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); - LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ; + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER) ; - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; image_raw = new LLImageRaw(32,32,3); @@ -373,6 +397,9 @@ void LLViewerTextureManager::init() LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); LLViewerTexture::initClass() ; + + // Create a texture manager bridge. + gTextureManagerBridgep = new LLViewerTextureManagerBridge; if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) { @@ -389,6 +416,7 @@ void LLViewerTextureManager::cleanup() { stop_glerror(); + delete gTextureManagerBridgep; LLImageGL::sDefaultGLTexture = NULL ; LLViewerTexture::sNullImagep = NULL; LLViewerTexture::sBlackImagep = NULL; @@ -416,25 +444,6 @@ void LLViewerTexture::initClass() } } -// static -S32 LLViewerTexture::getTotalNumOfCategories() -{ - return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; -} - -// static -//index starts from zero. -S32 LLViewerTexture::getIndexFromCategory(S32 category) -{ - return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; -} - -//static -S32 LLViewerTexture::getCategoryFromIndex(S32 index) -{ - return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; -} - // tuning params const F32 discard_bias_delta = .25f; const F32 discard_delta_time = 0.5f; @@ -571,70 +580,54 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity //------------------------------------------------------------------------------------------- const U32 LLViewerTexture::sCurrentFileVersion = 1; -LLViewerTexture::LLViewerTexture(BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(BOOL usemipmaps) : + LLGLTexture(usemipmaps) { init(true); - mUseMipMaps = usemipmaps ; mID.generate(); sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) - : mID(id) +LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) : + LLGLTexture(usemipmaps), + mID(id) { init(true); - mUseMipMaps = usemipmaps ; sImageCount++; } -LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) : + LLGLTexture(width, height, components, usemipmaps) { init(true); - mFullWidth = width ; - mFullHeight = height ; - mUseMipMaps = usemipmaps ; - mComponents = components ; - setTexelsPerImage(); - mID.generate(); sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : + LLGLTexture(raw, usemipmaps) { init(true); - mUseMipMaps = usemipmaps ; - mGLTexturep = new LLImageGL(raw, usemipmaps) ; - // Create an empty image of the specified size and width mID.generate(); sImageCount++; } LLViewerTexture::~LLViewerTexture() { + // LL_DEBUGS("Avatar") << mID << llendl; cleanup(); sImageCount--; } +// virtual void LLViewerTexture::init(bool firstinit) { - mBoostLevel = LLViewerTexture::BOOST_NONE; mSelectedTime = 0.f; - - mFullWidth = 0; - mFullHeight = 0; - mTexelsPerImage = 0 ; - mUseMipMaps = FALSE ; - mComponents = 0 ; - - mTextureState = NO_DELETE ; - mDontDiscard = FALSE; mMaxVirtualSize = 0.f; - mNeedsGLTexture = FALSE ; mMaxVirtualSizeResetInterval = 1; mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ; mAdditionalDecodePriority = 0.f ; @@ -655,19 +648,12 @@ void LLViewerTexture::cleanup() { mFaceList.clear() ; mVolumeList.clear(); - if(mGLTexturep) - { - mGLTexturep->cleanup(); - } } // virtual void LLViewerTexture::dump() { - if(mGLTexturep) - { - mGLTexturep->dump(); - } + LLGLTexture::dump(); llinfos << "LLViewerTexture" << " mID " << mID @@ -690,10 +676,8 @@ void LLViewerTexture::setBoostLevel(S32 level) { mSelectedTime = gFrameTimeSeconds; } - } - bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -886,294 +870,18 @@ void LLViewerTexture::reorganizeVolumeList() mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end()); } - - //virtual void LLViewerTexture::switchToCachedImage() { //nothing here. } -void LLViewerTexture::forceActive() -{ - mTextureState = ACTIVE ; -} - -void LLViewerTexture::setActive() -{ - if(mTextureState != NO_DELETE) - { - mTextureState = ACTIVE ; - } -} - -//set the texture to stay in memory -void LLViewerTexture::setNoDelete() -{ - mTextureState = NO_DELETE ; -} - -void LLViewerTexture::generateGLTexture() -{ - if(mGLTexturep.isNull()) - { - mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; - } -} - -LLImageGL* LLViewerTexture::getGLTexture() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep ; -} - -BOOL LLViewerTexture::createGLTexture() -{ - if(mGLTexturep.isNull()) - { - generateGLTexture() ; - } - - return mGLTexturep->createGLTexture() ; -} - -BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) -{ - llassert(mGLTexturep.notNull()) ; - - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; - - if(ret) - { - mFullWidth = mGLTexturep->getCurrentWidth() ; - mFullHeight = mGLTexturep->getCurrentHeight() ; - mComponents = mGLTexturep->getComponents() ; - setTexelsPerImage(); - } - - return ret ; -} - //virtual void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { //nothing here. } -void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; -} -void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) -{ - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setAddressMode(mode) ; -} -void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) -{ - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setFilteringOption(option) ; -} - -//virtual -S32 LLViewerTexture::getWidth(S32 discard_level) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getWidth(discard_level) ; -} - -//virtual -S32 LLViewerTexture::getHeight(S32 discard_level) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getHeight(discard_level) ; -} - -S32 LLViewerTexture::getMaxDiscardLevel() const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMaxDiscardLevel() ; -} -S32 LLViewerTexture::getDiscardLevel() const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getDiscardLevel() ; -} -S8 LLViewerTexture::getComponents() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getComponents() ; -} - -LLGLuint LLViewerTexture::getTexName() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexName() ; -} - -BOOL LLViewerTexture::hasGLTexture() const -{ - if(mGLTexturep.notNull()) - { - return mGLTexturep->getHasGLTexture() ; - } - return FALSE ; -} - -BOOL LLViewerTexture::getBoundRecently() const -{ - if(mGLTexturep.notNull()) - { - return mGLTexturep->getBoundRecently() ; - } - return FALSE ; -} - -LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTarget() ; -} - -BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; -} - -BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; -} - -void LLViewerTexture::setGLTextureCreated (bool initialized) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setGLTextureCreated (initialized) ; -} - -void LLViewerTexture::setCategory(S32 category) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setCategory(category) ; -} - -LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getAddressMode() ; -} - -S32 LLViewerTexture::getTextureMemory() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->mTextureMemory ; -} - -LLGLenum LLViewerTexture::getPrimaryFormat() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getPrimaryFormat() ; -} - -BOOL LLViewerTexture::getIsAlphaMask() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getIsAlphaMask() ; -} - -BOOL LLViewerTexture::getMask(const LLVector2 &tc) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getMask(tc) ; -} - -F32 LLViewerTexture::getTimePassedSinceLastBound() -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTimePassedSinceLastBound() ; -} -BOOL LLViewerTexture::getMissed() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getMissed() ; -} - -BOOL LLViewerTexture::isJustBound() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->isJustBound() ; -} - -void LLViewerTexture::forceUpdateBindStats(void) const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->forceUpdateBindStats() ; -} - -U32 LLViewerTexture::getTexelsInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInAtlas() ; -} - -U32 LLViewerTexture::getTexelsInGLTexture() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInGLTexture() ; -} - -BOOL LLViewerTexture::isGLTextureCreated() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->isGLTextureCreated() ; -} - -S32 LLViewerTexture::getDiscardLevelInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getDiscardLevelInAtlas() ; -} - -void LLViewerTexture::destroyGLTexture() -{ - if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) - { - mGLTexturep->destroyGLTexture() ; - mTextureState = DELETED ; - } -} - -void LLViewerTexture::setTexelsPerImage() -{ - S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); - S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); - mTexelsPerImage = (F32)fullwidth * fullheight; -} - BOOL LLViewerTexture::isLargeImage() { return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ; @@ -1197,25 +905,32 @@ void LLViewerTexture::updateBindStatsForTester() //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), mTargetHost(host) { init(TRUE) ; + mFTType = f_type; + if (mFTType == FTT_HOST_BAKE) + { + mCanUseHTTP = false; + } generateGLTexture() ; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps) : LLViewerTexture(raw, usemipmaps) { init(TRUE) ; + mFTType = f_type; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), mUrl(url) { init(TRUE) ; + mFTType = f_type; generateGLTexture() ; } @@ -1281,6 +996,8 @@ void LLViewerFetchedTexture::init(bool firstinit) mLastCallBackActiveTime = 0.f; mInDebug = FALSE; + + mFTType = FTT_UNKNOWN; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -1301,6 +1018,11 @@ S8 LLViewerFetchedTexture::getType() const return LLViewerTexture::FETCHED_TEXTURE ; } +FTType LLViewerFetchedTexture::getFTType() const +{ + return mFTType; +} + void LLViewerFetchedTexture::cleanup() { for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); @@ -1345,6 +1067,7 @@ void LLViewerFetchedTexture::loadFromFastCache() { //discard all oversized textures. destroyRawImage(); + llwarns << "oversized, setting as missing" << llendl; setIsMissingAsset(); mRawDiscardLevel = INVALID_DISCARD_LEVEL ; } @@ -1454,7 +1177,8 @@ void LLViewerFetchedTexture::destroyTexture() { return ; } - + + //LL_DEBUGS("Avatar") << mID << llendl; destroyGLTexture() ; mFullyLoaded = FALSE ; } @@ -1610,6 +1334,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) // An inappropriately-sized image was uploaded (through a non standard client) // We treat these images as missing assets which causes them to // be renderd as 'missing image' and to stop requesting data + llwarns << "!size_ok, setting as missing" << llendl; setIsMissingAsset(); destroyRawImage(); return FALSE; @@ -1757,7 +1482,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Don't decode anything we don't need priority = -4.0f; } - else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data) + else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data) { priority = 1.f; } @@ -2068,6 +1793,7 @@ bool LLViewerFetchedTexture::updateFetch() { //discard all oversized textures. destroyRawImage(); + llwarns << "oversize, setting as missing" << llendl; setIsMissingAsset(); mRawDiscardLevel = INVALID_DISCARD_LEVEL ; mIsFetching = FALSE ; @@ -2097,6 +1823,10 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { + llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << llendl; setIsMissingAsset(); desired_discard = -1; } @@ -2164,7 +1894,7 @@ bool LLViewerFetchedTexture::updateFetch() // Load the texture progressively: we try not to rush to the desired discard too fast. // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around - S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; + S32 delta_level = (mBoostLevel > LLGLTexture::BOOST_NONE) ? 2 : 1 ; if (current_discard < 0) { desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); @@ -2212,7 +1942,7 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) @@ -2229,11 +1959,13 @@ bool LLViewerFetchedTexture::updateFetch() } else if (mHasFetcher && !mIsFetching) { - // Only delete requests that haven't receeived any network data for a while + // Only delete requests that haven't received any network data + // for a while. Note - this is the normal mechanism for + // deleting requests, not just a place to handle timeouts. const F32 FETCH_IDLE_TIME = 5.f; if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) { -// llinfos << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << llendl; + LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << llendl; LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); mHasFetcher = FALSE; } @@ -2281,8 +2013,10 @@ void LLViewerFetchedTexture::setIsMissingAsset() } else { - //it is normal no map tile on an empty region. - //llwarns << mUrl << ": Marking image as missing" << llendl; + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + llwarns << mUrl << ": Marking image as missing" << llendl; } if (mHasFetcher) { @@ -2415,7 +2149,7 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so destroySavedRawImage() ; } } - else if(needsToSaveRawImage() && mBoostLevel != LLViewerTexture::BOOST_PREVIEW) + else if(needsToSaveRawImage() && mBoostLevel != LLGLTexture::BOOST_PREVIEW) { if(desired_raw_discard != INVALID_DISCARD_LEVEL) { @@ -2873,7 +2607,7 @@ void LLViewerFetchedTexture::setCachedRawImage() S32 h = mRawImage->getHeight() ; S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; - if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel) + if(LLGLTexture::BOOST_TERRAIN == mBoostLevel) { max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; } @@ -3197,14 +2931,14 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //---------------------------------------------------------------------------------------------- //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- -LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) - : LLViewerFetchedTexture(id, host, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) + : LLViewerFetchedTexture(id, f_type, host, usemipmaps) { init(TRUE) ; } -LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(url, id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) + : LLViewerFetchedTexture(url, f_type, id, usemipmaps) { init(TRUE) ; } @@ -3246,7 +2980,7 @@ void LLViewerLODTexture::processTextureStats() if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } - else if (mBoostLevel < LLViewerTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) + else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) { // If the image has not been significantly visible in a while, we don't want it mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); @@ -3296,7 +3030,7 @@ void LLViewerLODTexture::processTextureStats() mCalculatedDiscardLevel = discard_level; } } - if (mBoostLevel < LLViewerTexture::BOOST_SCULPTED) + if (mBoostLevel < LLGLTexture::BOOST_SCULPTED) { discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale @@ -3322,7 +3056,7 @@ void LLViewerLODTexture::processTextureStats() // S32 current_discard = getDiscardLevel(); - if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0) + if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLGLTexture::BOOST_SCULPTED && current_discard >= 0) { if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage) { @@ -3465,7 +3199,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL setMediaImpl() ; - setCategory(LLViewerTexture::MEDIA) ; + setCategory(LLGLTexture::MEDIA) ; LLViewerTexture* tex = gTextureList.findImage(mID) ; if(tex) //this media is a parcel media for tex. diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 2e7949e9a3..f2e1a90713 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -27,7 +27,7 @@ #ifndef LL_LLVIEWERTEXTURE_H #define LL_LLVIEWERTEXTURE_H -#include "lltexture.h" +#include "llgltexture.h" #include "lltimer.h" #include "llframetimer.h" #include "llhost.h" @@ -88,16 +88,11 @@ public: class LLTextureBar; -class LLViewerTexture : public LLTexture +class LLViewerTexture : public LLGLTexture { public: enum { - MAX_IMAGE_SIZE_DEFAULT = 1024, - INVALID_DISCARD_LEVEL = 0x7fff - }; - enum - { LOCAL_TEXTURE, MEDIA_TEXTURE, DYNAMIC_TEXTURE, @@ -107,43 +102,6 @@ public: INVALID_TEXTURE_TYPE }; - enum EBoostLevel - { - BOOST_NONE = 0, - BOOST_AVATAR_BAKED , - BOOST_AVATAR , - BOOST_CLOUDS , - BOOST_SCULPTED , - - BOOST_HIGH = 10, - BOOST_BUMP , - BOOST_TERRAIN , // has to be high priority for minimap / low detail - BOOST_SELECTED , - BOOST_AVATAR_BAKED_SELF , - BOOST_AVATAR_SELF , // needed for baking avatar - BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. - BOOST_HUD , - BOOST_ICON , - BOOST_UI , - BOOST_PREVIEW , - BOOST_MAP , - BOOST_MAP_VISIBLE , - BOOST_MAX_LEVEL, - - //other texture Categories - LOCAL = BOOST_MAX_LEVEL, - AVATAR_SCRATCH_TEX, - DYNAMIC_TEX, - MEDIA, - ATLAS, - OTHER, - MAX_GL_IMAGE_CATEGORY - }; - - static S32 getTotalNumOfCategories() ; - static S32 getIndexFromCategory(S32 category) ; - static S32 getCategoryFromIndex(S32 index) ; - typedef std::vector<LLFace*> ll_face_list_t; typedef std::vector<LLVOVolume*> ll_volume_list_t; @@ -168,8 +126,7 @@ public: /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; - const LLUUID& getID() const { return mID; } - + /*virtual*/ const LLUUID& getID() const { return mID; } void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } @@ -177,13 +134,12 @@ public: void resetTextureStats(); void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;} + S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; } virtual F32 getMaxVirtualSize() ; LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} - S32 getFullWidth() const { return mFullWidth; } - S32 getFullHeight() const { return mFullHeight; } /*virtual*/ void setKnownDrawSize(S32 width, S32 height); virtual void addFace(LLFace* facep) ; @@ -196,60 +152,8 @@ public: S32 getNumVolumes() const; const ll_volume_list_t* getVolumeList() const { return &mVolumeList; } - void generateGLTexture() ; - void destroyGLTexture() ; - //--------------------------------------------------------------------------------------------- - //functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - /*virtual*/S32 getWidth(S32 discard_level = -1) const; - /*virtual*/S32 getHeight(S32 discard_level = -1) const; - - BOOL hasGLTexture() const ; - LLGLuint getTexName() const ; - BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER); virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; - - void setFilteringOption(LLTexUnit::eTextureFilterOptions option); - void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); - void setAddressMode(LLTexUnit::eTextureAddressMode mode); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); - void setGLTextureCreated (bool initialized); - void setCategory(S32 category) ; - - LLTexUnit::eTextureAddressMode getAddressMode(void) const ; - S32 getMaxDiscardLevel() const; - S32 getDiscardLevel() const; - S8 getComponents() const ; - BOOL getBoundRecently() const; - S32 getTextureMemory() const ; - LLGLenum getPrimaryFormat() const; - BOOL getIsAlphaMask() const ; - LLTexUnit::eTextureType getTarget(void) const ; - BOOL getMask(const LLVector2 &tc); - F32 getTimePassedSinceLastBound(); - BOOL getMissed() const ; - BOOL isJustBound()const ; - void forceUpdateBindStats(void) const; - - U32 getTexelsInAtlas() const ; - U32 getTexelsInGLTexture() const ; - BOOL isGLTextureCreated() const ; - S32 getDiscardLevelInAtlas() const ; - //--------------------------------------------------------------------------------------------- - //end of functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - - //----------------- - /*virtual*/ void setActive() ; - void forceActive() ; - void setNoDelete() ; - void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } - BOOL getDontDiscard() const { return mDontDiscard; } - //----------------- - BOOL isLargeImage() ; void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} @@ -262,36 +166,22 @@ protected: void init(bool firstinit) ; void reorganizeFaceList() ; void reorganizeVolumeList() ; - void setTexelsPerImage(); private: friend class LLBumpImageList; friend class LLUIImageList; - //note: do not make this function public. - /*virtual*/ LLImageGL* getGLTexture() const ; virtual void switchToCachedImage(); static bool isMemoryForTextureLow() ; protected: LLUUID mID; - S32 mBoostLevel; // enum describing priority level F32 mSelectedTime; // time texture was last selected - S32 mFullWidth; - S32 mFullHeight; - BOOL mUseMipMaps ; - S8 mComponents; - F32 mTexelsPerImage; // Texels per image. - mutable S8 mNeedsGLTexture; mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter ; mutable S32 mMaxVirtualSizeResetInterval; mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. LLFrameTimer mLastReferencedTimer; - //GL texture - LLPointer<LLImageGL> mGLTexturep ; - S8 mDontDiscard; // Keep full res version of this image (for UI, etc) - ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture U32 mNumFaces ; LLFrameTimer mLastFaceListUpdateTimer ; @@ -303,17 +193,6 @@ protected: //do not use LLPointer here. LLViewerMediaTexture* mParcelMedia ; -protected: - typedef enum - { - DELETED = 0, //removed from memory - DELETION_CANDIDATE, //ready to be removed from memory - INACTIVE, //not be used for the last certain period (i.e., 30 seconds). - ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). - NO_DELETE = 99 //stay in memory, can not be removed. - } LLGLTextureState; - LLGLTextureState mTextureState ; - static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; @@ -353,6 +232,16 @@ public: }; +enum FTType +{ + FTT_UNKNOWN = -1, + FTT_DEFAULT = 0, // standard texture fetched by id. + FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. + FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. + FTT_MAP_TILE, // tiles are fetched from map server directly. + FTT_LOCAL_FILE // fetch directly from a local file. +}; + // //textures are managed in gTextureList. //raw image data is fetched from remote or local cache @@ -366,9 +255,9 @@ class LLViewerFetchedTexture : public LLViewerTexture protected: /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps); - LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); + LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); public: static F32 maxDecodePriority(); @@ -393,6 +282,7 @@ public: public: /*virtual*/ S8 getType() const ; + FTType getFTType() const; /*virtual*/ void forceImmediateUpdate() ; /*virtual*/ void dump() ; @@ -428,6 +318,7 @@ public: // the priority list, and cause horrible things to happen. void setDecodePriority(F32 priority = -1.0f); F32 getDecodePriority() const { return mDecodePriority; }; + F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; }; void setAdditionalDecodePriority(F32 priority) ; @@ -509,7 +400,7 @@ protected: S32 getCurrentDiscardLevelForFetching() ; private: - void init(bool firstinit) ; + void init(bool firstinit) ; void cleanup() ; void saveRawImage() ; @@ -556,7 +447,8 @@ protected: S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active bool mCanUseHTTP ; //This texture can be fetched through http if true. - + + FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. typedef std::list<LLLoadedCallbackEntry*> callback_list_t; @@ -616,8 +508,8 @@ protected: /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); /*virtual*/ S8 getType() const; // Process image stats to determine priority/quality requirements. @@ -731,8 +623,9 @@ public: static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -740,8 +633,9 @@ public: ); static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -749,15 +643,16 @@ public: ); static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, const LLUUID& force_id = LLUUID::null ); - static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) ; + static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; static void init() ; static void cleanup() ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index b9f5c432d0..d2af48f528 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -112,10 +112,10 @@ void LLViewerTextureList::doPreloadImages() llassert_always(mUUIDMap.empty()) ; // Set the "missing asset" image - LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); // Set the "white" image - LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); @@ -130,33 +130,33 @@ void LLViewerTextureList::doPreloadImages() //uv_test->setMipFilterNearest(TRUE, TRUE); // prefetch specific UUIDs - LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE); - LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + LLViewerTextureManager::getFetchedTexture(IMG_SHOT); + LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")); if (image) { @@ -198,7 +198,7 @@ void LLViewerTextureList::doPrefetchImages() if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) { - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, texture_type); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) { image->addTextureStats((F32)pixel_area); @@ -228,7 +228,9 @@ void LLViewerTextureList::shutdown() if (!image->hasGLTexture() || !image->getUseDiscard() || image->needsAux() || - image->getTargetHost() != LLHost::invalid) + image->getTargetHost() != LLHost::invalid || + !image->getUrl().empty() + ) { continue; // avoid UI, baked, and other special images } @@ -322,7 +324,8 @@ void LLViewerTextureList::restoreGL() /////////////////////////////////////////////////////////////////////////////// -LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, +LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -339,15 +342,16 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& if (full_path.empty()) { llwarns << "Failed to find local image file: " << filename << llendl; - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); } std::string url = "file://" + full_path; - return getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + return getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -372,16 +376,33 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& } LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id); - + + if (!imagep.isNull()) + { + LLViewerFetchedTexture *texture = imagep.get(); + if (texture->getUrl().empty()) + { + llwarns << "Requested texture " << new_id << " already exists but does not have a URL" << llendl; + } + else if (texture->getUrl() != url) + { + // This is not an error as long as the images really match - + // e.g. could be two avatars wearing the same outfit. + LL_DEBUGS("Avatar") << "Requested texture " << new_id + << " already exists with a different url, requested: " << url + << " current: " << texture->getUrl() << llendl; + } + + } if (imagep.isNull()) { switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps); + imagep = new LLViewerFetchedTexture(url, f_type, new_id, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(url, new_id, usemipmaps); + imagep = new LLViewerLODTexture(url, f_type, new_id, usemipmaps); break ; default: llerrs << "Invalid texture type " << texture_type << llendl ; @@ -411,7 +432,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& } -LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, +LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -430,14 +452,34 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if ((&image_id == NULL) || image_id.isNull()) { - return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI)); + return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); } LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id); - + if (!imagep.isNull()) + { + LLViewerFetchedTexture *texture = imagep.get(); + if (request_from_host.isOk() && + !texture->getTargetHost().isOk()) + { + llwarns << "Requested texture " << image_id << " already exists but does not have a host" << llendl; + } + else if (request_from_host.isOk() && + texture->getTargetHost().isOk() && + request_from_host != texture->getTargetHost()) + { + llwarns << "Requested texture " << image_id << " already exists with a different target host, requested: " + << request_from_host << " current: " << texture->getTargetHost() << llendl; + } + if (f_type != FTT_DEFAULT && imagep->getFTType() != f_type) + { + llwarns << "FTType mismatch: requested " << f_type << " image has " << imagep->getFTType() << llendl; + } + + } if (imagep.isNull()) { - imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + imagep = createImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } imagep->setGLTextureCreated(true); @@ -446,7 +488,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, } //when this function is called, there is no such texture in the gTextureList with image_id. -LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, +LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -460,10 +503,10 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerFetchedTexture(image_id, f_type, request_from_host, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerLODTexture(image_id, f_type, request_from_host, usemipmaps); break ; default: llerrs << "Invalid texture type " << texture_type << llendl ; @@ -1353,7 +1396,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1425,7 +1468,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1456,6 +1499,7 @@ void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void ** LLViewerFetchedTexture* image = gTextureList.findImage( image_id ); if( image ) { + llwarns << "not in db" << llendl; image->setIsMissingAsset(); } } @@ -1525,22 +1569,22 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priori LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority ) { - if (boost_priority == LLViewerTexture::BOOST_NONE) + if (boost_priority == LLGLTexture::BOOST_NONE) { - boost_priority = LLViewerTexture::BOOST_UI; + boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, FTT_LOCAL_FILE, MIPMAP_NO, boost_priority); return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect); } LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority) { - if (boost_priority == LLViewerTexture::BOOST_NONE) + if (boost_priority == LLGLTexture::BOOST_NONE) { - boost_priority = LLViewerTexture::BOOST_UI; + boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, MIPMAP_NO, boost_priority); return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect); } @@ -1563,7 +1607,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st //Note: //Some other textures such as ICON also through this flow to be fetched. //But only UI textures need to set this callback. - if(imagep->getBoostLevel() == LLViewerTexture::BOOST_UI) + if(imagep->getBoostLevel() == LLGLTexture::BOOST_UI) { LLUIImageLoadData* datap = new LLUIImageLoadData; datap->mImageName = name; diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 3dda973d3f..136042620d 100755 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -130,8 +130,9 @@ private: void removeImageFromList(LLViewerFetchedTexture *image); LLViewerFetchedTexture * getImage(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -139,8 +140,9 @@ private: ); LLViewerFetchedTexture * getImageFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -148,8 +150,9 @@ private: ); LLViewerFetchedTexture* getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -157,8 +160,9 @@ private: ); LLViewerFetchedTexture* createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -167,8 +171,8 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC - LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, FTType f_type, LLHost host) + { return getImage(image_id, f_type, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t; @@ -233,11 +237,11 @@ private: LLPointer<LLUIImage> loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); LLPointer<LLUIImage> loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); LLPointer<LLUIImage> loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp new file mode 100644 index 0000000000..e8425dc76a --- /dev/null +++ b/indra/newview/llviewerwearable.cpp @@ -0,0 +1,656 @@ +/** + * @file llviewerwearable.cpp + * @brief LLViewerWearable class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llfloatersidepanelcontainer.h" +#include "llnotificationsutil.h" +#include "llsidepanelappearance.h" +#include "lltextureentry.h" +#include "llviewertexlayer.h" +#include "llvoavatarself.h" +#include "llavatarappearancedefines.h" +#include "llviewerwearable.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" + +using namespace LLAvatarAppearanceDefines; + +// support class - remove for 2.1 (hackity hack hack) +class LLOverrideBakedTextureUpdate +{ +public: + LLOverrideBakedTextureUpdate(bool temp_state) + { + U32 num_bakes = (U32) LLAvatarAppearanceDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); + } + gAgentAvatarp->setCompositeUpdatesEnabled(temp_state); + } + + ~LLOverrideBakedTextureUpdate() + { + U32 num_bakes = (U32)LLAvatarAppearanceDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); + } + } +private: + bool composite_enabled[LLAvatarAppearanceDefines::BAKED_NUM_INDICES]; +}; + +// Private local functions +static std::string asset_id_to_filename(const LLUUID &asset_id); + +LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id) : + LLWearable() +{ + mTransactionID = transaction_id; + mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); +} + +LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id) : + LLWearable() +{ + mAssetID = asset_id; + mTransactionID.setNull(); +} + +// virtual +LLViewerWearable::~LLViewerWearable() +{ +} + +// virtual +LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) +{ + // suppress texlayerset updates while wearables are being imported. Layersets will be updated + // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. + LLOverrideBakedTextureUpdate stop_bakes(false); + + LLWearable::EImportResult result = LLWearable::importStream(input_stream, avatarp); + if (LLWearable::FAILURE == result) return result; + if (LLWearable::BAD_HEADER == result) + { + // Shouldn't really log the asset id for security reasons, but + // we need it in this case. + llwarns << "Bad Wearable asset header: " << mAssetID << llendl; + //gVFS->dumpMap(); + return result; + } + + LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); + LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); + + te_map_t::const_iterator iter = mTEMap.begin(); + te_map_t::const_iterator end = mTEMap.end(); + for (; iter != end; ++iter) + { + S32 te = iter->first; + LLLocalTextureObject* lto = iter->second; + LLUUID textureid = LLUUID::null; + if (lto) + { + textureid = lto->getID(); + } + + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( textureid ); + if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) + { + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLAvatarAppearanceDefines::ETextureIndex)te), NULL); + } + } + + return result; +} + + +// Avatar parameter and texture definitions can change over time. +// This function returns true if parameters or textures have been added or removed +// since this wearable was created. +BOOL LLViewerWearable::isOldVersion() const +{ + if (!isAgentAvatarValid()) return FALSE; + + if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion ) + { + llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; + llassert(0); + } + + if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion ) + { + return TRUE; + } + + S32 param_count = 0; + for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) && (param->isTweakable() ) ) + { + param_count++; + if( !is_in_map(mVisualParamIndexMap, param->getID() ) ) + { + return TRUE; + } + } + } + if( param_count != mVisualParamIndexMap.size() ) + { + return TRUE; + } + + + S32 te_count = 0; + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_count++; + if( !is_in_map(mTEMap, te ) ) + { + return TRUE; + } + } + } + if( te_count != mTEMap.size() ) + { + return TRUE; + } + + return FALSE; +} + +// Avatar parameter and texture definitions can change over time. +// * If parameters or textures have been REMOVED since the wearable was created, +// they're just ignored, so we consider the wearable clean even though isOldVersion() +// will return true. +// * If parameters or textures have been ADDED since the wearable was created, +// they are taken to have default values, so we consider the wearable clean +// only if those values are the same as the defaults. +BOOL LLViewerWearable::isDirty() const +{ + if (!isAgentAvatarValid()) return FALSE; + + for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) + && (param->isTweakable() ) + && !param->getCrossWearable()) + { + F32 current_weight = getVisualParamWeight(param->getID()); + current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() ); + F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight()); + saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() ); + + U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); + U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); + if( a != b ) + { + return TRUE; + } + } + } + + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator current_iter = mTEMap.find(te); + if(current_iter != mTEMap.end()) + { + const LLUUID& current_image_id = current_iter->second->getID(); + te_map_t::const_iterator saved_iter = mSavedTEMap.find(te); + if(saved_iter != mSavedTEMap.end()) + { + const LLUUID& saved_image_id = saved_iter->second->getID(); + if (saved_image_id != current_image_id) + { + // saved vs current images are different, wearable is dirty + return TRUE; + } + } + else + { + // image found in current image list but not saved image list + return TRUE; + } + } + } + } + + return FALSE; +} + + +void LLViewerWearable::setParamsToDefaults() +{ + if (!isAgentAvatarValid()) return; + + for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + { + if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) ) + { + setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE); + } + } +} + +void LLViewerWearable::setTexturesToDefaults() +{ + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + LLUUID id = getDefaultTextureImageID((ETextureIndex) te); + LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); + if( mTEMap.find(te) == mTEMap.end() ) + { + mTEMap[te] = new LLLocalTextureObject(image, id); + createLayers(te, gAgentAvatarp); + } + else + { + // Local Texture Object already created, just set image and UUID + LLLocalTextureObject *lto = mTEMap[te]; + lto->setID(id); + lto->setImage(image); + } + } + } +} + + +// virtual +LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) const +{ + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + const std::string &default_image_name = texture_dict->mDefaultImageName; + if (default_image_name == "") + { + return IMG_DEFAULT_AVATAR; + } + else + { + return LLUUID(gSavedSettings.getString(default_image_name)); + } +} + + +// Updates the user's avatar's appearance +//virtual +void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) +{ + LLVOAvatarSelf* viewer_avatar = dynamic_cast<LLVOAvatarSelf*>(avatarp); + + if (!avatarp || !viewer_avatar) return; + + if (!viewer_avatar->isValid()) return; + +#if 0 + // FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables. + // Ideally would avoid calling this func in the first place. + if (viewer_avatar->isUsingServerBakes() && + !viewer_avatar->isUsingLocalAppearance()) + { + return; + } +#endif + + ESex old_sex = avatarp->getSex(); + + LLWearable::writeToAvatar(avatarp); + + + // Pull texture entries + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = mTEMap.find(te); + LLUUID image_id; + if(iter != mTEMap.end()) + { + image_id = iter->second->getID(); + } + else + { + image_id = getDefaultTextureImageID((ETextureIndex) te); + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. + viewer_avatar->setLocalTextureTE(te, image, 0); + } + } + + ESex new_sex = avatarp->getSex(); + if( old_sex != new_sex ) + { + viewer_avatar->updateSexDependentLayerSets( FALSE ); + } + +// if( upload_bake ) +// { +// gAgent.sendAgentSetAppearance(); +// } +} + + +// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. +// static +void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ) +{ + if (!isAgentAvatarValid()) return; + + // You can't just remove body parts. + if( (type == LLWearableType::WT_SHAPE) || + (type == LLWearableType::WT_SKIN) || + (type == LLWearableType::WT_HAIR) || + (type == LLWearableType::WT_EYES) ) + { + return; + } + + // Pull params + for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + { + if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) ) + { + S32 param_id = param->getID(); + gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake ); + } + } + + if(gAgentCamera.cameraCustomizeAvatar()) + { + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); + } + + gAgentAvatarp->updateVisualParams(); + gAgentAvatarp->wearableUpdated(type, FALSE); + +// if( upload_bake ) +// { +// gAgent.sendAgentSetAppearance(); +// } +} + +// Does not copy mAssetID. +// Definition version is current: removes obsolete enties and creates default values for new ones. +void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) +{ + if (!isAgentAvatarValid()) return; + + mDefinitionVersion = LLWearable::sCurrentDefinitionVersion; + + mName = src->mName; + mDescription = src->mDescription; + mPermissions = src->mPermissions; + mSaleInfo = src->mSaleInfo; + + setType(src->mType, gAgentAvatarp); + + mSavedVisualParamMap.clear(); + // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) ) + { + S32 id = param->getID(); + F32 weight = src->getVisualParamWeight(id); + mSavedVisualParamMap[id] = weight; + } + } + + destroyTextures(); + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + for (S32 te = 0; te < TEX_NUM_INDICES; te++) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src->mTEMap.find(te); + LLUUID image_id; + LLViewerFetchedTexture *image = NULL; + if(iter != src->mTEMap.end()) + { + image = dynamic_cast<LLViewerFetchedTexture*> (src->getLocalTextureObject(te)->getImage()); + image_id = src->getLocalTextureObject(te)->getID(); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + mTEMap[te]->setBakedReady(src->getLocalTextureObject(te)->getBakedReady()); + mTEMap[te]->setDiscard(src->getLocalTextureObject(te)->getDiscard()); + } + else + { + image_id = getDefaultTextureImageID((ETextureIndex) te); + image = LLViewerTextureManager::getFetchedTexture( image_id ); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + } + createLayers(te, gAgentAvatarp); + } + } + + // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable + // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) + revertValues(); +} + +void LLViewerWearable::setItemID(const LLUUID& item_id) +{ + mItemID = item_id; +} + +void LLViewerWearable::revertValues() +{ +#if 0 + // DRANO avoid overwrite when not in local appearance + if (isAgentAvatarValid() && gAgentAvatarp->isUsingServerBakes() && !gAgentAvatarp->isUsingLocalAppearance()) + { + return; + } +#endif + LLWearable::revertValues(); + + + LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + } +} + +void LLViewerWearable::saveValues() +{ + LLWearable::saveValues(); + + LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + } +} + +// virtual +void LLViewerWearable::setUpdated() const +{ + gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); +} + +void LLViewerWearable::refreshName() +{ + LLUUID item_id = getItemID(); + LLInventoryItem* item = gInventory.getItem(item_id); + if( item ) + { + mName = item->getName(); + } +} + +// virtual +void LLViewerWearable::addToBakedTextureHash(LLMD5& hash) const +{ + LLUUID asset_id = getAssetID(); + hash.update((const unsigned char*)asset_id.mData, UUID_BYTES); +} + +struct LLWearableSaveData +{ + LLWearableType::EType mType; +}; + +void LLViewerWearable::saveNewAsset() const +{ +// llinfos << "LLViewerWearable::saveNewAsset() type: " << getTypeName() << llendl; + //llinfos << *this << llendl; + + const std::string filename = asset_id_to_filename(mAssetID); + LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ + BOOL successful_save = FALSE; + if(fp && exportFile(fp)) + { + successful_save = TRUE; + } + if(fp) + { + fclose(fp); + fp = NULL; + } + if(!successful_save) + { + std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str()); + llwarns << buffer << llendl; + + LLSD args; + args["NAME"] = mName; + LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args); + return; + } + + // save it out to database + if( gAssetStorage ) + { + /* + std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + if (!url.empty()) + { + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); + body["asset_type"] = LLAssetType::lookup(getAssetType()); + body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); + body["name"] = getName(); + body["description"] = getDescription(); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); + } + else + { + } + */ + LLWearableSaveData* data = new LLWearableSaveData; + data->mType = mType; + gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), + &LLViewerWearable::onSaveNewAssetComplete, + (void*)data); + } +} + +// static +void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ + LLWearableSaveData* data = (LLWearableSaveData*)userdata; + const std::string& type_name = LLWearableType::getTypeName(data->mType); + if(0 == status) + { + // Success + llinfos << "Saved wearable " << type_name << llendl; + } + else + { + std::string buffer = llformat("Unable to save %s to central asset store.", type_name.c_str()); + llwarns << buffer << " Status: " << status << llendl; + LLSD args; + args["NAME"] = type_name; + LLNotificationsUtil::add("CannotSaveToAssetStore", args); + } + + // Delete temp file + const std::string src_filename = asset_id_to_filename(new_asset_id); + LLFile::remove(src_filename); + + // delete the context data + delete data; + +} + +std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) +{ + s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; + s << " Name: " << w.mName << "\n"; + s << " Desc: " << w.mDescription << "\n"; + //w.mPermissions + //w.mSaleInfo + + s << " Params:" << "\n"; + for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); + iter != w.mVisualParamIndexMap.end(); ++iter) + { + S32 param_id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 param_weight = wearable_param->getWeight(); + s << " " << param_id << " " << param_weight << "\n"; + } + + s << " Textures:" << "\n"; + for (LLViewerWearable::te_map_t::const_iterator iter = w.mTEMap.begin(); + iter != w.mTEMap.end(); ++iter) + { + S32 te = iter->first; + const LLUUID& image_id = iter->second->getID(); + s << " " << te << " " << image_id << "\n"; + } + return s; +} + +std::string asset_id_to_filename(const LLUUID &asset_id) +{ + std::string asset_id_string; + asset_id.toString(asset_id_string); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl"; + return filename; +} diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h new file mode 100644 index 0000000000..65566f23a5 --- /dev/null +++ b/indra/newview/llviewerwearable.h @@ -0,0 +1,104 @@ +/** + * @file llviewerwearable.h + * @brief LLViewerWearable class header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_VIEWER_WEARABLE_H +#define LL_VIEWER_WEARABLE_H + +#include "llwearable.h" +#include "llavatarappearancedefines.h" + +class LLVOAvatar; + +class LLViewerWearable : public LLWearable +{ + friend class LLWearableList; + + //-------------------------------------------------------------------- + // Constructors and destructors + //-------------------------------------------------------------------- +private: + // Private constructors used by LLViewerWearableList + LLViewerWearable(const LLTransactionID& transactionID); + LLViewerWearable(const LLAssetID& assetID); +public: + virtual ~LLViewerWearable(); + + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + const LLUUID& getItemID() const { return mItemID; } + const LLAssetID& getAssetID() const { return mAssetID; } + const LLTransactionID& getTransactionID() const { return mTransactionID; } + void setItemID(const LLUUID& item_id); + +public: + + BOOL isDirty() const; + BOOL isOldVersion() const; + + /*virtual*/ void writeToAvatar(LLAvatarAppearance *avatarp); + void removeFromAvatar( BOOL upload_bake ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); } + static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); + + /*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); + + void setParamsToDefaults(); + void setTexturesToDefaults(); + + /*virtual*/ LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const; + + + void saveNewAsset() const; + static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); + + void copyDataFrom(const LLViewerWearable* src); + + friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w); + + /*virtual*/ void revertValues(); + /*virtual*/ void saveValues(); + + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). + /*virtual*/void setUpdated() const; + + // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, + // not the wearable asset itself. + void refreshName(); + + // Update the baked texture hash. + /*virtual*/void addToBakedTextureHash(LLMD5& hash) const; + +protected: + LLAssetID mAssetID; + LLTransactionID mTransactionID; + + LLUUID mItemID; // ID of the inventory item in the agent's inventory +}; + + +#endif // LL_VIEWER_WEARABLE_H + diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4afd90b44c..0910b7536d 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -383,7 +383,7 @@ public: if (isAgentAvatarValid()) { - tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition()); + tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); agent_root_center_text = llformat("AgentRootCenter %f %f %f", (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); } @@ -1573,6 +1573,16 @@ LLViewerWindow::LLViewerWindow(const Params& p) LLViewerWindow::sMovieBaseName = "SLmovie"; resetSnapshotLoc(); + + /* + LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, + BOOL fullscreen, + BOOL clearBg, + BOOL disable_vsync, + BOOL ignore_pixel_depth, + U32 fsaa_samples) + */ // create window mWindow = LLWindowManager::createWindow(this, p.title, p.name, p.x, p.y, p.width, p.height, 0, @@ -2147,7 +2157,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) calcDisplayScale(); - BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor; + BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); LLUI::setScaleFactor(mDisplayScale); // update our window rectangle @@ -2353,7 +2363,7 @@ void LLViewerWindow::draw() // scale view by UI global scale factor and aspect ratio correction factor gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - LLVector2 old_scale_factor = LLUI::sGLScaleFactor; + LLVector2 old_scale_factor = LLUI::getScaleFactor(); // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); @@ -2367,7 +2377,7 @@ void LLViewerWindow::draw() (F32)getWindowHeightScaled() * -(F32)pos_y, 0.f); gGL.scalef(zoom_factor, zoom_factor, 1.f); - LLUI::sGLScaleFactor *= zoom_factor; + LLUI::getScaleFactor() *= zoom_factor; } // Draw tool specific overlay on world @@ -2415,7 +2425,7 @@ void LLViewerWindow::draw() LLFontGL::HCENTER, LLFontGL::TOP); } - LLUI::sGLScaleFactor = old_scale_factor; + LLUI::setScaleFactor(old_scale_factor); } LLUI::popMatrix(); gGL.popMatrix(); @@ -3218,8 +3228,8 @@ void LLViewerWindow::updateLayout() void LLViewerWindow::updateMouseDelta() { - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); - S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; @@ -4784,7 +4794,7 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gResizeScreenTexture = TRUE; gWindowResized = TRUE; - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) { LLVisualParamHint::requestHintUpdates(); } diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index abb5153480..94760e3c83 100755 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -223,7 +223,7 @@ BOOL LLVLComposition::generateComposition() { if (mDetailTextures[i]->getDiscardLevel() < 0) { - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); return FALSE; } @@ -240,7 +240,7 @@ BOOL LLVLComposition::generateComposition() ddiscard++; min_dim /= 2; } - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail mDetailTextures[i]->setMinDiscardLevel(ddiscard); return FALSE; } @@ -376,9 +376,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps); U8 *rawp = raw->getData(); - F32 tex_width_inv = 1.f/tex_width; - F32 tex_height_inv = 1.f/tex_height; - F32 st_x_stride, st_y_stride; st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); @@ -413,11 +410,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, tex1 = tex0 + 1; tex1 = llclamp(tex1, 0, 3); - F32 xy_int_i, xy_int_j; - - xy_int_i = i * tex_width_inv; - xy_int_j = j * tex_height_inv; - st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; for (U32 k = 0; k < tex_comps; k++) { @@ -461,7 +453,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, for (S32 i = 0; i < 4; i++) { // Un-boost detatil textures (will get re-boosted if rendering in high detail) - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE); + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE); mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a3093f069d..06fb23b84b 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -24,18 +24,13 @@ * $/LicenseInfo$ */ -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#endif - #include "llviewerprecompiledheaders.h" #include "llvoavatar.h" #include <stdio.h> #include <ctype.h> +#include <sstream> #include "llaudioengine.h" #include "noise.h" @@ -53,6 +48,7 @@ #include "llcallingcard.h" // IDEVO for LLAvatarTracker #include "lldrawpoolavatar.h" #include "lldriverparam.h" +#include "llpolyskeletaldistortion.h" #include "lleditingmotion.h" #include "llemote.h" //#include "llfirstuse.h" @@ -78,15 +74,16 @@ #include "llselectmgr.h" #include "llsprite.h" #include "lltargetingmotion.h" -#include "lltexlayer.h" #include "lltoolmorph.h" #include "llviewercamera.h" +#include "llviewertexlayer.h" #include "llviewertexturelist.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewershadermgr.h" #include "llviewerstats.h" +#include "llviewerwearable.h" #include "llvoavatarself.h" #include "llvovolume.h" #include "llworld.h" @@ -103,22 +100,17 @@ #include "lldebugmessagebox.h" #include "llsdutil.h" +#include "llsdserialize.h" extern F32 SPEED_ADJUST_MAX; extern F32 SPEED_ADJUST_MAX_SEC; extern F32 ANIM_SPEED_MAX; extern F32 ANIM_SPEED_MIN; -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif - -#include <boost/lexical_cast.hpp> // #define OUTPUT_BREAST_DATA -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; //----------------------------------------------------------------------------- // Global constants @@ -139,7 +131,6 @@ const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df44 //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- -const std::string AVATAR_DEFAULT_CHAR = "avatar"; const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; const F32 SHADOW_OFFSET_AMT = 0.03f; @@ -196,8 +187,6 @@ const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; -const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); - enum ERenderName { RENDER_NAME_NEVER, @@ -244,6 +233,24 @@ struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarColli scale; }; +struct LLAppearanceMessageContents +{ + LLAppearanceMessageContents(): + mAppearanceVersion(-1), + mParamAppearanceVersion(-1), + mCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) + { + } + LLTEContents mTEContents; + S32 mAppearanceVersion; + S32 mParamAppearanceVersion; + S32 mCOFVersion; + // For future use: + //U32 appearance_flags = 0; + std::vector<F32> mParamWeights; + std::vector<LLVisualParam*> mParams; +}; + struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> { Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> > bone; @@ -255,6 +262,8 @@ struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoi {} }; + + struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo> { LLVOAvatarBoneInfo() @@ -284,6 +293,8 @@ struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo Mandatory<LLVOAvatarChildJoint> skeleton_root; }; + + //----------------------------------------------------------------------------- // class LLBodyNoiseMotion //----------------------------------------------------------------------------- @@ -605,11 +616,7 @@ private: //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -LLXmlTree LLVOAvatar::sXMLTree; -LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree; -LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; -LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; -LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; +LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; U32 LLVOAvatar::sMaxVisible = 12; F32 LLVOAvatar::sRenderDistance = 256.f; @@ -656,15 +663,13 @@ static F32 calc_bouncy_animation(F32 x); LLVOAvatar::LLVOAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLAvatarAppearance(&gAgentWearables), LLViewerObject(id, pcode, regionp), - mIsDummy(FALSE), mSpecialRenderMode(0), mAttachmentGeometryBytes(0), mAttachmentSurfaceArea(0.f), mTurning(FALSE), - mPelvisToFoot(0.f), mLastSkeletonSerialNum( 0 ), - mHeadOffset(), mIsSitting(FALSE), mTimeVisible(), mTyping(FALSE), @@ -689,9 +694,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFirstAppearanceMessageReceived( FALSE ), mCulled( FALSE ), mVisibilityRank(0), - mTexSkinColor( NULL ), - mTexHairColor( NULL ), - mTexEyeColor( NULL ), mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), @@ -699,12 +701,15 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), - mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")), - mLastRezzedStatus(-1) - + mLastRezzedStatus(-1), + mIsEditingAppearance(FALSE), + mUseLocalAppearance(FALSE), + mUseServerBakes(FALSE), // FIXME DRANO consider using boost::optional, defaulting to unknown. + mLastUpdateRequestCOFVersion(-1), + mLastUpdateReceivedCOFVersion(-1) { //VTResume(); // VTune @@ -716,28 +721,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mPelvisp = NULL; - mBakedTextureDatas.resize(BAKED_NUM_INDICES); - for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) - { - mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; - mBakedTextureDatas[i].mTexLayerSet = NULL; - mBakedTextureDatas[i].mIsLoaded = false; - mBakedTextureDatas[i].mIsUsed = false; - mBakedTextureDatas[i].mMaskTexName = 0; - mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); - } - mDirtyMesh = 2; // Dirty geometry, need to regenerate. mMeshTexturesDirty = FALSE; mHeadp = NULL; - mIsBuilt = FALSE; - - mNumJoints = 0; - mSkeleton = NULL; - - mNumCollisionVolumes = 0; - mCollisionVolumes = NULL; // set up animation variables mSpeed = 0.f; @@ -815,59 +802,22 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { - if (!mFullyLoaded) - { + if (!mFullyLoaded) + { debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); - } - else - { + } + else + { debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); - } + } + logPendingPhases(); + lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; - mRoot.removeAllChildren(); - mJointMap.clear(); - - deleteAndClearArray(mSkeleton); - deleteAndClearArray(mCollisionVolumes); - - mNumJoints = 0; - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); - mBakedTextureDatas[i].mMeshes.clear(); - - for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); - iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) - { - LLMaskedMorph* masked_morph = (*iter2); - delete masked_morph; - } - } - std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); mAttachmentPoints.clear(); - deleteAndClear(mTexSkinColor); - deleteAndClear(mTexHairColor); - deleteAndClear(mTexEyeColor); - - std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); - mMeshes.clear(); - - for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); - ++jointIter) - { - LLViewerJoint* joint = (LLViewerJoint *) *jointIter; - std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); - joint->mMeshParts.clear(); - } - std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); - mMeshLOD.clear(); - mDead = TRUE; mAnimationSources.clear(); @@ -912,7 +862,7 @@ BOOL LLVOAvatar::isFullyTextured() const { for (S32 i = 0; i < mMeshLOD.size(); i++) { - LLViewerJoint* joint = (LLViewerJoint*) mMeshLOD[i]; + LLAvatarJoint* joint = mMeshLOD[i]; if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) { continue; // don't care about skirt textures if we're not wearing one. @@ -921,19 +871,19 @@ BOOL LLVOAvatar::isFullyTextured() const { continue; // nonexistent LOD OK. } - std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); + avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); if (meshIter != joint->mMeshParts.end()) { - LLViewerJointMesh *mesh = (LLViewerJointMesh *) *meshIter; + LLAvatarJointMesh *mesh = (*meshIter); if (!mesh) { continue; // nonexistent mesh OK } - if (mesh->mTexture.notNull() && mesh->mTexture->hasGLTexture()) + if (mesh->hasGLTexture()) { continue; // Mesh exists and has a baked texture. } - if (mesh->mLayerSet && mesh->mLayerSet->hasComposite()) + if (mesh->hasComposite()) { continue; // Mesh exists and has a composite texture. } @@ -952,6 +902,7 @@ BOOL LLVOAvatar::hasGray() const S32 LLVOAvatar::getRezzedStatus() const { if (getIsCloud()) return 0; + if (isFullyTextured() && allBakedTexturesCompletelyDownloaded()) return 3; if (isFullyTextured()) return 2; llassert(hasGray()); return 1; // gray @@ -1007,7 +958,7 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) { counts.clear(); - counts.resize(3); + counts.resize(4); for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { @@ -1025,6 +976,7 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status) if (rez_status==0) return "cloud"; if (rez_status==1) return "gray"; if (rez_status==2) return "textured"; + if (rez_status==3) return "textured_and_downloaded"; return "unknown"; } @@ -1086,15 +1038,15 @@ void LLVOAvatar::dumpBakedStatus() { llcont << " Unbaked ("; - for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++iter) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; if (!inst->isTextureDefined(index)) { - llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName; + llcont << " " << LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName; } } llcont << " ) " << inst->getUnbakedPixelAreaRank(); @@ -1115,7 +1067,7 @@ void LLVOAvatar::restoreGL() gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++) { - gAgentAvatarp->invalidateComposite(gAgentAvatarp->mBakedTextureDatas[i].mTexLayerSet, FALSE); + gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i), FALSE); } gAgentAvatarp->updateMeshTextures(); } @@ -1142,7 +1094,7 @@ void LLVOAvatar::resetImpostors() // static void LLVOAvatar::deleteCachedImages(bool clearAll) { - if (LLTexLayerSet::sHasCaches) + if (LLViewerTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); @@ -1151,7 +1103,7 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->deleteLayerSetCaches(clearAll); } - LLTexLayerSet::sHasCaches = FALSE; + LLViewerTexLayerSet::sHasCaches = FALSE; } LLVOAvatarSelf::deleteScratchTextures(); LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); @@ -1164,97 +1116,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) //------------------------------------------------------------------------ void LLVOAvatar::initClass() { - std::string xmlFile; - - xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; - BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); - if (!success) - { - llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl; - } - - // now sanity check xml file - LLXmlTreeNode* root = sXMLTree.getRoot(); - if (!root) - { - llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; - return; - } - - //------------------------------------------------------------------------- - // <linden_avatar version="1.0"> (root) - //------------------------------------------------------------------------- - if( !root->hasName( "linden_avatar" ) ) - { - llerrs << "Invalid avatar file header: " << xmlFile << llendl; - } - - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) - { - llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl; - } - - S32 wearable_def_version = 1; - static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); - root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); - LLWearable::setCurrentDefinitionVersion( wearable_def_version ); - - std::string mesh_file_name; - - LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); - if (!skeleton_node) - { - llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl; - return; - } - - std::string skeleton_file_name; - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) - { - llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl; - } - - std::string skeleton_path; - skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); - if (!parseSkeletonFile(skeleton_path)) - { - llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; - } - - // parse avatar_lad.xml - if (sAvatarXmlInfo) - { //this can happen if a login attempt failed - deleteAndClear(sAvatarXmlInfo); - } - sAvatarXmlInfo = new LLVOAvatarXmlInfo; - if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlColorNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise"); gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot"); gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion"); @@ -1271,85 +1132,12 @@ void LLVOAvatar::initClass() void LLVOAvatar::cleanupClass() { - deleteAndClear(sAvatarXmlInfo); - sSkeletonXMLTree = NULL; - sXMLTree.cleanup(); } +// virtual void LLVOAvatar::initInstance(void) { //------------------------------------------------------------------------- - // initialize joint, mesh and shape members - //------------------------------------------------------------------------- - mRoot.setName( "mRoot" ); - - for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - ++iter) - { - const EMeshIndex mesh_index = iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; - LLViewerJoint* joint = new LLViewerJoint(); - joint->setName(mesh_dict->mName); - joint->setMeshID(mesh_index); - mMeshLOD.push_back(joint); - - /* mHairLOD.setName("mHairLOD"); - mHairMesh0.setName("mHairMesh0"); - mHairMesh0.setMeshID(MESH_ID_HAIR); - mHairMesh1.setName("mHairMesh1"); */ - for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) - { - LLViewerJointMesh* mesh = new LLViewerJointMesh(); - std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod); - // We pre-pended an m - need to capitalize first character for camelCase - mesh_name[1] = toupper(mesh_name[1]); - mesh->setName(mesh_name); - mesh->setMeshID(mesh_index); - mesh->setPickName(mesh_dict->mPickName); - mesh->setIsTransparent(FALSE); - switch((int)mesh_index) - { - case MESH_ID_HAIR: - mesh->setIsTransparent(TRUE); - break; - case MESH_ID_SKIRT: - mesh->setIsTransparent(TRUE); - break; - case MESH_ID_EYEBALL_LEFT: - case MESH_ID_EYEBALL_RIGHT: - mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - break; - } - - joint->mMeshParts.push_back(mesh); - } - } - - //------------------------------------------------------------------------- - // associate baked textures with meshes - //------------------------------------------------------------------------- - for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - ++iter) - { - const EMeshIndex mesh_index = iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; - const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; - // Skip it if there's no associated baked texture. - if (baked_texture_index == BAKED_NUM_INDICES) continue; - - for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); - iter != mMeshLOD[mesh_index]->mMeshParts.end(); - ++iter) - { - LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter; - mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh); - } - } - - - //------------------------------------------------------------------------- // register motions //------------------------------------------------------------------------- if (LLCharacter::sInstances.size() == 1) @@ -1407,10 +1195,9 @@ void LLVOAvatar::initInstance(void) registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create ); registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); - } - - buildCharacter(); + + LLAvatarAppearance::initInstance(); // preload specific motions here createMotion( ANIM_AGENT_CUSTOMIZE); @@ -1419,7 +1206,30 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +} + +// virtual +LLAvatarJoint* LLVOAvatar::createAvatarJoint() +{ + return new LLViewerJoint(); +} +// virtual +LLAvatarJoint* LLVOAvatar::createAvatarJoint(S32 joint_num) +{ + return new LLViewerJoint(joint_num); +} + +// virtual +LLAvatarJointMesh* LLVOAvatar::createAvatarJointMesh() +{ + return new LLViewerJointMesh(); +} + +// virtual +LLTexLayerSet* LLVOAvatar::createTexLayerSet() +{ + return new LLViewerTexLayerSet(this); } const LLVector3 LLVOAvatar::getRenderPosition() const @@ -1494,7 +1304,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) float max_attachment_span = get_default_max_prim_scale() * 5.0f; //stretch bounding box by joint positions - for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) + for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) { LLPolyMesh* mesh = i->second; for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++) @@ -1732,149 +1542,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector return hit; } -//----------------------------------------------------------------------------- -// parseSkeletonFile() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) -{ - //------------------------------------------------------------------------- - // parse the file - //------------------------------------------------------------------------- - - LLXMLNodePtr skeleton_xml; - BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); - - if (!parsesuccess || skeleton_xml.isNull()) - { - llerrs << "Can't parse skeleton file: " << filename << llendl; - return FALSE; - } - - // Process XML data - if (sAvatarSkeletonInfo) - { //this can happen if a login attempt failed - delete sAvatarSkeletonInfo; - } - sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; - - LLXUIParser parser; - parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); - if (!sAvatarSkeletonInfo->validateBlock()) - { - llerrs << "Error parsing skeleton XML file: " << filename << llendl; - } - - if( !skeleton_xml->hasName( "linden_skeleton" ) ) - { - llerrs << "Invalid avatar skeleton file header: " << filename << llendl; - return FALSE; - } - - if (sAvatarSkeletonInfo->version() != "1.0") - { - llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl; - return FALSE; - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// setupBone() -//----------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) -{ - LLViewerJoint* joint = NULL; - if (info.bone.isChosen()) - { - joint = (LLViewerJoint*)getCharacterJoint(joint_num); - if (!joint) - { - llwarns << "Too many bones" << llendl; - return FALSE; - } - joint->setName( info.bone().name ); - joint->setPosition(info.bone().pos); - joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info.bone().scale); - joint->setSkinOffset( info.bone().pivot ); - joint_num++; - - for (LLInitParam::ParamIterator<LLVOAvatarChildJoint>::const_iterator child_it = info.bone().children.begin(), - end_it = info.bone().children.end(); - child_it != end_it; - ++child_it) - { - if (!setupBone(*child_it, joint, volume_num, joint_num)) - { - return FALSE; - } - } - } - else // collision volume - { - if (volume_num >= (S32)mNumCollisionVolumes) - { - llwarns << "Too many bones" << llendl; - return FALSE; - } - joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); - joint->setName( info.collision_volume.name); - joint->setPosition(info.collision_volume.pos); - joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info.collision_volume.scale); - volume_num++; - } - - // add to parent - if (parent) - { - parent->addChild( joint ); - } - - joint->setDefaultFromCurrentXform(); - - return TRUE; -} - -//----------------------------------------------------------------------------- -// buildSkeleton() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) -{ - //------------------------------------------------------------------------- - // allocate joints - //------------------------------------------------------------------------- - if (!allocateCharacterJoints(info->num_bones)) - { - llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl; - return FALSE; - } - //------------------------------------------------------------------------- - // allocate volumes - //------------------------------------------------------------------------- - if (info->num_collision_volumes) - { - if (!allocateCollisionVolumes(info->num_collision_volumes)) - { - llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl; - return FALSE; - } - } - - S32 current_joint_num = 0; - S32 current_volume_num = 0; - - if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num)) - { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } - - return TRUE; -} - LLVOAvatar* LLVOAvatar::asAvatar() { return this; @@ -1906,114 +1574,15 @@ void LLVOAvatar::startDefaultMotions() // LLVOAvatar::buildCharacter() // Deferred initialization and rebuild of the avatar. //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::buildCharacter() { - //------------------------------------------------------------------------- - // remove all references to our existing skeleton - // so we can rebuild it - //------------------------------------------------------------------------- - flushAllMotions(); + LLAvatarAppearance::buildCharacter(); - //------------------------------------------------------------------------- - // remove all of mRoot's children - //------------------------------------------------------------------------- - mRoot.removeAllChildren(); - mJointMap.clear(); + // Not done building yet; more to do. mIsBuilt = FALSE; //------------------------------------------------------------------------- - // clear mesh data - //------------------------------------------------------------------------- - for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); ++jointIter) - { - LLViewerJoint* joint = (LLViewerJoint*) *jointIter; - for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); - meshIter != joint->mMeshParts.end(); ++meshIter) - { - LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter; - mesh->setMesh(NULL); - } - } - - //------------------------------------------------------------------------- - // (re)load our skeleton and meshes - //------------------------------------------------------------------------- - LLTimer timer; - - BOOL status = loadAvatar(); - stop_glerror(); - -// gPrintMessagesThisFrame = TRUE; - lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; - - if (!status) - { - if (isSelf()) - { - llerrs << "Unable to load user's avatar" << llendl; - } - else - { - llwarns << "Unable to load other's avatar" << llendl; - } - return; - } - - //------------------------------------------------------------------------- - // initialize "well known" joint pointers - //------------------------------------------------------------------------- - mPelvisp = (LLViewerJoint*)mRoot.findJoint("mPelvis"); - mTorsop = (LLViewerJoint*)mRoot.findJoint("mTorso"); - mChestp = (LLViewerJoint*)mRoot.findJoint("mChest"); - mNeckp = (LLViewerJoint*)mRoot.findJoint("mNeck"); - mHeadp = (LLViewerJoint*)mRoot.findJoint("mHead"); - mSkullp = (LLViewerJoint*)mRoot.findJoint("mSkull"); - mHipLeftp = (LLViewerJoint*)mRoot.findJoint("mHipLeft"); - mHipRightp = (LLViewerJoint*)mRoot.findJoint("mHipRight"); - mKneeLeftp = (LLViewerJoint*)mRoot.findJoint("mKneeLeft"); - mKneeRightp = (LLViewerJoint*)mRoot.findJoint("mKneeRight"); - mAnkleLeftp = (LLViewerJoint*)mRoot.findJoint("mAnkleLeft"); - mAnkleRightp = (LLViewerJoint*)mRoot.findJoint("mAnkleRight"); - mFootLeftp = (LLViewerJoint*)mRoot.findJoint("mFootLeft"); - mFootRightp = (LLViewerJoint*)mRoot.findJoint("mFootRight"); - mWristLeftp = (LLViewerJoint*)mRoot.findJoint("mWristLeft"); - mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight"); - mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); - mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); - - //------------------------------------------------------------------------- - // Make sure "well known" pointers exist - //------------------------------------------------------------------------- - if (!(mPelvisp && - mTorsop && - mChestp && - mNeckp && - mHeadp && - mSkullp && - mHipLeftp && - mHipRightp && - mKneeLeftp && - mKneeRightp && - mAnkleLeftp && - mAnkleRightp && - mFootLeftp && - mFootRightp && - mWristLeftp && - mWristRightp && - mEyeLeftp && - mEyeRightp)) - { - llerrs << "Failed to create avatar." << llendl; - return; - } - - //------------------------------------------------------------------------- - // initialize the pelvis - //------------------------------------------------------------------------- - mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); - - //------------------------------------------------------------------------- // set head offset from pelvis //------------------------------------------------------------------------- updateHeadOffset(); @@ -2065,11 +1634,11 @@ void LLVOAvatar::releaseMeshData() //llinfos << "Releasing" << llendl; // cleanup mesh data - for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin(); + for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); iter != mMeshLOD.end(); ++iter) { - LLViewerJoint* joint = (LLViewerJoint*) *iter; + LLAvatarJoint* joint = (*iter); joint->setValid(FALSE, TRUE); } @@ -2158,7 +1727,11 @@ void LLVOAvatar::updateMeshData() last_v_num = num_vertices ; last_i_num = num_indices ; - mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + LLViewerJoint* part_mesh = getViewerJoint(part_index++); + if (part_mesh) + { + part_mesh->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + } } if(num_vertices < 1)//skip empty meshes { @@ -2232,7 +1805,11 @@ void LLVOAvatar::updateMeshData() rigid = true; } - mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); + LLViewerJoint* mesh = getViewerJoint(k); + if (mesh) + { + mesh->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); + } } stop_glerror(); @@ -2253,72 +1830,6 @@ void LLVOAvatar::updateMeshData() //------------------------------------------------------------------------ //------------------------------------------------------------------------ -// The viewer can only suggest a good size for the agent, -// the simulator will keep it inside a reasonable range. -void LLVOAvatar::computeBodySize() -{ - LLVector3 pelvis_scale = mPelvisp->getScale(); - - // some of the joints have not been cached - LLVector3 skull = mSkullp->getPosition(); - LLVector3 skull_scale = mSkullp->getScale(); - - LLVector3 neck = mNeckp->getPosition(); - LLVector3 neck_scale = mNeckp->getScale(); - - LLVector3 chest = mChestp->getPosition(); - LLVector3 chest_scale = mChestp->getScale(); - - // the rest of the joints have been cached - LLVector3 head = mHeadp->getPosition(); - LLVector3 head_scale = mHeadp->getScale(); - - LLVector3 torso = mTorsop->getPosition(); - LLVector3 torso_scale = mTorsop->getScale(); - - LLVector3 hip = mHipLeftp->getPosition(); - LLVector3 hip_scale = mHipLeftp->getScale(); - - LLVector3 knee = mKneeLeftp->getPosition(); - LLVector3 knee_scale = mKneeLeftp->getScale(); - - LLVector3 ankle = mAnkleLeftp->getPosition(); - LLVector3 ankle_scale = mAnkleLeftp->getScale(); - - LLVector3 foot = mFootLeftp->getPosition(); - - mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - - knee.mV[VZ] * hip_scale.mV[VZ] - - ankle.mV[VZ] * knee_scale.mV[VZ] - - foot.mV[VZ] * ankle_scale.mV[VZ]; - - LLVector3 new_body_size; - new_body_size.mV[VZ] = mPelvisToFoot + - // the sqrt(2) correction below is an approximate - // correction to get to the top of the head - F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + - head.mV[VZ] * neck_scale.mV[VZ] + - neck.mV[VZ] * chest_scale.mV[VZ] + - chest.mV[VZ] * torso_scale.mV[VZ] + - torso.mV[VZ] * pelvis_scale.mV[VZ]; - - // TODO -- measure the real depth and width - new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; - new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; - - if (new_body_size != mBodySize) - { - mBodySize = new_body_size; - - if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF()) - { // notify simulator of change in size - // but not if we are in the middle of updating appearance - gAgent.sendAgentSetAppearance(); - } - } -} - -//------------------------------------------------------------------------ // LLVOAvatar::processUpdateMessage() //------------------------------------------------------------------------ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, @@ -2326,7 +1837,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp) { - LLVector3 old_vel = getVelocity(); const BOOL has_name = !getNVPair("FirstName"); // Do base class updates... @@ -2354,20 +1864,50 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } -// virtual -S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) +LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUUID& uuid) { - // The core setTETexture() method requests images, so we need - // to redirect certain avatar texture requests to different sims. - if (isIndexBakedTexture((ETextureIndex)te)) + LLViewerFetchedTexture *result = NULL; + + if (uuid == IMG_DEFAULT_AVATAR || + uuid == IMG_DEFAULT || + uuid == IMG_INVISIBLE) { - LLHost target_host = getObjectHost(); - return setTETextureCore(te, uuid, target_host); + // Should already exist, don't need to find it on sim or baked-texture host. + result = gTextureList.findImage(uuid); } - else + + if (!result) { - return setTETextureCore(te, uuid, LLHost::invalid); + const std::string url = getImageURL(te,uuid); + if (!url.empty()) + { + LL_DEBUGS("Avatar") << avString() << "from URL " << url << llendl; + result = LLViewerTextureManager::getFetchedTextureFromUrl( + url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + } + else + { + LL_DEBUGS("Avatar") << avString() << "from host " << uuid << llendl; + LLHost host = getObjectHost(); + result = LLViewerTextureManager::getFetchedTexture( + uuid, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + } } + return result; +} + +// virtual +S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) +{ + if (!isIndexBakedTexture((ETextureIndex)te)) + { + // Sim still sends some uuids for non-baked slots sometimes - ignore. + return LLViewerObject::setTETexture(te, LLUUID::null); + } + + LLViewerFetchedTexture *image = getBakedTextureImage(te,uuid); + llassert(image); + return setTETextureCore(te, image); } static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Avatar Update"); @@ -2413,7 +1953,8 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return; } - if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) + if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)) + && !(gSavedSettings.getBOOL("DisableAllRenderTypes"))) { return; } @@ -2478,7 +2019,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // animate the character // store off last frame's root position to be consistent with camera position - LLVector3 root_pos_last = mRoot.getWorldPosition(); + LLVector3 root_pos_last = mRoot->getWorldPosition(); BOOL detailed_update = updateCharacter(agent); static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false); @@ -2597,11 +2138,11 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) if ( mIsSitting ) { LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); - mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); + mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot->getWorldPosition() + headOffset ); } else { - LLVector3 tagPos = mRoot.getWorldPosition(); + LLVector3 tagPos = mRoot->getWorldPosition(); tagPos[VZ] -= mPelvisToFoot; tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); @@ -3206,8 +2747,6 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; std::deque<LLChat>::iterator chat_iter = mChats.begin(); mNameText->clearString(); @@ -3334,7 +2873,7 @@ void LLVOAvatar::invalidateNameTags() // Compute name tag position during idle update void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { - LLQuaternion root_rot = mRoot.getWorldRotation(); + LLQuaternion root_rot = mRoot->getWorldRotation(); LLQuaternion inv_root_rot = ~root_rot; LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; @@ -3353,7 +2892,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) local_camera_up.scaleVec(avatar_ellipsoid); local_camera_at.scaleVec(avatar_ellipsoid); - LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot->getLastWorldPosition()) * inv_root_rot; if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) { @@ -3362,7 +2901,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); - LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); + LLVector3 name_position = mRoot->getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; @@ -3423,13 +2962,13 @@ void LLVOAvatar::idleUpdateBelowWater() void LLVOAvatar::slamPosition() { gAgent.setPositionAgent(getPositionAgent()); - mRoot.setWorldPosition(getPositionAgent()); // teleport + mRoot->setWorldPosition(getPositionAgent()); // teleport setChanged(TRANSLATED); if (mDrawable.notNull()) { gPipeline.updateMoveNormalAsync(mDrawable); } - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); } bool LLVOAvatar::isVisuallyMuted() const @@ -3450,6 +2989,47 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { // clear debug text mDebugText.clear(); + + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + S32 central_bake_version = -1; + if (getRegion()) + { + central_bake_version = getRegion()->getCentralBakeVersion(); + } + bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); + bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); + std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + isSelf() ? (all_local_downloaded ? "L" : "l") : "-", + all_baked_downloaded ? "B" : "b", + mUseLocalAppearance, mIsEditingAppearance, + mUseServerBakes, central_bake_version); + std::string origin_string = bakedTextureOriginInfo(); + debug_line += " [" + origin_string + "]"; + S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); + S32 last_request_cof_version = mLastUpdateRequestCOFVersion; + S32 last_received_cof_version = mLastUpdateReceivedCOFVersion; + if (isSelf()) + { + debug_line += llformat(" - cof: %d req: %d rcv:%d", + curr_cof_version, last_request_cof_version, last_received_cof_version); + if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure")) + { + debug_line += " FORCING ERRS"; + } + } + else + { + debug_line += llformat(" - cof rcv:%d", last_received_cof_version); + } + addDebugText(debug_line); + } + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + if (!mBakedTextureDebugText.empty()) + addDebugText(mBakedTextureDebugText); + } + if (LLVOAvatar::sShowAnimationDebug) { for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); @@ -3586,8 +3166,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) xyVel.mV[VZ] = 0.0f; speed = xyVel.length(); - BOOL throttle = TRUE; - if (!(mIsSitting && getParent())) { //-------------------------------------------------------------------- @@ -3598,11 +3176,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if (mTimeLast == 0.0f) { mTimeLast = animation_time; - throttle = FALSE; // put the pelvis at slaved position/mRotation - mRoot.setWorldPosition( getPositionAgent() ); // first frame - mRoot.setWorldRotation( getRotation() ); + mRoot->setWorldPosition( getPositionAgent() ); // first frame + mRoot->setWorldRotation( getRotation() ); } //-------------------------------------------------------------------- @@ -3627,6 +3204,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } root_pos = gAgent.getPosGlobalFromAgent(getRenderPosition()); + root_pos.mdV[VZ] += getVisualParamWeight(AVATAR_HOVER); + resolveHeightGlobal(root_pos, ground_under_pelvis, normal); F32 foot_to_ground = (F32) (root_pos.mdV[VZ] - mPelvisToFoot - ground_under_pelvis.mdV[VZ]); @@ -3645,10 +3224,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); - if (newPosition != mRoot.getXform()->getWorldPosition()) + if (newPosition != mRoot->getXform()->getWorldPosition()) { - mRoot.touch(); - mRoot.setWorldPosition( newPosition ); // regular update + mRoot->touch(); + mRoot->setWorldPosition( newPosition ); // regular update } @@ -3709,7 +3288,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } - LLQuaternion root_rotation = mRoot.getWorldMatrix().quaternion(); + LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion(); F32 root_roll, root_pitch, root_yaw; root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); @@ -3718,7 +3297,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // and head turn. Once in motion, it must conform however. BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); - LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV ); + LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV ); static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow"); static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast"); @@ -3804,14 +3383,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); - mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) ); + mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); } } else if (mDrawable.notNull()) { - mRoot.setPosition(mDrawable->getPosition()); - mRoot.setRotation(mDrawable->getRotation()); + mRoot->setPosition(mDrawable->getPosition()); + mRoot->setRotation(mDrawable->getRotation()); } //------------------------------------------------------------------------- @@ -3907,7 +3486,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); if (!mDebugText.size() && mText.notNull()) { @@ -3931,7 +3510,7 @@ void LLVOAvatar::updateHeadOffset() { // since we only care about Z, just grab one of the eyes LLVector3 midEyePt = mEyeLeftp->getWorldPosition(); - midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot.getWorldPosition(); + midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot->getWorldPosition(); midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]); if (mDrawable.notNull()) @@ -3969,8 +3548,8 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, void LLVOAvatar::postPelvisSetRecalc( void ) { computeBodySize(); - mRoot.touch(); - mRoot.updateWorldMatrixChildren(); + mRoot->touch(); + mRoot->updateWorldMatrixChildren(); dirtyMesh(); updateHeadOffset(); } @@ -4118,7 +3697,7 @@ void LLVOAvatar::updateVisibility() // private bool LLVOAvatar::shouldAlphaMask() { - const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked + const bool should_alpha_mask = !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked && !LLDrawPoolAvatar::sSkipTransparent; return should_alpha_mask; @@ -4157,19 +3736,44 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (mNeedsSkin) { //generate animated mesh - mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry(); - mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry(); + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + + if(upper_mesh) + { + upper_mesh->updateJointGeometry(); + } + if (lower_mesh) + { + lower_mesh->updateJointGeometry(); + } if( isWearingWearableType( LLWearableType::WT_SKIRT ) ) { - mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry(); + if(skirt_mesh) + { + skirt_mesh->updateJointGeometry(); + } } if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry(); - mMeshLOD[MESH_ID_HEAD]->updateJointGeometry(); - mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); + if(eyelash_mesh) + { + eyelash_mesh->updateJointGeometry(); + } + if(head_mesh) + { + head_mesh->updateJointGeometry(); + } + if(hair_mesh) + { + hair_mesh->updateJointGeometry(); + } } mNeedsSkin = FALSE; mLastSkinTime = gFrameTimeSeconds; @@ -4286,19 +3890,31 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy); + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + if (head_mesh) + { + num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); + } first_pass = FALSE; } } if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + if (upper_mesh) + { + num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + if (lower_mesh) + { + num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } } @@ -4331,7 +3947,11 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); - num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE); + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + if (skirt_mesh) + { + num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE); + } first_pass = FALSE; gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } @@ -4345,16 +3965,23 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) if (isTextureVisible(TEX_HEAD_BAKED)) { - num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + if (eyelash_mesh) + { + num_indices += eyelash_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } // Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair) // TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); - - if ( getImage(TEX_HAIR_BAKED, 0) - && getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha) + if ( getImage(TEX_HAIR_BAKED, 0) && + getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha) { - num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } if (LLPipeline::sImpostorRender) @@ -4398,8 +4025,16 @@ U32 LLVOAvatar::renderRigid() if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy); - num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy); + LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); + LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); + if (eyeball_left) + { + num_indices += eyeball_left->render(mAdjustedPixelArea, TRUE, mIsDummy); + } + if(eyeball_right) + { + num_indices += eyeball_right->render(mAdjustedPixelArea, TRUE, mIsDummy); + } } if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) @@ -4446,11 +4081,224 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) return 6; } -//------------------------------------------------------------------------ -// LLVOAvatar::updateTextures() -//------------------------------------------------------------------------ +bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const +{ + for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep && imagep->getDiscardLevel()!=0) + { + return false; + } + } + return true; +} + +bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() const +{ + std::set<LLUUID> local_ids; + collectLocalTextureUUIDs(local_ids); + return allTexturesCompletelyDownloaded(local_ids); +} + +bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const +{ + std::set<LLUUID> baked_ids; + collectBakedTextureUUIDs(baked_ids); + return allTexturesCompletelyDownloaded(baked_ids); +} + +void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has origin URL. + S32 &host_count, // host-based bake, has host. + S32 &both_count, // error - both host and URL set. + S32 &neither_count) // error - neither set. +{ + sb_count = host_count = both_count = neither_count = 0; + + std::set<LLUUID> baked_ids; + collectBakedTextureUUIDs(baked_ids); + for (std::set<LLUUID>::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + bool has_url = false, has_host = false; + if (!imagep->getUrl().empty()) + { + has_url = true; + } + if (imagep->getTargetHost().isOk()) + { + has_host = true; + } + if (has_url && !has_host) sb_count++; + else if (has_host && !has_url) host_count++; + else if (has_host && has_url) both_count++; + else if (!has_host && !has_url) neither_count++; + } +} + +std::string LLVOAvatar::bakedTextureOriginInfo() +{ + std::string result; + + std::set<LLUUID> baked_ids; + collectBakedTextureUUIDs(baked_ids); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex texture_index = mBakedTextureDatas[i].mTextureIndex; + LLViewerFetchedTexture *imagep = + LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + if (!imagep || + imagep->getID() == IMG_DEFAULT || + imagep->getID() == IMG_DEFAULT_AVATAR) + + { + result += "-"; + } + else + { + bool has_url = false, has_host = false; + if (!imagep->getUrl().empty()) + { + has_url = true; + } + if (imagep->getTargetHost().isOk()) + { + has_host = true; + } + S32 discard = imagep->getDiscardLevel(); + if (has_url && !has_host) result += discard ? "u" : "U"; // server-bake texture with url + else if (has_host && !has_url) result += discard ? "h" : "H"; // old-style texture on sim + else if (has_host && has_url) result += discard ? "x" : "X"; // both origins? + else if (!has_host && !has_url) result += discard ? "n" : "N"; // no origin? + if (discard != 0) + { + result += llformat("(%d/%d)",discard,imagep->getDesiredDiscardLevel()); + } + } + + } + return result; +} + +S32 LLVOAvatar::totalTextureMemForUUIDS(std::set<LLUUID>& ids) +{ + S32 result = 0; + for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep) + { + result += imagep->getTextureMemory(); + } + } + return result; +} + +void LLVOAvatar::collectLocalTextureUUIDs(std::set<LLUUID>& ids) const +{ + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + + LLViewerFetchedTexture *imagep = NULL; + for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); + if (imagep) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + if (texture_dict->mIsLocalTexture) + { + ids.insert(imagep->getID()); + } + } + } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); +} + +void LLVOAvatar::collectBakedTextureUUIDs(std::set<LLUUID>& ids) const +{ + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLViewerFetchedTexture *imagep = NULL; + if (isIndexBakedTexture((ETextureIndex) texture_index)) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + if (imagep) + { + ids.insert(imagep->getID()); + } + } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); +} + +void LLVOAvatar::collectTextureUUIDs(std::set<LLUUID>& ids) +{ + collectLocalTextureUUIDs(ids); + collectBakedTextureUUIDs(ids); +} + +void LLVOAvatar::releaseOldTextures() +{ + S32 current_texture_mem = 0; + + // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" + std::set<LLUUID> baked_texture_ids; + collectBakedTextureUUIDs(baked_texture_ids); + S32 new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); + + std::set<LLUUID> local_texture_ids; + collectLocalTextureUUIDs(local_texture_ids); + //S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); + + std::set<LLUUID> new_texture_ids; + new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); + new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); + S32 new_total_mem = totalTextureMemForUUIDS(new_texture_ids); + + //S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); + //LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << llendl; + if (!isSelf() && new_total_mem > new_baked_mem) + { + llwarns << "extra local textures stored for non-self av" << llendl; + } + for (std::set<LLUUID>::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) + { + if (new_texture_ids.find(*it) == new_texture_ids.end()) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep) + { + current_texture_mem += imagep->getTextureMemory(); + if (imagep->getTextureState() == LLGLTexture::NO_DELETE) + { + // This will allow the texture to be deleted if not in use. + imagep->forceActive(); + + // This resets the clock to texture being flagged + // as unused, preventing the texture from being + // deleted immediately. If other avatars or + // objects are using it, it can still be flagged + // no-delete by them. + imagep->forceUpdateBindStats(); + } + } + } + } + mTextureIDs = new_texture_ids; +} + void LLVOAvatar::updateTextures() { + releaseOldTextures(); + BOOL render_avatar = TRUE; if (mIsDummy) @@ -4493,7 +4341,7 @@ void LLVOAvatar::updateTextures() mHasGrey = FALSE; // debug for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); const LLTextureEntry *te = getTE(texture_index); @@ -4516,11 +4364,11 @@ void LLVOAvatar::updateTextures() imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; if (texture_dict->mIsLocalTexture) { - addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); + addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, mBakedTextureDatas[baked_index].mIsUsed); } } } @@ -4532,6 +4380,7 @@ void LLVOAvatar::updateTextures() if (isIndexBakedTexture((ETextureIndex)texture_index) && imagep->getID() != IMG_DEFAULT_AVATAR && imagep->getID() != IMG_INVISIBLE + && !isUsingServerBakes() && !imagep->getTargetHost().isOk()) { LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " @@ -4552,7 +4401,7 @@ void LLVOAvatar::updateTextures() void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index ) + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) { // No local texture stats for non-self avatars return; @@ -4626,7 +4475,6 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel //the texture pipeline will stop fetching this texture. imagep->resetTextureStats(); - imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures. imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; @@ -4635,7 +4483,7 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel imagep->addTextureStats(pixel_area / texel_area_ratio); imagep->setBoostLevel(boost_level); - if(boost_level != LLViewerTexture::BOOST_AVATAR_BAKED_SELF) + if(boost_level != LLGLTexture::BOOST_AVATAR_BAKED_SELF) { imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ; } @@ -4668,6 +4516,30 @@ void LLVOAvatar::setTexEntry(const U8 index, const LLTextureEntry &te) setTE(index, te); } +const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) +{ + llassert(isIndexBakedTexture(ETextureIndex(te))); + std::string url = ""; + if (isUsingServerBakes()) + { + const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL(); + if (appearance_service_url.empty()) + { + // Probably a server-side issue if we get here: + llwarns << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << llendl; + return url; + } + + const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + if (texture_entry != NULL) + { + url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); + //llinfos << "baked texture url: " << url << llendl; + } + } + return url; +} + //----------------------------------------------------------------------------- // resolveHeight() //----------------------------------------------------------------------------- @@ -5009,48 +4881,6 @@ void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id) } //----------------------------------------------------------------------------- -// getVolumePos() -//----------------------------------------------------------------------------- -LLVector3 LLVOAvatar::getVolumePos(S32 joint_index, LLVector3& volume_offset) -{ - if (joint_index > mNumCollisionVolumes) - { - return LLVector3::zero; - } - - return mCollisionVolumes[joint_index].getVolumePos(volume_offset); -} - -//----------------------------------------------------------------------------- -// findCollisionVolume() -//----------------------------------------------------------------------------- -LLJoint* LLVOAvatar::findCollisionVolume(U32 volume_id) -{ - if ((S32)volume_id > mNumCollisionVolumes) - { - return NULL; - } - - return &mCollisionVolumes[volume_id]; -} - -//----------------------------------------------------------------------------- -// findCollisionVolume() -//----------------------------------------------------------------------------- -S32 LLVOAvatar::getCollisionVolumeID(std::string &name) -{ - for (S32 i = 0; i < mNumCollisionVolumes; i++) - { - if (mCollisionVolumes[i].getName() == name) - { - return i; - } - } - - return -1; -} - -//----------------------------------------------------------------------------- // addDebugText() //----------------------------------------------------------------------------- void LLVOAvatar::addDebugText(const std::string& text) @@ -5079,7 +4909,7 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) if (iter == mJointMap.end() || iter->second == NULL) { //search for joint and cache found joint in lookup table - jointp = mRoot.findJoint(name); + jointp = mRoot->findJoint(name); mJointMap[name] = jointp; } else @@ -5095,10 +4925,12 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) //----------------------------------------------------------------------------- void LLVOAvatar::resetJointPositions( void ) { - for(S32 i = 0; i < (S32)mNumJoints; ++i) + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) { - mSkeleton[i].restoreOldXform(); - mSkeleton[i].setId( LLUUID::null ); + (*iter)->restoreOldXform(); + (*iter)->setId( LLUUID::null ); } mHasPelvisOffset = false; mPelvisFixup = mLastPelvisFixup; @@ -5108,7 +4940,7 @@ void LLVOAvatar::resetJointPositions( void ) //----------------------------------------------------------------------------- void LLVOAvatar::resetSpecificJointPosition( const std::string& name ) { - LLJoint* pJoint = mRoot.findJoint( name ); + LLJoint* pJoint = mRoot->findJoint( name ); if ( pJoint && pJoint->doesJointNeedToBeReset() ) { @@ -5130,16 +4962,17 @@ void LLVOAvatar::resetSpecificJointPosition( const std::string& name ) //----------------------------------------------------------------------------- void LLVOAvatar::resetJointPositionsToDefault( void ) { - //Subsequent joints are relative to pelvis - for( S32 i = 0; i < (S32)mNumJoints; ++i ) + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) { - LLJoint* pJoint = (LLJoint*)&mSkeleton[i]; + LLJoint* pJoint = (*iter); if ( pJoint->doesJointNeedToBeReset() ) { - pJoint->setId( LLUUID::null ); //restore joints to default positions, however skip over the pelvis + // *TODO: How does this pointer check skip over pelvis? if ( pJoint ) { pJoint->restoreOldXform(); @@ -5238,23 +5071,6 @@ F32 LLVOAvatar::getPixelArea() const } -//----------------------------------------------------------------------------- -// LLVOAvatar::getHeadMesh() -//----------------------------------------------------------------------------- -LLPolyMesh* LLVOAvatar::getHeadMesh() -{ - return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); -} - - -//----------------------------------------------------------------------------- -// LLVOAvatar::getUpperBodyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh* LLVOAvatar::getUpperBodyMesh() -{ - return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); -} - //----------------------------------------------------------------------------- // LLVOAvatar::getPosGlobalFromAgent() @@ -5272,61 +5088,6 @@ LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position) return gAgent.getPosAgentFromGlobal(position); } -//----------------------------------------------------------------------------- -// allocateCharacterJoints() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::allocateCharacterJoints( U32 num ) -{ - deleteAndClearArray(mSkeleton); - mNumJoints = 0; - - mSkeleton = new LLViewerJoint[num]; - - for(S32 joint_num = 0; joint_num < (S32)num; joint_num++) - { - mSkeleton[joint_num].setJointNum(joint_num); - } - - if (!mSkeleton) - { - return FALSE; - } - - mNumJoints = num; - return TRUE; -} - -//----------------------------------------------------------------------------- -// allocateCollisionVolumes() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::allocateCollisionVolumes( U32 num ) -{ - deleteAndClearArray(mCollisionVolumes); - mNumCollisionVolumes = 0; - - mCollisionVolumes = new LLViewerJointCollisionVolume[num]; - if (!mCollisionVolumes) - { - return FALSE; - } - - mNumCollisionVolumes = num; - return TRUE; -} - - -//----------------------------------------------------------------------------- -// getCharacterJoint() -//----------------------------------------------------------------------------- -LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) -{ - if ((S32)num >= mNumJoints - || (S32)num < 0) - { - return NULL; - } - return (LLJoint*)&mSkeleton[num]; -} //----------------------------------------------------------------------------- // requestStopMotion() @@ -5338,215 +5099,24 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion ) } //----------------------------------------------------------------------------- -// loadAvatar() -//----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar"); - -BOOL LLVOAvatar::loadAvatar() -{ -// LLFastTimer t(FTM_LOAD_AVATAR); - - // avatar_skeleton.xml - if( !buildSkeleton(sAvatarSkeletonInfo) ) - { - llwarns << "avatar file: buildSkeleton() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : <skeleton> - if( !loadSkeletonNode() ) - { - llwarns << "avatar file: loadNodeSkeleton() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : <mesh> - if( !loadMeshNodes() ) - { - llwarns << "avatar file: loadNodeMesh() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : <global_color> - if( sAvatarXmlInfo->mTexSkinColorInfo ) - { - mTexSkinColor = new LLTexGlobalColor( this ); - if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) - { - llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << "<global_color> name=\"skin_color\" not found" << llendl; - return FALSE; - } - if( sAvatarXmlInfo->mTexHairColorInfo ) - { - mTexHairColor = new LLTexGlobalColor( this ); - if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) - { - llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << "<global_color> name=\"hair_color\" not found" << llendl; - return FALSE; - } - if( sAvatarXmlInfo->mTexEyeColorInfo ) - { - mTexEyeColor = new LLTexGlobalColor( this ); - if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) - { - llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << "<global_color> name=\"eye_color\" not found" << llendl; - return FALSE; - } - - // avatar_lad.xml : <layer_set> - if (sAvatarXmlInfo->mLayerInfoList.empty()) - { - llwarns << "avatar file: missing <layer_set> node" << llendl; - return FALSE; - } - - if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) - { - llwarns << "avatar file: missing <morph_masks> node" << llendl; - return FALSE; - } - - // avatar_lad.xml : <morph_masks> - for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin(); - iter != sAvatarXmlInfo->mMorphMaskInfoList.end(); - ++iter) - { - LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter; - - EBakedTextureIndex baked = LLVOAvatarDictionary::findBakedByRegionName(info->mRegion); - if (baked != BAKED_NUM_INDICES) - { - LLPolyMorphTarget *morph_param; - const std::string *name = &info->mName; - morph_param = (LLPolyMorphTarget *)(getVisualParam(name->c_str())); - if (morph_param) - { - BOOL invert = info->mInvert; - addMaskedMorph(baked, morph_param, invert, info->mLayer); - } - } - - } - - loadLayersets(); - - // avatar_lad.xml : <driver_parameters> - for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); - iter != sAvatarXmlInfo->mDriverInfoList.end(); - ++iter) - { - LLDriverParamInfo *info = *iter; - LLDriverParam* driver_param = new LLDriverParam( this ); - if (driver_param->setInfo(info)) - { - addVisualParam( driver_param ); - LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam; - if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false)) - { - llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl; - continue; - } - } - else - { - delete driver_param; - llwarns << "avatar file: driver_param->parseData() failed" << llendl; - return FALSE; - } - } - - - return TRUE; -} - -//----------------------------------------------------------------------------- // loadSkeletonNode(): loads <skeleton> node from XML tree //----------------------------------------------------------------------------- +//virtual BOOL LLVOAvatar::loadSkeletonNode () { - mRoot.addChild( &mSkeleton[0] ); - - for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); - ++iter) - { - LLViewerJoint *joint = (LLViewerJoint *) *iter; - joint->mUpdateXform = FALSE; - joint->setMeshesToChildren(); - } - - mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); - mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]); - mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]); - mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]); - mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]); - mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); - - LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull"); - if (skull) - { - skull->addChild(mMeshLOD[MESH_ID_HAIR] ); - } - - LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); - if (eyeL) - { - eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); - } - - LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); - if (eyeR) + if (!LLAvatarAppearance::loadSkeletonNode()) { - eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); + return FALSE; } - // SKELETAL DISTORTIONS - { - LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; - for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); - ++iter) - { - LLPolySkeletalDistortionInfo *info = *iter; - LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); - if (!param->setInfo(info)) - { - delete param; - return FALSE; - } - else - { - addVisualParam(param); - } - } - } - // ATTACHMENTS { - LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter; + LLAvatarXmlInfo::attachment_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); iter != sAvatarXmlInfo->mAttachmentInfoList.end(); ++iter) { - LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter; + LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; if (!isSelf() && info->mJointName == "mScreen") { //don't process screen joint for other avatars continue; @@ -5619,144 +5189,6 @@ BOOL LLVOAvatar::loadSkeletonNode () } //----------------------------------------------------------------------------- -// loadMeshNodes(): loads <mesh> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::loadMeshNodes() -{ - for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); - meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); - ++meshinfo_iter) - { - const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter; - const std::string &type = info->mType; - S32 lod = info->mLOD; - - LLViewerJointMesh* mesh = NULL; - U8 mesh_id = 0; - BOOL found_mesh_id = FALSE; - - /* if (type == "hairMesh") - switch(lod) - case 0: - mesh = &mHairMesh0; */ - for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); - ++mesh_iter) - { - const EMeshIndex mesh_index = mesh_iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second; - if (type.compare(mesh_dict->mName) == 0) - { - mesh_id = mesh_index; - found_mesh_id = TRUE; - break; - } - } - - if (found_mesh_id) - { - if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) - { - mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; - } - else - { - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else - { - llwarns << "Ignoring unrecognized mesh type: " << type << llendl; - return FALSE; - } - - // llinfos << "Parsing mesh data for " << type << "..." << llendl; - - // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. - // Do not touch!!! - mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f ); - - LLPolyMesh *poly_mesh = NULL; - - if (!info->mReferenceMeshName.empty()) - { - polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); - if (polymesh_iter != mMeshes.end()) - { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); - poly_mesh->setAvatar(this); - } - else - { - // This should never happen - LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; - } - } - else - { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); - poly_mesh->setAvatar(this); - } - - if( !poly_mesh ) - { - llwarns << "Failed to load mesh of type " << type << llendl; - return FALSE; - } - - // Multimap insert - mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); - - mesh->setMesh( poly_mesh ); - mesh->setLOD( info->mMinPixelArea ); - - for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); - xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); - ++xmlinfo_iter) - { - const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); - LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); - if (!param->setInfo(info_pair->first)) - { - delete param; - return FALSE; - } - else - { - if (info_pair->second) - { - addSharedVisualParam(param); - } - else - { - addVisualParam(param); - } - } - } - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// loadLayerSets() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::loadLayersets() -{ - BOOL success = TRUE; - for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin(); - layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); - ++layerset_iter) - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - LLTexLayerSetInfo *layerset_info = *layerset_iter; - layerset_info->createVisualParams(this); - } - return success; -} - -//----------------------------------------------------------------------------- // updateVisualParams() //----------------------------------------------------------------------------- void LLVOAvatar::updateVisualParams() @@ -5769,7 +5201,7 @@ void LLVOAvatar::updateVisualParams() { computeBodySize(); mLastSkeletonSerialNum = mSkeletonSerialNum; - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); } dirtyMesh(); @@ -5856,7 +5288,12 @@ BOOL LLVOAvatar::updateJointLODs() } // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + LLViewerJoint* root = dynamic_cast<LLViewerJoint*>(mRoot); + BOOL res = FALSE; + if (root) + { + res = root->updateLOD(mAdjustedPixelArea, TRUE); + } if (res) { sNumLODChangesThisFrame++; @@ -5945,6 +5382,15 @@ void LLVOAvatar::dirtyMesh(S32 priority) { mDirtyMesh = llmax(mDirtyMesh, priority); } + +//----------------------------------------------------------------------------- +// getViewerJoint() +//----------------------------------------------------------------------------- +LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx) +{ + return dynamic_cast<LLViewerJoint*>(mMeshLOD[idx]); +} + //----------------------------------------------------------------------------- // hideSkirt() //----------------------------------------------------------------------------- @@ -6251,9 +5697,9 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) // Notice that removing sitDown() from here causes avatars sitting on // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655. sitDown(TRUE); - mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject - mRoot.setPosition(getPosition()); - mRoot.updateWorldMatrixChildren(); + mRoot->getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject + mRoot->setPosition(getPosition()); + mRoot->updateWorldMatrixChildren(); stopMotion(ANIM_AGENT_BODY_NOISE); @@ -6299,10 +5745,10 @@ void LLVOAvatar::getOffObject() sitDown(FALSE); - mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject - mRoot.setPosition(cur_position_world); - mRoot.setRotation(cur_rotation_world); - mRoot.getXform()->update(); + mRoot->getXform()->setParent(NULL); // LLVOAvatar::getOffObject + mRoot->setPosition(cur_position_world); + mRoot->setRotation(cur_rotation_world); + mRoot->getXform()->update(); startMotion(ANIM_AGENT_BODY_NOISE); @@ -6350,26 +5796,53 @@ S32 LLVOAvatar::getAttachmentCount() return count; } -LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const +BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const { - if (color_name=="skin_color" && mTexSkinColor) - { - return mTexSkinColor->getColor(); - } - else if(color_name=="hair_color" && mTexHairColor) + if (mIsDummy) return TRUE; + + if (isSelf()) { - return mTexHairColor->getColor(); + return LLAvatarAppearance::isWearingWearableType(type); } - if(color_name=="eye_color" && mTexEyeColor) + + switch(type) { - return mTexEyeColor->getColor(); + case LLWearableType::WT_SHAPE: + case LLWearableType::WT_SKIN: + case LLWearableType::WT_HAIR: + case LLWearableType::WT_EYES: + return TRUE; // everyone has all bodyparts + default: + break; // Do nothing } - else + + /* switch(type) + case LLWearableType::WT_SHIRT: + indicator_te = TEX_UPPER_SHIRT; */ + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + ++tex_iter) { - return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; + if (texture_dict->mWearableType == type) + { + // Thus, you must check to see if the corresponding baked texture is defined. + // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing + // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that + // gets baked into a texture that always exists (upper or lower). + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); + } + return FALSE; + } } + return FALSE; } + + // virtual void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) { @@ -6379,6 +5852,7 @@ void LLVOAvatar::invalidateAll() { } +// virtual void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake ) { if (global_color == mTexSkinColor) @@ -6397,9 +5871,15 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) { LLColor4 color = mTexHairColor->getColor(); - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor( color ); + } } } } @@ -6442,42 +5922,170 @@ BOOL LLVOAvatar::getIsCloud() const void LLVOAvatar::updateRezzedStatusTimers() { - // State machine for rezzed status. Statuses are 0 = cloud, 1 = gray, 2 = textured. - // Purpose is to collect time data for each period of cloud or cloud+gray. + // State machine for rezzed status. Statuses are -1 on startup, 0 + // = cloud, 1 = gray, 2 = textured, 3 = textured_and_downloaded. + // Purpose is to collect time data for each it takes avatar to reach + // various loading landmarks: gray, textured (partial), textured fully. + S32 rez_status = getRezzedStatus(); if (rez_status != mLastRezzedStatus) { LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; - bool is_cloud_or_gray = (rez_status==0 || rez_status==1); - bool was_cloud_or_gray = (mLastRezzedStatus==0 || mLastRezzedStatus==1); - bool is_cloud = (rez_status==0); - bool was_cloud = (mLastRezzedStatus==0); - // Non-cloud to cloud - if (is_cloud && !was_cloud) + if (mLastRezzedStatus == -1 && rez_status != -1) + { + // First time initialization, start all timers. + for (S32 i = 1; i < 4; i++) + { + startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + startPhase("first_load_" + LLVOAvatar::rezStatusToString(i)); + } + } + if (rez_status < mLastRezzedStatus) + { + // load level has decreased. start phase timers for higher load levels. + for (S32 i = rez_status+1; i <= mLastRezzedStatus; i++) + { + startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + } + } + else if (rez_status > mLastRezzedStatus) + { + // load level has increased. stop phase timers for lower and equal load levels. + for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++) + { + stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); + stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); + } + if (rez_status == 3) + { + // "fully loaded", mark any pending appearance change complete. + selfStopPhase("update_appearance_from_cof"); + selfStopPhase("wear_inventory_category", false); + selfStopPhase("process_initial_wearables_update", false); + } + } + + mLastRezzedStatus = rez_status; + } +} + +void LLVOAvatar::clearPhases() +{ + getPhases().clearPhases(); +} + +void LLVOAvatar::startPhase(const std::string& phase_name) +{ + F32 elapsed; + bool completed; + if (getPhases().getPhaseValues(phase_name, elapsed, completed)) + { + if (!completed) { - // start cloud timer. - getPhases().startPhase("cloud"); + LL_DEBUGS("Avatar") << avString() << "no-op, start when started already for " << phase_name << llendl; + return; } - else if (was_cloud && !is_cloud) + } + LL_DEBUGS("Avatar") << "started phase " << phase_name << llendl; + getPhases().startPhase(phase_name); +} + +void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check) +{ + F32 elapsed; + bool completed; + if (getPhases().getPhaseValues(phase_name, elapsed, completed)) + { + if (!completed) { - // stop cloud timer, which will capture stats. - getPhases().stopPhase("cloud"); + getPhases().stopPhase(phase_name); + completed = true; + logMetricsTimerRecord(phase_name, elapsed, completed); + LL_DEBUGS("Avatar") << avString() << "stopped phase " << phase_name << " elapsed " << elapsed << llendl; } + else + { + if (err_check) + { + LL_DEBUGS("Avatar") << "no-op, stop when stopped already for " << phase_name << llendl; + } + } + } + else + { + if (err_check) + { + LL_DEBUGS("Avatar") << "no-op, stop when not started for " << phase_name << llendl; + } + } +} - // Non-cloud-or-gray to cloud-or-gray - if (is_cloud_or_gray && !was_cloud_or_gray) +void LLVOAvatar::logPendingPhases() +{ + if (!isAgentAvatarValid()) + { + return; + } + + for (LLViewerStats::phase_map_t::iterator it = getPhases().begin(); + it != getPhases().end(); + ++it) + { + const std::string& phase_name = it->first; + F32 elapsed; + bool completed; + if (getPhases().getPhaseValues(phase_name, elapsed, completed)) { - // start cloud-or-gray timer. - getPhases().startPhase("cloud-or-gray"); + if (!completed) + { + logMetricsTimerRecord(phase_name, elapsed, completed); + } } - else if (was_cloud_or_gray && !is_cloud_or_gray) + } +} + +//static +void LLVOAvatar::logPendingPhasesAllAvatars() +{ + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if( inst->isDead() ) { - // stop cloud-or-gray timer, which will capture stats. - getPhases().stopPhase("cloud-or-gray"); + continue; } - - mLastRezzedStatus = rez_status; + inst->logPendingPhases(); + } +} + +void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed) +{ + if (!isAgentAvatarValid()) + { + return; + } + + LLSD record; + record["timer_name"] = phase_name; + record["avatar_id"] = getID(); + record["elapsed"] = elapsed; + record["completed"] = completed; + U32 grid_x(0), grid_y(0); + if (getRegion()) + { + record["central_bake_version"] = LLSD::Integer(getRegion()->getCentralBakeVersion()); + grid_from_region_handle(getRegion()->getHandle(), &grid_x, &grid_y); + } + record["grid_x"] = LLSD::Integer(grid_x); + record["grid_y"] = LLSD::Integer(grid_y); + record["is_using_server_bakes"] = ((bool) isUsingServerBakes()); + record["is_self"] = isSelf(); + + if (isAgentAvatarValid()) + { + gAgentAvatarp->addMetricsTimerRecord(record); } } @@ -6574,24 +6182,49 @@ LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const return mMotionController.findMotion(id); } +// This is a semi-deprecated debugging tool - meshes will not show as +// colorized if using deferred rendering. +void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) +{ + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + { + mesh->setColor(color); + } + } + } + } +} + //----------------------------------------------------------------------------- // updateMeshTextures() // Uses the current TE values to set the meshes' and layersets' textures. //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::updateMeshTextures() { - // llinfos << "updateMeshTextures" << llendl; + static S32 update_counter = 0; + mBakedTextureDebugText.clear(); + // if user has never specified a texture, assign the default for (U32 i=0; i < getNumTEs(); i++) { const LLViewerTexture* te_image = getImage(i, 0); if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) { - setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered. + // IMG_DEFAULT_AVATAR = a special texture that's never rendered. + const LLUUID& image_id = (i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR); + setImage(i, LLViewerTextureManager::getFetchedTexture(image_id), 0); } } - const BOOL self_customizing = isSelf() && gAgentCamera.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures const BOOL other_culled = !isSelf() && mCulled; LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; BOOL paused = FALSE; @@ -6607,71 +6240,97 @@ void LLVOAvatar::updateMeshTextures() std::vector<BOOL> use_lkg_baked_layer; // lkg = "last known good" use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false); + mBakedTextureDebugText += llformat("%06d\n",update_counter++); + mBakedTextureDebugText += "indx layerset linvld ltda ilb ulkg ltid\n"; for (U32 i=0; i < mBakedTextureDatas.size(); i++) { is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); - + LLViewerTexLayerSet* layerset = NULL; + bool layerset_invalid = false; if (!other_culled) { // When an avatar is changing clothes and not in Appearance mode, - // use the last-known good baked texture until it finish the first + // use the last-known good baked texture until it finishes the first // render of the new layerset. - const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet - && ( !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized() - || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() ); + layerset = getTexLayerSet(i); + layerset_invalid = layerset && ( !layerset->getViewerComposite()->isInitialized() + || !layerset->isLocalTextureDataAvailable() ); use_lkg_baked_layer[i] = (!is_layer_baked[i] - && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) + && (mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR) && layerset_invalid); if (use_lkg_baked_layer[i]) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); + layerset->setUpdatesEnabled(TRUE); } } else { use_lkg_baked_layer[i] = (!is_layer_baked[i] - && mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); - if (mBakedTextureDatas[i].mTexLayerSet) - { - mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); - } + && mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR); } - } - - // Turn on alpha masking correctly for yourself and other avatars on 1.23+ - mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR]; - - // Baked textures should be requested from the sim this avatar is on. JC - const LLHost target_host = getObjectHost(); - if (!target_host.isOk()) - { - llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; + std::string last_id_string; + if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT_AVATAR) + last_id_string = "A"; + else if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT) + last_id_string = "D"; + else if (mBakedTextureDatas[i].mLastTextureID == IMG_INVISIBLE) + last_id_string = "I"; + else + last_id_string = "*"; + bool is_ltda = layerset + && layerset->getViewerComposite()->isInitialized() + && layerset->isLocalTextureDataAvailable(); + mBakedTextureDebugText += llformat("%4d %4s %4d %4d %4d %4d %4s\n", + i, + (layerset?"*":"0"), + layerset_invalid, + is_ltda, + is_layer_baked[i], + use_lkg_baked_layer[i], + last_id_string.c_str()); } for (U32 i=0; i < mBakedTextureDatas.size(); i++) { - if (use_lkg_baked_layer[i] && !self_customizing ) + debugColorizeSubMeshes(i, LLColor4::white); + + LLViewerTexLayerSet* layerset = getTexLayerSet(i); + if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host ); + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); mBakedTextureDatas[i].mIsUsed = TRUE; - for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + + debugColorizeSubMeshes(i,LLColor4::red); + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img ); + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setTexture( baked_img ); + } } } - else if (!self_customizing && is_layer_baked[i]) + else if (!isUsingLocalAppearance() && is_layer_baked[i]) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; - if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex ) + LLViewerFetchedTexture* baked_img = + LLViewerTextureManager::staticCastToFetchedTexture( + getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; + if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureID ) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). + // Even though the file may not be finished loading, + // we'll consider it loaded and use it (rather than + // doing compositing). useBakedTexture( baked_img->getID() ); } else { mBakedTextureDatas[i].mIsLoaded = FALSE; - if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) + if ( (baked_img->getID() != IMG_INVISIBLE) && + ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), src_callback_list, paused); @@ -6680,40 +6339,59 @@ void LLVOAvatar::updateMeshTextures() src_callback_list, paused ); } } - else if (mBakedTextureDatas[i].mTexLayerSet - && !other_culled) + else if (layerset && isUsingLocalAppearance()) { - mBakedTextureDatas[i].mTexLayerSet->createComposite(); - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE ); + debugColorizeSubMeshes(i,LLColor4::yellow ); + + layerset->createComposite(); + layerset->setUpdatesEnabled( TRUE ); mBakedTextureDatas[i].mIsUsed = FALSE; - for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet ); + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setLayerSet( layerset ); + } } } + else + { + debugColorizeSubMeshes(i,LLColor4::blue); + } } // set texture and color of hair manually if we are not using a baked image. // This can happen while loading hair for yourself, or for clients that did not // bake a hair texture. Still needed for yourself after 1.22 is depricated. - if (!is_layer_baked[BAKED_HAIR] || self_customizing) + if (!is_layer_baked[BAKED_HAIR] || isEditingAppearance()) { const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor( color ); + mesh->setTexture( hair_img ); + } } } - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); @@ -6741,7 +6419,7 @@ void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, B } //virtual -void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatar::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { // invalid for anyone but self llassert(0); @@ -6776,18 +6454,30 @@ void LLVOAvatar::clearChat() mChats.clear(); } -// adds a morph mask to the appropriate baked texture structure -void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer) + +void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index) { - if (index < BAKED_NUM_INDICES) + if (index >= BAKED_NUM_INDICES) { - LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); - mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); + llwarns << "invalid baked texture index passed to applyMorphMask" << llendl; + return; + } + + for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); + iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) + { + const LLMaskedMorph* maskedMorph = (*iter); + LLPolyMorphTarget* morph_target = dynamic_cast<LLPolyMorphTarget*>(maskedMorph->mMorphTarget); + if (morph_target) + { + morph_target->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); + } } } + // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise -BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index) +BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index) { if (index >= BAKED_NUM_INDICES) { @@ -6798,7 +6488,7 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde { if (isSelf()) { - LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet; + LLViewerTexLayerSet *layer_set = getTexLayerSet(index); if (layer_set) { return !layer_set->isMorphValid(); @@ -6813,23 +6503,6 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde return FALSE; } -void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index) -{ - if (index >= BAKED_NUM_INDICES) - { - llwarns << "invalid baked texture index passed to applyMorphMask" << llendl; - return; - } - - for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); - iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) - { - const LLMaskedMorph* maskedMorph = (*iter); - maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); - } -} - - //----------------------------------------------------------------------------- // releaseComponentTextures() // release any component texture UUIDs for which we have a baked texture @@ -6852,7 +6525,7 @@ void LLVOAvatar::releaseComponentTextures() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLVOAvatarDictionary::BakedEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID if (!isTextureDefined(bakedDicEntry->mTextureIndex) && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) @@ -6868,120 +6541,14 @@ void LLVOAvatar::releaseComponentTextures() } } -//static -BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name ) -{ - switch( te ) - { - case TEX_UPPER_SHIRT: - param_name[0] = 803; //"shirt_red"; - param_name[1] = 804; //"shirt_green"; - param_name[2] = 805; //"shirt_blue"; - break; - - case TEX_LOWER_PANTS: - param_name[0] = 806; //"pants_red"; - param_name[1] = 807; //"pants_green"; - param_name[2] = 808; //"pants_blue"; - break; - - case TEX_LOWER_SHOES: - param_name[0] = 812; //"shoes_red"; - param_name[1] = 813; //"shoes_green"; - param_name[2] = 817; //"shoes_blue"; - break; - - case TEX_LOWER_SOCKS: - param_name[0] = 818; //"socks_red"; - param_name[1] = 819; //"socks_green"; - param_name[2] = 820; //"socks_blue"; - break; - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - param_name[0] = 834; //"jacket_red"; - param_name[1] = 835; //"jacket_green"; - param_name[2] = 836; //"jacket_blue"; - break; - - case TEX_UPPER_GLOVES: - param_name[0] = 827; //"gloves_red"; - param_name[1] = 829; //"gloves_green"; - param_name[2] = 830; //"gloves_blue"; - break; - - case TEX_UPPER_UNDERSHIRT: - param_name[0] = 821; //"undershirt_red"; - param_name[1] = 822; //"undershirt_green"; - param_name[2] = 823; //"undershirt_blue"; - break; - - case TEX_LOWER_UNDERPANTS: - param_name[0] = 824; //"underpants_red"; - param_name[1] = 825; //"underpants_green"; - param_name[2] = 826; //"underpants_blue"; - break; - - case TEX_SKIRT: - param_name[0] = 921; //"skirt_red"; - param_name[1] = 922; //"skirt_green"; - param_name[2] = 923; //"skirt_blue"; - break; - - case TEX_HEAD_TATTOO: - case TEX_LOWER_TATTOO: - case TEX_UPPER_TATTOO: - param_name[0] = 1071; //"tattoo_red"; - param_name[1] = 1072; //"tattoo_green"; - param_name[2] = 1073; //"tattoo_blue"; - break; - - default: - llassert(0); - return FALSE; - } - - return TRUE; -} - -void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) -{ - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake ); - setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake ); - setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake ); - } -} - -LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) -{ - LLColor4 color; - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - color.mV[VX] = getVisualParamWeight( param_name[0] ); - color.mV[VY] = getVisualParamWeight( param_name[1] ); - color.mV[VZ] = getVisualParamWeight( param_name[2] ); - } - return color; -} - -// static -LLColor4 LLVOAvatar::getDummyColor() -{ - return DUMMY_COLOR; -} - void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; // TODO: MULTI-WEARABLE: handle multiple textures for self const LLViewerTexture* te_image = getImage(iter->first,0); if( !te_image ) @@ -7007,48 +6574,6 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const } } -// Unlike most wearable functions, this works for both self and other. -BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const -{ - if (mIsDummy) return TRUE; - - switch(type) - { - case LLWearableType::WT_SHAPE: - case LLWearableType::WT_SKIN: - case LLWearableType::WT_HAIR: - case LLWearableType::WT_EYES: - return TRUE; // everyone has all bodyparts - default: - break; // Do nothing - } - - /* switch(type) - case LLWearableType::WT_SHIRT: - indicator_te = TEX_UPPER_SHIRT; */ - for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - ++tex_iter) - { - const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second; - if (texture_dict->mWearableType == type) - { - // If you're checking another avatar's clothing, you don't have component textures. - // Thus, you must check to see if the corresponding baked texture is defined. - // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing - // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that - // gets baked into a texture that always exists (upper or lower). - if (texture_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); - } - return FALSE; - } - } - return FALSE; -} - //----------------------------------------------------------------------------- // clampAttachmentPositions() //----------------------------------------------------------------------------- @@ -7129,7 +6654,7 @@ LLBBox LLVOAvatar::getHUDBBox() const //----------------------------------------------------------------------------- void LLVOAvatar::onFirstTEMessageReceived() { - LL_INFOS("Avatar") << avString() << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << LL_ENDL; if( !mFirstTEMessageReceived ) { mFirstTEMessageReceived = TRUE; @@ -7151,7 +6676,7 @@ void LLVOAvatar::onFirstTEMessageReceived() if (layer_baked) { LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; - mBakedTextureDatas[i].mLastTextureIndex = image->getID(); + mBakedTextureDatas[i].mLastTextureID = image->getID(); // If we have more than one texture for the other baked layers, we'll want to call this for them too. if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { @@ -7203,85 +6728,106 @@ bool LLVOAvatar::visualParamWeightsAreDefault() return rtn; } - -//----------------------------------------------------------------------------- -// processAvatarAppearance() -//----------------------------------------------------------------------------- -void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) +void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value) { - if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages")) + std::string type_string = "unknown"; + if (dynamic_cast<LLTexLayerParamAlpha*>(viewer_param)) + type_string = "param_alpha"; + if (dynamic_cast<LLTexLayerParamColor*>(viewer_param)) + type_string = "param_color"; + if (dynamic_cast<LLDriverParam*>(viewer_param)) + type_string = "param_driver"; + if (dynamic_cast<LLPolyMorphTarget*>(viewer_param)) + type_string = "param_morph"; + if (dynamic_cast<LLPolySkeletalDistortion*>(viewer_param)) + type_string = "param_skeleton"; + S32 wtype = -1; + LLViewerVisualParam *vparam = dynamic_cast<LLViewerVisualParam*>(viewer_param); + if (vparam) { - llwarns << "Blocking AvatarAppearance message" << llendl; - return; + wtype = vparam->getWearableType(); } - - BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; - mFirstAppearanceMessageReceived = TRUE; + S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); + apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\"/>\n", + viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(), + LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str() +// param_location_name(vparam->getParamLocation()).c_str() + ); +} - LL_INFOS("Avatar") << avString() << "processAvatarAppearance start " << mID - << " first? " << is_first_appearance_message << " self? " << isSelf() << LL_ENDL; +void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, + const LLAppearanceMessageContents& contents) +{ + std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml"); + const std::vector<F32>& params_for_dump = contents.mParamWeights; + const LLTEContents& tec = contents.mTEContents; - if( isSelf() ) + LLAPRFile outfile; + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + outfile.open(fullpath, LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle(); + if (!file) { - llwarns << avString() << "Received AvatarAppearance for self" << llendl; - if( mFirstTEMessageReceived ) - { -// llinfos << "processAvatarAppearance end " << mID << llendl; - return; - } + return; + } + else + { + LL_DEBUGS("Avatar") << "dumping appearance message to " << fullpath << llendl; } - ESex old_sex = getSex(); - -// llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; -// dumpAvatarTEs( "PRE processAvatarAppearance()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData); -// dumpAvatarTEs( "POST processAvatarAppearance()" ); + apr_file_printf(file, "<header>\n"); + apr_file_printf(file, "\t\t<cof_version %i />\n", contents.mCOFVersion); + apr_file_printf(file, "\t\t<appearance_version %i />\n", contents.mAppearanceVersion); + apr_file_printf(file, "</header>\n"); - // prevent the overwriting of valid baked textures with invalid baked textures - for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) + apr_file_printf(file, "\n<params>\n"); + LLVisualParam* param = getFirstVisualParam(); + for (S32 i = 0; i < params_for_dump.size(); i++) { - if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) - && mBakedTextureDatas[baked_index].mLastTextureIndex != IMG_DEFAULT - && baked_index != BAKED_SKIRT) + while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT { - setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, - TRUE, - LLViewerTexture::BOOST_NONE, - LLViewerTexture::LOD_TEXTURE)); + param = getNextVisualParam(); } + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + F32 value = params_for_dump[i]; + dump_visual_param(file, viewer_param, value); + param = getNextVisualParam(); } + apr_file_printf(file, "</params>\n"); - - // runway - was - // if (!is_first_appearance_message ) - // which means it would be called on second appearance message - probably wrong. - if (is_first_appearance_message ) + apr_file_printf(file, "\n<textures>\n"); + for (U32 i = 0; i < tec.face_count; i++) { - onFirstTEMessageReceived(); + std::string uuid_str; + ((LLUUID*)tec.image_data)[i].toString(uuid_str); + apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", i, uuid_str.c_str()); } + apr_file_printf(file, "</textures>\n"); +} - setCompositeUpdatesEnabled( FALSE ); - mMeshTexturesDirty = TRUE; - gPipeline.markGLRebuild(this); +void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& contents) +{ + parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, contents.mTEContents); - // ! BACKWARDS COMPATIBILITY ! - // Non-self avatars will no longer have component textures - if (!isSelf()) + // Parse the AppearanceData field, if any. + if (mesgsys->has(_PREHASH_AppearanceData)) { - releaseComponentTextures(); + U8 av_u8; + mesgsys->getU8Fast(_PREHASH_AppearanceData, _PREHASH_AppearanceVersion, av_u8, 0); + contents.mAppearanceVersion = av_u8; + LL_DEBUGS("Avatar") << "appversion set by AppearanceData field: " << contents.mAppearanceVersion << llendl; + mesgsys->getS32Fast(_PREHASH_AppearanceData, _PREHASH_CofVersion, contents.mCOFVersion, 0); + // For future use: + //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); } - - // parse visual params + + // Parse visual params, if any. S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing if( num_blocks > 1 && !drop_visual_params_debug) { LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; - BOOL params_changed = FALSE; - BOOL interp_params = FALSE; LLVisualParam* param = getFirstVisualParam(); llassert(param); // if this ever fires, we should do the same as when num_blocks<=1 @@ -7307,21 +6853,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) U8 value; mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + contents.mParamWeights.push_back(newWeight); + contents.mParams.push_back(param); - if (is_first_appearance_message || (param->getWeight() != newWeight)) - { - //llinfos << "Received update for param " << param->getDisplayName() << " at value " << newWeight << llendl; - params_changed = TRUE; - if(is_first_appearance_message) - { - param->setWeight(newWeight, FALSE); - } - else - { - interp_params = TRUE; - param->setAnimationTarget(newWeight, FALSE); - } - } param = getNextVisualParam(); } } @@ -7329,7 +6863,210 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT if (num_blocks != expected_tweakable_count) { - llinfos << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << llendl; + LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << llendl; + } + } + else + { + if (drop_visual_params_debug) + { + llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; + } + else + { + LL_DEBUGS("Avatar") << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl; + } + } + + LLVisualParam* appearance_version_param = getVisualParam(11000); + if (appearance_version_param) + { + std::vector<LLVisualParam*>::iterator it = std::find(contents.mParams.begin(), contents.mParams.end(),appearance_version_param); + if (it != contents.mParams.end()) + { + S32 index = it - contents.mParams.begin(); + contents.mParamAppearanceVersion = llround(contents.mParamWeights[index]); + LL_DEBUGS("Avatar") << "appversion req by appearance_version param: " << contents.mParamAppearanceVersion << llendl; + } + } +} + +bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32& appearance_version) +{ + appearance_version = -1; + + if ((contents.mAppearanceVersion) >= 0 && + (contents.mParamAppearanceVersion >= 0) && + (contents.mAppearanceVersion != contents.mParamAppearanceVersion)) + { + llwarns << "inconsistent appearance_version settings - field: " << + contents.mAppearanceVersion << ", param: " << contents.mParamAppearanceVersion << llendl; + return false; + } + if (contents.mParamAppearanceVersion >= 0) // use visual param if available. + { + appearance_version = contents.mParamAppearanceVersion; + } + if (contents.mAppearanceVersion >= 0) + { + appearance_version = contents.mAppearanceVersion; + } + if (appearance_version < 0) // still not set, go with 0. + { + appearance_version = 0; + } + LL_DEBUGS("Avatar") << "appearance version info - field " << contents.mAppearanceVersion + << " param: " << contents.mParamAppearanceVersion + << " final: " << appearance_version << llendl; + return true; +} + +//----------------------------------------------------------------------------- +// processAvatarAppearance() +//----------------------------------------------------------------------------- +void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) +{ + LL_DEBUGS("Avatar") << "starts" << llendl; + + bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); + std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_"; + if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages")) + { + llwarns << "Blocking AvatarAppearance message" << llendl; + return; + } + + ESex old_sex = getSex(); + + LLAppearanceMessageContents contents; + parseAppearanceMessage(mesgsys, contents); + if (enable_verbose_dumps) + { + dumpAppearanceMsgParams(dump_prefix + "appearance_msg", contents); + } + + S32 appearance_version; + if (!resolve_appearance_version(contents, appearance_version)) + { + llwarns << "bad appearance version info, discarding" << llendl; + return; + } + S32 this_update_cof_version = contents.mCOFVersion; + S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion; + + // Only now that we have result of appearance_version can we decide whether to bail out. + if( isSelf() ) + { + LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version + << " last_update_request_cof_version " << last_update_request_cof_version + << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << llendl; + + if (getRegion() && (getRegion()->getCentralBakeVersion()==0)) + { + llwarns << avString() << "Received AvatarAppearance message for self in non-server-bake region" << llendl; + } + if( mFirstTEMessageReceived && (appearance_version == 0)) + { + return; + } + } + else + { + LL_DEBUGS("Avatar") << "appearance message received" << llendl; + } + + // Check for stale update. + if (isSelf() + && (appearance_version>0) + && (this_update_cof_version < last_update_request_cof_version)) + { + llwarns << "Stale appearance update, wanted version " << last_update_request_cof_version + << ", got " << this_update_cof_version << llendl; + return; + } + + if (isSelf() && isEditingAppearance()) + { + LL_DEBUGS("Avatar") << "ignoring appearance message while in appearance edit" << llendl; + return; + } + + S32 num_params = contents.mParamWeights.size(); + if (num_params <= 1) + { + // In this case, we have no reliable basis for knowing + // appearance version, which may cause us to look for baked + // textures in the wrong place and flag them as missing + // assets. + LL_DEBUGS("Avatar") << "ignoring appearance message due to lack of params" << llendl; + return; + } + + mLastUpdateReceivedCOFVersion = this_update_cof_version; + + setIsUsingServerBakes(appearance_version > 0); + + applyParsedTEMessage(contents.mTEContents); + + // prevent the overwriting of valid baked textures with invalid baked textures + for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) + { + if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) + && mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT + && baked_index != BAKED_SKIRT) + { + setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + } + } + + // runway - was + // if (!is_first_appearance_message ) + // which means it would be called on second appearance message - probably wrong. + BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; + mFirstAppearanceMessageReceived = TRUE; + + LL_DEBUGS("Avatar") << avString() << "processAvatarAppearance start " << mID + << " first? " << is_first_appearance_message << " self? " << isSelf() << LL_ENDL; + + if (is_first_appearance_message ) + { + onFirstTEMessageReceived(); + } + + setCompositeUpdatesEnabled( FALSE ); + gPipeline.markGLRebuild(this); + + // Apply visual params + if( num_params > 1) + { + LL_DEBUGS("Avatar") << avString() << " handle visual params, num_params " << num_params << LL_ENDL; + BOOL params_changed = FALSE; + BOOL interp_params = FALSE; + + for( S32 i = 0; i < num_params; i++ ) + { + LLVisualParam* param = contents.mParams[i]; + F32 newWeight = contents.mParamWeights[i]; + + if (is_first_appearance_message || (param->getWeight() != newWeight)) + { + params_changed = TRUE; + if(is_first_appearance_message) + { + param->setWeight(newWeight, FALSE); + } + else + { + interp_params = TRUE; + param->setAnimationTarget(newWeight, FALSE); + } + } + } + const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + if (num_params != expected_tweakable_count) + { + LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << llendl; } if (params_changed) @@ -7353,14 +7090,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { // AvatarAppearance message arrived without visual params LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; - if (drop_visual_params_debug) - { - llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; - } - else - { - llinfos << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl; - } const F32 LOADING_TIMEOUT_SECONDS = 60.f; // this isn't really a problem if we already have a non-default shape @@ -7383,7 +7112,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // If all of the avatars are completely baked, release the global image caches to conserve memory. LLVOAvatar::cullAvatarsByPixelArea(); -// llinfos << "processAvatarAppearance end " << mID << llendl; + if (isSelf()) + { + mUseLocalAppearance = false; + } + + updateMeshTextures(); + + //if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end"); } // static @@ -7413,6 +7149,7 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names ) names->put( "enter_away_from_keyboard_state" ); } +// static void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { if (!userdata) return; @@ -7431,7 +7168,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture { if (!aux_src->getData()) { - llerrs << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl; + llerrs << "No auxiliary source (morph mask) data for image id " << id << llendl; return; } @@ -7456,12 +7193,12 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; */ BOOL found_texture_id = false; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsUsedByBakedTexture) { const ETextureIndex texture_index = iter->first; @@ -7483,7 +7220,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture } if (!found_texture_id) { - llinfos << "onBakedTextureMasksLoaded(): unexpected image id: " << id << llendl; + llinfos << "unexpected image id: " << id << llendl; } self->dirtyMesh(); } @@ -7491,7 +7228,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture { // this can happen when someone uses an old baked texture possibly provided by // viewer-side baked texture caching - llwarns << "Masks loaded callback but NO aux source!" << llendl; + llwarns << "Masks loaded callback but NO aux source, id " << id << llendl; } } @@ -7529,7 +7266,7 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - //llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; + LL_DEBUGS("Avatar") << "onBakedTextureLoaded: " << src_vi->getID() << LL_ENDL; LLUUID id = src_vi->getID(); LLUUID *avatar_idp = (LLUUID *)userdata; @@ -7566,17 +7303,31 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) { LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; mBakedTextureDatas[i].mIsLoaded = true; - mBakedTextureDatas[i].mLastTextureIndex = id; + mBakedTextureDatas[i].mLastTextureID = id; mBakedTextureDatas[i].mIsUsed = true; - for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + + if (isUsingLocalAppearance()) { - mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked ); + llinfos << "not changing to baked texture while isUsingLocalAppearance" << llendl; } - if (mBakedTextureDatas[i].mTexLayerSet) + else { - //mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); + debugColorizeSubMeshes(i,LLColor4::green); + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setTexture( image_baked ); + } + } } - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = + LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) @@ -7589,9 +7340,15 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) // This is paired with similar code in updateMeshTextures that sets hair mesh color. if (i == BAKED_HAIR) { - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor( LLColor4::white ); + } } } } @@ -7600,11 +7357,39 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) dirtyMesh(); } -// static -void LLVOAvatar::dumpArchetypeXML( void* ) +std::string get_sequential_numbered_file_name(const std::string& prefix, + const std::string& suffix) +{ + typedef std::map<std::string,S32> file_num_type; + static file_num_type file_nums; + file_num_type::iterator it = file_nums.find(prefix); + S32 num = 0; + if (it != file_nums.end()) + { + num = it->second; + } + file_nums[prefix] = num+1; + std::string outfilename = prefix + " " + llformat("%04d",num) + ".xml"; + std::replace(outfilename.begin(),outfilename.end(),' ','_'); + return outfilename; +} + +void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables ) { + std::string outprefix(prefix); + if (outprefix.empty()) + { + outprefix = getFullname() + (isSelf()?"_s":"_o"); + } + if (outprefix.empty()) + { + outprefix = std::string("new_archetype"); + } + std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + LLAPRFile outfile; - outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml"), LL_APR_WB ); + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + outfile.open(fullpath, LL_APR_WB ); apr_file_t* file = outfile.getFileHandle(); if (!file) { @@ -7612,36 +7397,60 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } else { - llinfos << "xmlfile write handle obtained : " << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml") << llendl; + llinfos << "xmlfile write handle obtained : " << fullpath << llendl; } apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" ); apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" ); apr_file_printf( file, "\n\t<archetype name=\"???\">\n" ); - // only body parts, not clothing. - for (S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_EYES; type++) + if (group_by_wearables) { - const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); - apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() ); - - for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam()) + for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - if( (viewer_param->getWearableType() == type) && - (viewer_param->isTweakable() ) ) + const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); + apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() ); + + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + if( (viewer_param->getWearableType() == type) && + (viewer_param->isTweakable() ) ) + { + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\"/>\n", - viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight()); + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + std::string uuid_str; + te_image->getID().toString( uuid_str ); + apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, uuid_str.c_str()); + } + } } } + } + else + { + // Just dump all params sequentially. + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0); + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); if( te_image ) { std::string uuid_str; @@ -7650,14 +7459,18 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } } } + } apr_file_printf( file, "\t</archetype>\n" ); apr_file_printf( file, "\n</linden_genepool>\n" ); - //explictly close the file if it is still open which it should be - if (file) + + bool ultra_verbose = false; + if (isSelf() && ultra_verbose) { - outfile.close(); + // show the cloned params inside the wearables as well. + gAgentAvatarp->dumpWearableInfo(outfile); } + // File will close when handle goes out of scope } @@ -7739,15 +7552,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } - // runway - this doesn't detect gray/grey state. - // think we just need to be checking self av since it's the only - // one with lltexlayer stuff. + // runway - this doesn't really detect gray/grey state. S32 grey_avatars = 0; - if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) - { - LLVOAvatar::deleteCachedImages(false); - } - else + if (!LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame { @@ -7775,501 +7582,44 @@ void LLVOAvatar::startAppearanceAnimation() } } -// virtual -void LLVOAvatar::removeMissingBakedTextures() -{ -} - -//----------------------------------------------------------------------------- -// LLVOAvatarXmlInfo -//----------------------------------------------------------------------------- - -LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() - : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) -{ -} - -LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() -{ - std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); - std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); - std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); - deleteAndClear(mTexSkinColorInfo); - deleteAndClear(mTexHairColorInfo); - deleteAndClear(mTexEyeColorInfo); - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); - std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); - std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); -} - -////----------------------------------------------------------------------------- -//// LLVOAvatarBoneInfo::parseXml() -////----------------------------------------------------------------------------- -//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -//{ -// if (node->hasName("bone")) -// { -// mIsJoint = TRUE; -// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -// if (!node->getFastAttributeString(name_string, mName)) -// { -// llwarns << "Bone without name" << llendl; -// return FALSE; -// } -// } -// else if (node->hasName("collision_volume")) -// { -// mIsJoint = FALSE; -// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -// if (!node->getFastAttributeString(name_string, mName)) -// { -// mName = "Collision Volume"; -// } -// } -// else -// { -// llwarns << "Invalid node " << node->getName() << llendl; -// return FALSE; -// } -// -// static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); -// if (!node->getFastAttributeVector3(pos_string, mPos)) -// { -// llwarns << "Bone without position" << llendl; -// return FALSE; -// } -// -// static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); -// if (!node->getFastAttributeVector3(rot_string, mRot)) -// { -// llwarns << "Bone without rotation" << llendl; -// return FALSE; -// } -// -// static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); -// if (!node->getFastAttributeVector3(scale_string, mScale)) -// { -// llwarns << "Bone without scale" << llendl; -// return FALSE; -// } -// -// if (mIsJoint) -// { -// static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); -// if (!node->getFastAttributeVector3(pivot_string, mPivot)) -// { -// llwarns << "Bone without pivot" << llendl; -// return FALSE; -// } -// } -// -// // parse children -// LLXmlTreeNode* child; -// for( child = node->getFirstChild(); child; child = node->getNextChild() ) -// { -// LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; -// if (!child_info->parseXml(child)) -// { -// delete child_info; -// return FALSE; -// } -// mChildList.push_back(child_info); -// } -// return TRUE; -//} -// -////----------------------------------------------------------------------------- -//// LLVOAvatarSkeletonInfo::parseXml() -////----------------------------------------------------------------------------- -//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -//{ -// static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); -// if (!node->getFastAttributeS32(num_bones_string, mNumBones)) -// { -// llwarns << "Couldn't find number of bones." << llendl; -// return FALSE; -// } -// -// static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); -// node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); -// -// LLXmlTreeNode* child; -// for( child = node->getFirstChild(); child; child = node->getNextChild() ) -// { -// LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; -// if (!info->parseXml(child)) -// { -// delete info; -// llwarns << "Error parsing bone in skeleton file" << llendl; -// return FALSE; -// } -// mBoneInfoList.push_back(info); -// } -// return TRUE; -//} - -//----------------------------------------------------------------------------- -// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) -{ - LLXmlTreeNode* node = root->getChildByName( "skeleton" ); - if( !node ) - { - llwarns << "avatar file: missing <skeleton>" << llendl; - return FALSE; - } - - LLXmlTreeNode* child; - - // SKELETON DISTORTIONS - for (child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_skeleton")) - { - if (child->getChildByName("param_morph")) - { - llwarns << "Can't specify morph param in skeleton definition." << llendl; - } - else - { - llwarns << "Unknown param type." << llendl; - } - continue; - } - - LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - - mSkeletalDistortionInfoList.push_back(info); - } - - // ATTACHMENT POINTS - for (child = node->getChildByName( "attachment_point" ); - child; - child = node->getNextNamedChild()) - { - LLVOAvatarAttachmentInfo* info = new LLVOAvatarAttachmentInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!child->getFastAttributeString(name_string, info->mName)) - { - llwarns << "No name supplied for attachment point." << llendl; - delete info; - continue; - } - - static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); - if (!child->getFastAttributeString(joint_string, info->mJointName)) - { - llwarns << "No bone declared in attachment point " << info->mName << llendl; - delete info; - continue; - } - - static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); - if (child->getFastAttributeVector3(position_string, info->mPosition)) - { - info->mHasPosition = TRUE; - } - - static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); - if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) - { - info->mHasRotation = TRUE; - } - static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); - if (child->getFastAttributeS32(group_string, info->mGroup)) - { - if (info->mGroup == -1) - info->mGroup = -1111; // -1 = none parsed, < -1 = bad value - } - - static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); - if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) - { - llwarns << "No id supplied for attachment point " << info->mName << llendl; - delete info; - continue; - } - - static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); - child->getFastAttributeS32(slot_string, info->mPieMenuSlice); - - static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); - child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); - - static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); - child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); - - mAttachmentInfoList.push_back(info); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// parseXmlMeshNodes(): parses <mesh> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +//virtual +void LLVOAvatar::bodySizeChanged() { - for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); - node; - node = root->getNextNamedChild()) - { - LLVOAvatarMeshInfo *info = new LLVOAvatarMeshInfo; - - // attribute: type - static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); - if( !node->getFastAttributeString( type_string, info->mType ) ) - { - llwarns << "Avatar file: <mesh> is missing type attribute. Ignoring element. " << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); - if (!node->getFastAttributeS32( lod_string, info->mLOD )) - { - llwarns << "Avatar file: <mesh> is missing lod attribute. Ignoring element. " << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) - { - llwarns << "Avatar file: <mesh> is missing file_name attribute. Ignoring: " << info->mType << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); - node->getFastAttributeString( reference_string, info->mReferenceMeshName ); - - // attribute: min_pixel_area - static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); - static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); - if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) - { - F32 min_pixel_area = 0.1f; - if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) - { - // this is square root of pixel area (sensible to use linear space in defining lods) - min_pixel_area = min_pixel_area * min_pixel_area; - } - info->mMinPixelArea = min_pixel_area; - } - - // Parse visual params for this node only if we haven't already - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_morph")) - { - if (child->getChildByName("param_skeleton")) - { - llwarns << "Can't specify skeleton param in a mesh definition." << llendl; - } - else - { - llwarns << "Unknown param type." << llendl; - } - continue; - } - - LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); - if (!morphinfo->parseXml(child)) - { - delete morphinfo; - delete info; - return -1; - } - BOOL shared = FALSE; - static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); - child->getFastAttributeBOOL(shared_string, shared); - - info->mPolyMorphTargetInfoList.push_back(LLVOAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); - } - - mMeshInfoList.push_back(info); + if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF()) + { // notify simulator of change in size + // but not if we are in the middle of updating appearance + gAgent.sendAgentSetAppearance(); } - return TRUE; } -//----------------------------------------------------------------------------- -// parseXmlColorNodes(): parses <global_color> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +BOOL LLVOAvatar::isUsingServerBakes() const { - for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); - color_node; - color_node = root->getNextNamedChild()) +#if 1 + // Sanity check - visual param for appearance version should match mUseServerBakes + LLVisualParam* appearance_version_param = getVisualParam(11000); + llassert(appearance_version_param); + F32 wt = appearance_version_param->getWeight(); + F32 expect_wt = mUseServerBakes ? 1.0 : 0.0; + if (!is_approx_equal(wt,expect_wt)) { - std::string global_color_name; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (color_node->getFastAttributeString( name_string, global_color_name ) ) - { - if( global_color_name == "skin_color" ) - { - if (mTexSkinColorInfo) - { - llwarns << "avatar file: multiple instances of skin_color" << llendl; - return FALSE; - } - mTexSkinColorInfo = new LLTexGlobalColorInfo; - if( !mTexSkinColorInfo->parseXml( color_node ) ) - { - deleteAndClear(mTexSkinColorInfo); - llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl; - return FALSE; - } - } - else if( global_color_name == "hair_color" ) - { - if (mTexHairColorInfo) - { - llwarns << "avatar file: multiple instances of hair_color" << llendl; - return FALSE; - } - mTexHairColorInfo = new LLTexGlobalColorInfo; - if( !mTexHairColorInfo->parseXml( color_node ) ) - { - deleteAndClear(mTexHairColorInfo); - llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl; - return FALSE; - } - } - else if( global_color_name == "eye_color" ) - { - if (mTexEyeColorInfo) - { - llwarns << "avatar file: multiple instances of eye_color" << llendl; - return FALSE; - } - mTexEyeColorInfo = new LLTexGlobalColorInfo; - if( !mTexEyeColorInfo->parseXml( color_node ) ) - { - llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl; - return FALSE; - } - } - } + llwarns << "wt " << wt << " differs from expected " << expect_wt << llendl; } - return TRUE; -} +#endif -//----------------------------------------------------------------------------- -// parseXmlLayerNodes(): parses <layer_set> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); - layer_node; - layer_node = root->getNextNamedChild()) - { - LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); - if( layer_info->parseXml( layer_node ) ) - { - mLayerInfoList.push_back(layer_info); - } - else - { - delete layer_info; - llwarns << "avatar file: layer_set->parseXml() failed" << llendl; - return FALSE; - } - } - return TRUE; + return mUseServerBakes; } -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +void LLVOAvatar::setIsUsingServerBakes(BOOL newval) { - LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); - if( driver ) - { - for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); - grand_child; - grand_child = driver->getNextNamedChild()) - { - if( grand_child->getChildByName( "param_driver" ) ) - { - LLDriverParamInfo* driver_info = new LLDriverParamInfo(); - if( driver_info->parseXml( grand_child ) ) - { - mDriverInfoList.push_back(driver_info); - } - else - { - delete driver_info; - llwarns << "avatar file: driver_param->parseXml() failed" << llendl; - return FALSE; - } - } - } - } - return TRUE; + mUseServerBakes = newval; + LLVisualParam* appearance_version_param = getVisualParam(11000); + llassert(appearance_version_param); + appearance_version_param->setWeight(newval ? 1.0 : 0.0, false); } -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) -{ - LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); - if( !masks ) - { - return FALSE; - } - - for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); - grand_child; - grand_child = masks->getNextNamedChild()) - { - LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); - if (!grand_child->getFastAttributeString(name_string, info->mName)) - { - llwarns << "No name supplied for morph mask." << llendl; - delete info; - continue; - } - - static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); - if (!grand_child->getFastAttributeString(region_string, info->mRegion)) - { - llwarns << "No region supplied for morph mask." << llendl; - delete info; - continue; - } - - static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); - if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) - { - llwarns << "No layer supplied for morph mask." << llendl; - delete info; - continue; - } - - // optional parameter. don't throw a warning if not present. - static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); - grand_child->getFastAttributeBOOL(invert_string, info->mInvert); - - mMorphMaskInfoList.push_back(info); - } - - return TRUE; +// virtual +void LLVOAvatar::removeMissingBakedTextures() +{ } //virtual @@ -8445,7 +7795,7 @@ void LLVOAvatar::idleUpdateRenderCost() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); ETextureIndex tex_index = baked_dict->mTextureIndex; if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) { @@ -8525,11 +7875,11 @@ void LLVOAvatar::idleUpdateRenderCost() } // print any avatar textures we didn't already know about - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; // TODO: MULTI-WEARABLE: handle multiple textures for self const LLViewerTexture* te_image = getImage(iter->first,0); if (!te_image) @@ -8558,26 +7908,26 @@ void LLVOAvatar::idleUpdateRenderCost() BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; } // static BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const { std::string line; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsBakedTexture) { line += texture_dict->mName; @@ -8609,7 +7959,7 @@ F32 calc_bouncy_animation(F32 x) } //virtual -BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index ) const +BOOL LLVOAvatar::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index ) const { if (isIndexLocalTexture(te)) { @@ -8627,7 +7977,7 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index } //virtual -BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (isIndexLocalTexture(type)) { @@ -8643,9 +7993,11 @@ BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 ind } //virtual -BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { // non-self avatars don't have wearables return FALSE; } + + diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 9f1f209920..85f6f25009 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -25,8 +25,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLVOAVATAR_H -#define LL_LLVOAVATAR_H +#ifndef LL_VOAVATAR_H +#define LL_VOAVATAR_H #include <map> #include <deque> @@ -36,6 +36,7 @@ #include <boost/signals2.hpp> #include "imageids.h" // IMG_INVISIBLE +#include "llavatarappearance.h" #include "llchat.h" #include "lldrawpoolalpha.h" #include "llviewerobject.h" @@ -44,9 +45,10 @@ #include "llviewerjointmesh.h" #include "llviewerjointattachment.h" #include "llrendertarget.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "lltexglobalcolor.h" #include "lldriverparam.h" +#include "llviewertexlayer.h" #include "material_codes.h" // LL_MCODE_END #include "llviewerstats.h" @@ -62,13 +64,15 @@ extern const LLUUID ANIM_AGENT_PELVIS_FIX; extern const LLUUID ANIM_AGENT_TARGET; extern const LLUUID ANIM_AGENT_WALK_ADJUST; -class LLTexLayerSet; +class LLViewerWearable; class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; struct LLVOAvatarBoneInfo; struct LLVOAvatarChildJoint; +//class LLViewerJoint; +struct LLAppearanceMessageContents; struct LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -76,17 +80,14 @@ struct LLVOAvatarSkeletonInfo; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLVOAvatar : + public LLAvatarAppearance, public LLViewerObject, - public LLCharacter, public boost::signals2::trackable { LOG_CLASS(LLVOAvatar); public: friend class LLVOAvatarSelf; -protected: - struct LLVOAvatarXmlInfo; - struct LLMaskedMorph; /******************************************************************************** ** ** @@ -111,9 +112,6 @@ public: virtual void initInstance(); // Called after construction to initialize the class. protected: virtual ~LLVOAvatar(); - BOOL loadSkeletonNode(); - BOOL loadMeshNodes(); - virtual BOOL loadLayersets(); /** Initialization ** ** @@ -128,31 +126,43 @@ protected: // LLViewerObject interface and related //-------------------------------------------------------------------- public: - virtual void updateGL(); - virtual LLVOAvatar* asAvatar(); - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + /*virtual*/ void updateGL(); + /*virtual*/ LLVOAvatar* asAvatar(); + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp); - virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - virtual BOOL updateLOD(); - BOOL updateJointLODs(); - void updateLODRiggedAttachments( void ); - virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate. - virtual void updateTextures(); - virtual S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. - virtual void onShift(const LLVector4a& shift_vector); - virtual U32 getPartitionType() const; - virtual const LLVector3 getRenderPosition() const; - virtual void updateDrawable(BOOL force_damped); - virtual LLDrawable* createDrawable(LLPipeline *pipeline); - virtual BOOL updateGeometry(LLDrawable *drawable); - virtual void setPixelAreaAndAngle(LLAgent &agent); - virtual void updateRegion(LLViewerRegion *regionp); - virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax); - virtual void getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); - virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ BOOL updateLOD(); + BOOL updateJointLODs(); + void updateLODRiggedAttachments( void ); + /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + S32 totalTextureMemForUUIDS(std::set<LLUUID>& ids); + bool allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const; + bool allLocalTexturesCompletelyDownloaded() const; + bool allBakedTexturesCompletelyDownloaded() const; + void bakedTextureOriginCounts(S32 &sb_count, S32 &host_count, + S32 &both_count, S32 &neither_count); + std::string bakedTextureOriginInfo(); + void collectLocalTextureUUIDs(std::set<LLUUID>& ids) const; + void collectBakedTextureUUIDs(std::set<LLUUID>& ids) const; + void collectTextureUUIDs(std::set<LLUUID>& ids); + void releaseOldTextures(); + /*virtual*/ void updateTextures(); + LLViewerFetchedTexture* getBakedTextureImage(const U8 te, const LLUUID& uuid); + /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. + /*virtual*/ void onShift(const LLVector4a& shift_vector); + /*virtual*/ U32 getPartitionType() const; + /*virtual*/ const LLVector3 getRenderPosition() const; + /*virtual*/ void updateDrawable(BOOL force_damped); + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); + /*virtual*/ void updateRegion(LLViewerRegion *regionp); + /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax); + /*virtual*/ void getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); + /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, S32* face_hit = NULL, // which face was hit @@ -173,16 +183,14 @@ public: // LLCharacter interface and related //-------------------------------------------------------------------- public: - virtual LLVector3 getCharacterPosition(); - virtual LLQuaternion getCharacterRotation(); - virtual LLVector3 getCharacterVelocity(); - virtual LLVector3 getCharacterAngularVelocity(); - virtual LLJoint* getCharacterJoint(U32 num); - virtual BOOL allocateCharacterJoints(U32 num); - - virtual LLUUID remapMotionID(const LLUUID& id); - virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); - virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); + /*virtual*/ LLVector3 getCharacterPosition(); + /*virtual*/ LLQuaternion getCharacterRotation(); + /*virtual*/ LLVector3 getCharacterVelocity(); + /*virtual*/ LLVector3 getCharacterAngularVelocity(); + + /*virtual*/ LLUUID remapMotionID(const LLUUID& id); + /*virtual*/ BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); + /*virtual*/ BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); virtual void stopMotionFromSource(const LLUUID& source_id); virtual void requestStopMotion(LLMotion* motion); LLMotion* findMotion(const LLUUID& id) const; @@ -190,25 +198,18 @@ public: void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); - virtual LLJoint* getRootJoint() { return &mRoot; } void resetJointPositions( void ); void resetJointPositionsToDefault( void ); void resetSpecificJointPosition( const std::string& name ); - virtual const char* getAnimationPrefix() { return "avatar"; } - virtual const LLUUID& getID() const; - virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); - virtual LLJoint* findCollisionVolume(U32 volume_id); - virtual S32 getCollisionVolumeID(std::string &name); - virtual void addDebugText(const std::string& text); - virtual F32 getTimeDilation(); - virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); - virtual F32 getPixelArea() const; - virtual LLPolyMesh* getHeadMesh(); - virtual LLPolyMesh* getUpperBodyMesh(); - virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); - virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); + /*virtual*/ const LLUUID& getID() const; + /*virtual*/ void addDebugText(const std::string& text); + /*virtual*/ F32 getTimeDilation(); + /*virtual*/ void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); + /*virtual*/ F32 getPixelArea() const; + /*virtual*/ LLVector3d getPosGlobalFromAgent(const LLVector3 &position); + /*virtual*/ LLVector3 getPosAgentFromGlobal(const LLVector3d &position); virtual void updateVisualParams(); @@ -223,14 +224,10 @@ public: public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent - bool isBuilt() const { return mIsBuilt; } private: //aligned members LL_ALIGN_16(LLVector4a mImpostorExtents[2]); -private: - BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients - //-------------------------------------------------------------------- // Updates //-------------------------------------------------------------------- @@ -293,17 +290,21 @@ public: virtual BOOL getIsCloud() const; BOOL isFullyTextured() const; BOOL hasGray() const; - S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured. + S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = textured, 3 = textured and fully downloaded. void updateRezzedStatusTimers(); S32 mLastRezzedStatus; - LLViewerStats::PhaseMap& getPhases() - { - return mPhases; - } + + void startPhase(const std::string& phase_name); + void stopPhase(const std::string& phase_name, bool err_check = true); + void clearPhases(); + void logPendingPhases(); + static void logPendingPhasesAllAvatars(); + void logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed); protected: + LLViewerStats::PhaseMap& getPhases() { return mPhases; } BOOL updateIsFullyLoaded(); BOOL processFullyLoadedChange(bool loading); void updateRuthTimer(bool loading); @@ -318,24 +319,6 @@ private: LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; -public: - class ScopedPhaseSetter - { - public: - ScopedPhaseSetter(LLVOAvatar *avatarp, std::string phase_name): - mAvatar(avatarp), mPhaseName(phase_name) - { - if (mAvatar) { mAvatar->getPhases().startPhase(mPhaseName); } - } - ~ScopedPhaseSetter() - { - if (mAvatar) { mAvatar->getPhases().stopPhase(mPhaseName); } - } - private: - std::string mPhaseName; - LLVOAvatar* mAvatar; - }; - private: LLViewerStats::PhaseMap mPhases; @@ -345,20 +328,25 @@ protected: /** State ** ** *******************************************************************************/ - /******************************************************************************** ** ** ** SKELETON **/ +protected: + /*virtual*/ LLAvatarJoint* createAvatarJoint(); // Returns LLViewerJoint + /*virtual*/ LLAvatarJoint* createAvatarJoint(S32 joint_num); // Returns LLViewerJoint + /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); - F32 getPelvisToFoot() const { return mPelvisToFoot; } void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; bool hasPelvisOffset( void ) { return mHasPelvisOffset; } void postPelvisSetRecalc( void ); void setPelvisOffset( F32 pelvixFixupAmount ); + /*virtual*/ BOOL loadSkeletonNode(); + /*virtual*/ void buildCharacter(); + bool mHasPelvisOffset; LLVector3 mPelvisOffset; F32 mLastPelvisToFoot; @@ -367,62 +355,8 @@ public: LLVector3 mCurRootToHeadOffset; LLVector3 mTargetRootToHeadOffset; - LLVector3 mHeadOffset; // current head position - LLViewerJoint mRoot; - - typedef std::map<std::string, LLJoint*> joint_map_t; - joint_map_t mJointMap; - -protected: - static BOOL parseSkeletonFile(const std::string& filename); - void buildCharacter(); - virtual BOOL loadAvatar(); - - BOOL setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); - BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); -private: - BOOL mIsBuilt; // state of deferred character building - S32 mNumJoints; - LLViewerJoint* mSkeleton; - - //-------------------------------------------------------------------- - // Pelvis height adjustment members. - //-------------------------------------------------------------------- -public: - LLVector3 mBodySize; S32 mLastSkeletonSerialNum; -private: - F32 mPelvisToFoot; - //-------------------------------------------------------------------- - // Cached pointers to well known joints - //-------------------------------------------------------------------- -public: - LLViewerJoint* mPelvisp; - LLViewerJoint* mTorsop; - LLViewerJoint* mChestp; - LLViewerJoint* mNeckp; - LLViewerJoint* mHeadp; - LLViewerJoint* mSkullp; - LLViewerJoint* mEyeLeftp; - LLViewerJoint* mEyeRightp; - LLViewerJoint* mHipLeftp; - LLViewerJoint* mHipRightp; - LLViewerJoint* mKneeLeftp; - LLViewerJoint* mKneeRightp; - LLViewerJoint* mAnkleLeftp; - LLViewerJoint* mAnkleRightp; - LLViewerJoint* mFootLeftp; - LLViewerJoint* mFootRightp; - LLViewerJoint* mWristLeftp; - LLViewerJoint* mWristRightp; - - //-------------------------------------------------------------------- - // XML parse tree - //-------------------------------------------------------------------- -private: - static LLXmlTree sXMLTree; // avatar config file - static LLXMLNodePtr sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** @@ -445,7 +379,6 @@ public: static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); - BOOL mIsDummy; // for special views S32 mSpecialRenderMode; // special lighting U32 mAttachmentGeometryBytes; //number of bytes in attached geometry F32 mAttachmentSurfaceArea; //estimated surface area of attachments @@ -463,9 +396,15 @@ private: // Morph masks //-------------------------------------------------------------------- public: - BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); - void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + /*virtual*/ void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + /*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); //-------------------------------------------------------------------- // Visibility @@ -548,10 +487,10 @@ private: // Constants //-------------------------------------------------------------------- public: - virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; } - virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; } + virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLGLTexture::BOOST_AVATAR; } + virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED; } virtual S32 getTexImageSize() const; - virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } + /*virtual*/ S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } /** Rendering ** ** @@ -566,9 +505,9 @@ public: // Loading status //-------------------------------------------------------------------- public: - virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; + virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const; BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); @@ -579,6 +518,7 @@ public: // Baked textures //-------------------------------------------------------------------- public: + /*virtual*/ LLTexLayerSet* createTexLayerSet(); // Return LLViewerTexLayerSet void releaseComponentTextures(); // ! BACKWARDS COMPATIBILITY ! protected: static void onBakedTextureMasksLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); @@ -586,32 +526,20 @@ protected: static void onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); virtual void removeMissingBakedTextures(); void useBakedTexture(const LLUUID& id); + LLViewerTexLayerSet* getTexLayerSet(const U32 index) const { return dynamic_cast<LLViewerTexLayerSet*>(mBakedTextureDatas[index].mTexLayerSet); } + - typedef std::deque<LLMaskedMorph *> morph_list_t; - struct BakedTextureData - { - LLUUID mLastTextureIndex; - LLTexLayerSet* mTexLayerSet; // Only exists for self - bool mIsLoaded; - bool mIsUsed; - LLVOAvatarDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; - // Stores pointers to the joint meshes that this baked texture deals with - std::vector< LLViewerJointMesh * > mMeshes; // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts - morph_list_t mMaskedMorphs; - }; - typedef std::vector<BakedTextureData> bakedtexturedata_vec_t; - bakedtexturedata_vec_t mBakedTextureDatas; LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; BOOL mLoadedCallbacksPaused; + std::set<LLUUID> mTextureIDs; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- protected: - virtual void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); - virtual void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); + virtual void setLocalTexture(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); + virtual void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); // MULTI-WEARABLE: make self-only? - virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); + virtual void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); //-------------------------------------------------------------------- // Texture accessors @@ -619,6 +547,7 @@ protected: private: virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); virtual LLViewerTexture* getImage(const U8 te, const U32 index) const; + const std::string getImageURL(const U8 te, const LLUUID &uuid); virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; virtual void setTexEntry(const U8 index, const LLTextureEntry &te); @@ -645,13 +574,11 @@ public: // Static texture/mesh/baked dictionary //-------------------------------------------------------------------- public: - static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); - static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); + static BOOL isIndexLocalTexture(LLAvatarAppearanceDefines::ETextureIndex i); + static BOOL isIndexBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i); private: - static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } - static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary; - static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; - static LLVOAvatarXmlInfo* sAvatarXmlInfo; + static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } + static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; //-------------------------------------------------------------------- // Messaging @@ -672,22 +599,20 @@ private: **/ public: - void updateMeshTextures(); + void debugColorizeSubMeshes(U32 i, const LLColor4& color); + virtual void updateMeshTextures(); void updateSexDependentLayerSets(BOOL upload_bake); - void dirtyMesh(); // Dirty the avatar mesh + virtual void dirtyMesh(); // Dirty the avatar mesh void updateMeshData(); protected: void releaseMeshData(); virtual void restoreMeshData(); private: - void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + virtual void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + LLViewerJoint* getViewerJoint(S32 idx); S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD BOOL mMeshTexturesDirty; - typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t; - polymesh_map_t mMeshes; - std::vector<LLViewerJoint *> mMeshLOD; - //-------------------------------------------------------------------- // Destroy invisible mesh //-------------------------------------------------------------------- @@ -705,38 +630,42 @@ protected: **/ public: + void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg); void processAvatarAppearance(LLMessageSystem* mesgsys); void hideSkirt(); void startAppearanceAnimation(); + /*virtual*/ void bodySizeChanged(); //-------------------------------------------------------------------- // Appearance morphing //-------------------------------------------------------------------- public: BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } + + // True if we are computing our appearance via local compositing + // instead of baked textures, as for example during wearable + // editing or when waiting for a subsequent server rebake. + /*virtual*/ BOOL isUsingLocalAppearance() const { return mUseLocalAppearance; } + + // True if this avatar should fetch its baked textures via the new + // appearance mechanism. + BOOL isUsingServerBakes() const; + void setIsUsingServerBakes(BOOL newval); + + + // True if we are currently in appearance editing mode. Often but + // not always the same as isUsingLocalAppearance(). + /*virtual*/ BOOL isEditingAppearance() const { return mIsEditingAppearance; } + + // FIXME review isUsingLocalAppearance uses, some should be isEditing instead. + private: BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; F32 mLastAppearanceBlendTime; - - //-------------------------------------------------------------------- - // Clothing colors (convenience functions to access visual parameters) - //-------------------------------------------------------------------- -public: - void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); - LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); - static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); - - //-------------------------------------------------------------------- - // Global colors - //-------------------------------------------------------------------- -public: - LLColor4 getGlobalColor(const std::string& color_name ) const; - void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); -private: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; + BOOL mIsEditingAppearance; // flag for if we're actively in appearance editing mode + BOOL mUseLocalAppearance; // flag for if we're using a local composite + BOOL mUseServerBakes; // flag for if baked textures should be fetched from baking service (false if they're temporary uploads) //-------------------------------------------------------------------- // Visibility @@ -746,7 +675,6 @@ public: void setVisibilityRank(U32 rank); U32 getVisibilityRank() const { return mVisibilityRank; } // unused static S32 sNumVisibleAvatars; // Number of instances of this class - static LLColor4 getDummyColor(); /** Appearance ** ** *******************************************************************************/ @@ -756,9 +684,6 @@ public: ** WEARABLES **/ -public: - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; - //-------------------------------------------------------------------- // Attachments //-------------------------------------------------------------------- @@ -768,6 +693,7 @@ public: virtual BOOL detachObject(LLViewerObject *viewer_object); void cleanupAttachedMesh( LLViewerObject* pVO ); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); + /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const; protected: LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); void lazyAttach(); @@ -869,15 +795,6 @@ private: F32 mSpeed; // misc. animation repeated state //-------------------------------------------------------------------- - // Collision volumes - //-------------------------------------------------------------------- -public: - S32 mNumCollisionVolumes; - LLViewerJointCollisionVolume* mCollisionVolumes; -protected: - BOOL allocateCollisionVolumes(U32 num); - - //-------------------------------------------------------------------- // Dimensions //-------------------------------------------------------------------- public: @@ -887,7 +804,6 @@ public: void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm); void slamPosition(); // Slam position to transmitted position (for teleport); protected: - void computeBodySize(); //-------------------------------------------------------------------- // Material being stepped on @@ -907,9 +823,9 @@ private: **/ public: - virtual BOOL setParent(LLViewerObject* parent); - virtual void addChild(LLViewerObject *childp); - virtual void removeChild(LLViewerObject *childp); + /*virtual*/ BOOL setParent(LLViewerObject* parent); + /*virtual*/ void addChild(LLViewerObject *childp); + /*virtual*/ void removeChild(LLViewerObject *childp); //-------------------------------------------------------------------- // Sitting @@ -1013,7 +929,9 @@ private: // General //-------------------------------------------------------------------- public: - static void dumpArchetypeXML(void*); + void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false); + void dumpAppearanceMsgParams( const std::string& dump_prefix, + const LLAppearanceMessageContents& contents); static void dumpBakedStatus(); const std::string getBakedStatusForPrintout() const; void dumpAvatarTEs(const std::string& context) const; @@ -1030,6 +948,7 @@ private: F32 mMaxPixelArea; F32 mAdjustedPixelArea; std::string mDebugText; + std::string mBakedTextureDebugText; //-------------------------------------------------------------------- @@ -1043,6 +962,17 @@ protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. + //-------------------------------------------------------------------- + // COF monitoring + //-------------------------------------------------------------------- + +public: + // COF version of last viewer-initiated appearance update request. For non-self avs, this will remain at default. + S32 mLastUpdateRequestCOFVersion; + + // COF version of last appearance message received for this av. + S32 mLastUpdateReceivedCOFVersion; + /** Diagnostics ** ** *******************************************************************************/ @@ -1054,105 +984,6 @@ protected: protected: // Shared with LLVOAvatarSelf - struct LLVOAvatarXmlInfo - { - LLVOAvatarXmlInfo(); - ~LLVOAvatarXmlInfo(); - - BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); - BOOL parseXmlMeshNodes(LLXmlTreeNode* root); - BOOL parseXmlColorNodes(LLXmlTreeNode* root); - BOOL parseXmlLayerNodes(LLXmlTreeNode* root); - BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - BOOL parseXmlMorphNodes(LLXmlTreeNode* root); - - struct LLVOAvatarMeshInfo - { - typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t; - typedef std::vector<morph_info_pair_t> morph_info_list_t; - - LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} - ~LLVOAvatarMeshInfo() - { - morph_info_list_t::iterator iter; - for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) - { - delete iter->first; - } - mPolyMorphTargetInfoList.clear(); - } - - std::string mType; - S32 mLOD; - std::string mMeshFileName; - std::string mReferenceMeshName; - F32 mMinPixelArea; - morph_info_list_t mPolyMorphTargetInfoList; - }; - typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t; - mesh_info_list_t mMeshInfoList; - - typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t; - skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - - struct LLVOAvatarAttachmentInfo - { - LLVOAvatarAttachmentInfo() - : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), - mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} - std::string mName; - std::string mJointName; - LLVector3 mPosition; - LLVector3 mRotationEuler; - S32 mGroup; - S32 mAttachmentID; - S32 mPieMenuSlice; - BOOL mVisibleFirstPerson; - BOOL mIsHUDAttachment; - BOOL mHasPosition; - BOOL mHasRotation; - }; - typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t; - attachment_info_list_t mAttachmentInfoList; - - LLTexGlobalColorInfo *mTexSkinColorInfo; - LLTexGlobalColorInfo *mTexHairColorInfo; - LLTexGlobalColorInfo *mTexEyeColorInfo; - - typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t; - layer_info_list_t mLayerInfoList; - - typedef std::vector<LLDriverParamInfo*> driver_info_list_t; - driver_info_list_t mDriverInfoList; - - struct LLVOAvatarMorphInfo - { - LLVOAvatarMorphInfo() - : mInvert(FALSE) {} - std::string mName; - std::string mRegion; - std::string mLayer; - BOOL mInvert; - }; - - typedef std::vector<LLVOAvatarMorphInfo*> morph_info_list_t; - morph_info_list_t mMorphMaskInfoList; - }; - - struct LLMaskedMorph - { - LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert, std::string layer) : - mMorphTarget(morph_target), - mInvert(invert), - mLayer(layer) - { - morph_target->addPendingMorphMask(); - } - - LLPolyMorphTarget *mMorphTarget; - BOOL mInvert; - std::string mLayer; - }; /** Support classes ** ** @@ -1162,4 +993,9 @@ protected: // Shared with LLVOAvatarSelf extern const F32 SELF_ADDITIONAL_PRI; extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; -#endif // LL_VO_AVATAR_H +std::string get_sequential_numbered_file_name(const std::string& prefix, + const std::string& suffix); +void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value); + +#endif // LL_VOAVATAR_H + diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index e32fd3c3c8..d54eb5f040 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -55,11 +55,14 @@ #include "llviewerobjectlist.h" #include "llviewerstats.h" #include "llviewerregion.h" +#include "llviewertexlayer.h" +#include "llviewerwearable.h" #include "llappearancemgr.h" #include "llmeshrepository.h" #include "llvovolume.h" #include "llsdutil.h" #include "llstartup.h" +#include "llsdserialize.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -72,24 +75,22 @@ LLPointer<LLVOAvatarSelf> gAgentAvatarp = NULL; BOOL isAgentAvatarValid() { - return (gAgentAvatarp.notNull() && - (gAgentAvatarp->getRegion() != NULL) && - (!gAgentAvatarp->isDead())); + return (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()); } void selfStartPhase(const std::string& phase_name) { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().startPhase(phase_name); + gAgentAvatarp->startPhase(phase_name); } } -void selfStopPhase(const std::string& phase_name) +void selfStopPhase(const std::string& phase_name, bool err_check) { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().stopPhase(phase_name); + gAgentAvatarp->stopPhase(phase_name, err_check); } } @@ -97,20 +98,11 @@ void selfClearPhases() { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().clearPhases(); - gAgentAvatarp->mLastRezzedStatus = -1; + gAgentAvatarp->clearPhases(); } } -void selfStopAllPhases() -{ - if (isAgentAvatarValid()) - { - gAgentAvatarp->getPhases().stopAllPhases(); - } -} - -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; /********************************************************************************* ** ** @@ -176,6 +168,35 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, lldebugs << "Marking avatar as self " << id << llendl; } +// Called periodically for diagnostics, return true when done. +bool output_self_av_texture_diagnostics() +{ + if (!isAgentAvatarValid()) + return true; // done checking + + gAgentAvatarp->outputRezDiagnostics(); + + return false; +} + +bool update_avatar_rez_metrics() +{ + if (!isAgentAvatarValid()) + return true; + + gAgentAvatarp->updateAvatarRezMetrics(false); + return false; +} + +bool check_for_unsupported_baked_appearance() +{ + if (!isAgentAvatarValid()) + return true; + + gAgentAvatarp->checkForUnsupportedServerBakeAppearance(); + return false; +} + void LLVOAvatarSelf::initInstance() { BOOL status = TRUE; @@ -188,7 +209,7 @@ void LLVOAvatarSelf::initInstance() llinfos << "Self avatar object created. Starting timer." << llendl; mDebugSelfLoadTimer.reset(); // clear all times to -1 for debugging - for (U32 i =0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + for (U32 i =0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) { for (U32 j = 0; j <= MAX_DISCARD_LEVEL; ++j) { @@ -196,7 +217,7 @@ void LLVOAvatarSelf::initInstance() } } - for (U32 i =0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + for (U32 i =0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) { mDebugBakedTextureTimes[i][0] = -1.0f; mDebugBakedTextureTimes[i][1] = -1.0f; @@ -209,6 +230,10 @@ void LLVOAvatarSelf::initInstance() llerrs << "Unable to load user's avatar" << llendl; return; } + + //doPeriodically(output_self_av_texture_diagnostics, 30.0); + doPeriodically(update_avatar_rez_metrics, 5.0); + doPeriodically(check_for_unsupported_baked_appearance, 120.0); } // virtual @@ -249,13 +274,11 @@ BOOL LLVOAvatarSelf::loadAvatarSelf() llwarns << "avatar file: buildSkeleton() failed" << llendl; return FALSE; } - // TODO: make loadLayersets() called only by self. - //success &= loadLayersets(); return success; } -BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info) +BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLAvatarSkeletonInfo *info) { // add special-purpose "screen" joint mScreenp = new LLViewerJoint("mScreen", NULL); @@ -341,7 +364,6 @@ BOOL LLVOAvatarSelf::buildMenus() } else { - BOOL attachment_found = FALSE; for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -369,7 +391,6 @@ BOOL LLVOAvatarSelf::buildMenus() gAttachPieMenu->addChild(item); - attachment_found = TRUE; break; } @@ -382,7 +403,6 @@ BOOL LLVOAvatarSelf::buildMenus() } else { - BOOL attachment_found = FALSE; for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -409,7 +429,6 @@ BOOL LLVOAvatarSelf::buildMenus() gDetachPieMenu->addChild(item); - attachment_found = TRUE; break; } } @@ -583,70 +602,6 @@ LLVOAvatarSelf::~LLVOAvatarSelf() ** ** *********************************************************************************/ -//virtual -BOOL LLVOAvatarSelf::loadLayersets() -{ - BOOL success = TRUE; - for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); - iter != sAvatarXmlInfo->mLayerInfoList.end(); - ++iter) - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - const LLTexLayerSetInfo *info = *iter; - LLTexLayerSet* layer_set = new LLTexLayerSet( this ); - - if (!layer_set->setInfo(info)) - { - stop_glerror(); - delete layer_set; - llwarns << "avatar file: layer_set->parseData() failed" << llendl; - return FALSE; - } - - // scan baked textures and associate the layerset with the appropriate one - EBakedTextureIndex baked_index = BAKED_NUM_INDICES; - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - ++baked_iter) - { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; - if (layer_set->isBodyRegion(baked_dict->mName)) - { - baked_index = baked_iter->first; - // ensure both structures are aware of each other - mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; - layer_set->setBakedTexIndex(baked_index); - break; - } - } - // if no baked texture was found, warn and cleanup - if (baked_index == BAKED_NUM_INDICES) - { - llwarns << "<layer_set> has invalid body_region attribute" << llendl; - delete layer_set; - return FALSE; - } - - // scan morph masks and let any affected layers know they have an associated morph - for (LLVOAvatar::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); - morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); - ++morph_iter) - { - LLMaskedMorph *morph = *morph_iter; - LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); - if (layer) - { - layer->setHasMorph(TRUE); - } - else - { - llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl; - success = FALSE; - } - } - } - return success; -} // virtual BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) { @@ -664,9 +619,15 @@ BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) } // virtual +BOOL LLVOAvatarSelf::isValid() const +{ + return ((getRegion() != NULL) && !isDead()); +} + +// virtual void LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - if (isAgentAvatarValid()) + if (isValid()) { LLVOAvatar::idleUpdate(agent, world, time); idleUpdateTractorBeam(); @@ -689,7 +650,7 @@ void LLVOAvatarSelf::resetJointPositions( void ) return LLVOAvatar::resetJointPositions(); } // virtual -BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake ) +BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake ) { if (!which_param) { @@ -717,20 +678,28 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bak return setParamWeight(param,weight,upload_bake); } -BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) +BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) { if (!param) { return FALSE; } +#if 0 + // FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables. + if (isUsingServerBakes() && !isUsingLocalAppearance()) + { + return FALSE; + } +#endif + if (param->getCrossWearable()) { LLWearableType::EType type = (LLWearableType::EType)param->getWearableType(); U32 size = gAgentWearables.getWearableCount(type); for (U32 count = 0; count < size; ++count) { - LLWearable *wearable = gAgentWearables.getWearable(type,count); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count); if (wearable) { wearable->setVisualParamWeight(param->getID(), weight, upload_bake); @@ -759,7 +728,7 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation() LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); if (wearable) { - wearable->writeToAvatar(); + wearable->writeToAvatar(this); } } @@ -802,18 +771,30 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, { U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp); - if (mInitialBakesLoaded == false && retval == 0x0) +#if 0 + // DRANO - it's not clear this does anything useful. If we wait + // until an appearance message has been received, we already have + // the texture ids. If we don't wait, we don't yet know where to + // look for baked textures, because we haven't received the + // appearance version data from the appearance message. This looks + // like an old optimization that's incompatible with server-side + // texture baking. + + // FIXME DRANO - skipping in the case of !mFirstAppearanceMessageReceived prevents us from trying to + // load textures before we know where they come from (ie, from baking service or not); + // unknown impact on performance. + if (mInitialBakesLoaded == false && retval == 0x0 && mFirstAppearanceMessageReceived) { // call update textures to force the images to be created updateMeshTextures(); // unpack the texture UUIDs to the texture slots - retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); // need to trigger a few operations to get the avatar to use the new bakes for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; + const LLAvatarAppearanceDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; LLUUID texture_id = getTEImage(te)->getID(); setNewBakedTexture(te, texture_id); mInitialBakeIDs[i] = texture_id; @@ -823,6 +804,7 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, mInitialBakesLoaded = true; } +#endif return retval; } @@ -877,11 +859,15 @@ void LLVOAvatarSelf::removeMissingBakedTextures() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); - invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE); + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + layerset->setUpdatesEnabled(TRUE); + invalidateComposite(layerset, FALSE); } updateMeshTextures(); - requestLayerSetUploads(); + if (getRegion() && !getRegion()->getCentralBakeVersion()) + { + requestLayerSetUploads(); + } } } @@ -938,7 +924,7 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) void LLVOAvatarSelf::idleUpdateTractorBeam() { // This is only done for yourself (maybe it should be in the agent?) - if (!needsRenderBeam() || !mIsBuilt) + if (!needsRenderBeam() || !isBuilt()) { mBeam = NULL; } @@ -1051,11 +1037,6 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) } } -/*virtual*/ BOOL LLVOAvatarSelf::isWearingWearableType(LLWearableType::EType type ) const -{ - return gAgentWearables.getWearableCount(type) > 0; -} - //----------------------------------------------------------------------------- // updatedWearable( LLWearableType::EType type ) // forces an update to any baked textures relevant to type. @@ -1063,26 +1044,27 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) //----------------------------------------------------------------------------- void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result ) { - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; - const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDefines::EBakedTextureIndex index = baked_iter->first; if (baked_dict) { - for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); + for (LLAvatarAppearanceDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); type_iter != baked_dict->mWearables.end(); ++type_iter) { const LLWearableType::EType comp_type = *type_iter; if (comp_type == type) { - if (mBakedTextureDatas[index].mTexLayerSet) + LLViewerTexLayerSet *layerset = getLayerSet(index); + if (layerset) { - mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled(true); - invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result); + layerset->setUpdatesEnabled(true); + invalidateComposite(layerset, upload_result); } break; } @@ -1246,7 +1228,7 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) // Make sure the inventory is in sync with the avatar. // Update COF contents, don't trigger appearance update. - if (!isAgentAvatarValid()) + if (!isValid()) { llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; } @@ -1287,7 +1269,7 @@ BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) const LLViewerObject *attached_obj = gAgentAvatarp->getWornAttachment(item_id); if (!attached_obj) { - LLAppearanceMgr::instance().removeCOFItemLinks(item_id, false); + LLAppearanceMgr::instance().removeCOFItemLinks(item_id); } } return TRUE; @@ -1295,9 +1277,9 @@ BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) return FALSE; } -U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const +U32 LLVOAvatarSelf::getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const { - LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); return gAgentWearables.getWearableCount(type); } @@ -1328,11 +1310,8 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr discard_level < local_tex_obj->getDiscard()) { local_tex_obj->setDiscard(discard_level); - if (isUsingBakedTextures()) - { - requestLayerSetUpdate(index); - } - else + requestLayerSetUpdate(index); + if (isEditingAppearance()) { LLVisualParamHint::requestHintUpdates(); } @@ -1366,11 +1345,11 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex { return FALSE; } - *tex_pp = local_tex_obj->getImage(); + *tex_pp = dynamic_cast<LLViewerTexture*> (local_tex_obj->getImage()); return TRUE; } -LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const +LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (!isIndexLocalTexture(type)) { @@ -1386,7 +1365,7 @@ LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETe { return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); } - return local_tex_obj->getImage(); + return dynamic_cast<LLViewerFetchedTexture*> (local_tex_obj->getImage()); } const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const @@ -1407,29 +1386,30 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c // Returns true if at least the lowest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const +BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const { /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) { BOOL ret = true; - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - ret &= (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + BOOL tex_avail = (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + ret &= tex_avail; } } return ret; @@ -1445,7 +1425,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) // Returns true if the highest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) const +BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const { const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels. @@ -1454,17 +1434,19 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons { if (layerset == mBakedTextureDatas[i].mTexLayerSet) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) { return FALSE; } @@ -1477,6 +1459,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons return FALSE; } + BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const { const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); @@ -1484,17 +1467,19 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) { return FALSE; } @@ -1504,22 +1489,22 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const return TRUE; } -BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const +BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const { - const LLTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; + const LLViewerTexLayerSet *layerset = getLayerSet(index); if (!layerset) return FALSE; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) return FALSE; return !layerset_buffer->uploadNeeded(); } -BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { LLUUID id; BOOL isDefined = TRUE; if (isIndexLocalTexture(type)) { - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(type); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(type); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (index >= wearable_count) { @@ -1546,7 +1531,7 @@ BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 } //virtual -BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (isIndexBakedTexture(type)) { @@ -1559,7 +1544,7 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 } //virtual -BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { if (isIndexBakedTexture(type)) { @@ -1582,13 +1567,14 @@ void LLVOAvatarSelf::requestLayerSetUploads() } } -void LLVOAvatarSelf::requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i) +void LLVOAvatarSelf::requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i) { ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); - if (!layer_baked && mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getLayerSet(i); + if (!layer_baked && layerset) { - mBakedTextureDatas[i].mTexLayerSet->requestUpload(); + layerset->requestUpload(); } } @@ -1602,8 +1588,8 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - LLTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; - if (layerset && layerset->getComposite() && layerset->getComposite()->uploadPending()) + LLViewerTexLayerSet* layerset = getTexLayerSet(i); + if (layerset && layerset->getViewerComposite() && layerset->getViewerComposite()->uploadPending()) { return true; } @@ -1613,22 +1599,23 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) { - if( !layerset || !layerset->getUpdatesEnabled() ) + LLViewerTexLayerSet *layer_set = dynamic_cast<LLViewerTexLayerSet*>(layerset); + if( !layer_set || !layer_set->getUpdatesEnabled() ) { return; } // llinfos << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegionName() << llendl; - layerset->requestUpdate(); - layerset->invalidateMorphMasks(); + layer_set->requestUpdate(); + layer_set->invalidateMorphMasks(); - if( upload_result ) + if( upload_result && (getRegion() && !getRegion()->getCentralBakeVersion())) { llassert(isSelf()); - ETextureIndex baked_te = getBakedTE( layerset ); + ETextureIndex baked_te = getBakedTE( layer_set ); setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR) ); - layerset->requestUpload(); + layer_set->requestUpload(); updateMeshTextures(); } } @@ -1637,7 +1624,8 @@ void LLVOAvatarSelf::invalidateAll() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE); + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + invalidateComposite(layerset, TRUE); } //mDebugSelfLoadTimer.reset(); } @@ -1655,17 +1643,19 @@ void LLVOAvatarSelf::setCompositeUpdatesEnabled( bool b ) void LLVOAvatarSelf::setCompositeUpdatesEnabled(U32 index, bool b) { - if (mBakedTextureDatas[index].mTexLayerSet ) + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset ) { - mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled( b ); + layerset->setUpdatesEnabled( b ); } } bool LLVOAvatarSelf::isCompositeUpdateEnabled(U32 index) { - if (mBakedTextureDatas[index].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset) { - return mBakedTextureDatas[index].mTexLayerSet->getUpdatesEnabled(); + return layerset->getUpdatesEnabled(); } return false; } @@ -1676,9 +1666,10 @@ void LLVOAvatarSelf::setupComposites() { ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); - if (mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(!layer_baked); + layerset->setUpdatesEnabled(!layer_baked); } } } @@ -1687,10 +1678,11 @@ void LLVOAvatarSelf::updateComposites() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (mBakedTextureDatas[i].mTexLayerSet + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT))) { - mBakedTextureDatas[i].mTexLayerSet->updateComposite(); + layerset->updateComposite(); } } } @@ -1703,11 +1695,12 @@ S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index); if (local_tex_obj) { + const LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); if (type >= 0 && local_tex_obj->getID() != IMG_DEFAULT_AVATAR - && !local_tex_obj->getImage()->isMissingAsset()) + && !image->isMissingAsset()) { - return local_tex_obj->getImage()->getDiscardLevel(); + return image->getDiscardLevel(); } else { @@ -1732,7 +1725,7 @@ void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); if (local_tex_obj) { - const LLViewerFetchedTexture* image_gl = local_tex_obj->getImage(); + const LLViewerFetchedTexture* image_gl = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); if (image_gl) { S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); @@ -1767,8 +1760,8 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te llerrs << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << llendl; return; } - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type); - if (!gAgentWearables.getWearable(wearable_type,index)) + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(type); + if (!gAgentWearables.getViewerWearable(wearable_type,index)) { // no wearable is loaded, cannot set the texture. return; @@ -1781,10 +1774,10 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te return; } - LLTexLayerSet *layer_set = getLayerSet(type); + LLViewerTexLayerSet *layer_set = getLayerSet(type); if (layer_set) { - layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index)); + layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getViewerWearable(wearable_type,index)); } } @@ -1804,16 +1797,13 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te local_tex_obj->setDiscard(tex_discard); if (isSelf()) { - if (gAgentAvatarp->isUsingBakedTextures()) - { requestLayerSetUpdate(type); - } - else - { - LLVisualParamHint::requestHintUpdates(); + if (isEditingAppearance()) + { + LLVisualParamHint::requestHintUpdates(); + } } } - } else { tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); @@ -1826,8 +1816,9 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te local_tex_obj->setID(tex->getID()); setBakedReady(type,baked_version_ready,index); } + //virtual -void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatarSelf::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { if (!isIndexLocalTexture(type)) return; LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); @@ -1846,16 +1837,16 @@ void LLVOAvatarSelf::dumpLocalTextures() const /* ETextureIndex baked_equiv[] = { TEX_UPPER_BAKED, if (isTextureDefined(baked_equiv[i])) */ - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) continue; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; + const ETextureIndex baked_equiv = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; const std::string &name = texture_dict->mName; const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); @@ -1878,7 +1869,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const } else { - const LLViewerFetchedTexture* image = local_tex_obj->getImage(); + const LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -1955,35 +1946,63 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() BOOL LLVOAvatarSelf::getIsCloud() const { + // Let people know why they're clouded without spamming them into oblivion. + bool do_warn = false; + static LLTimer time_since_notice; + F32 update_freq = 30.0; + if (time_since_notice.getElapsedTimeF32() > update_freq) + { + time_since_notice.reset(); + do_warn = true; + } + // do we have our body parts? - if (gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE) == 0 || - gAgentWearables.getWearableCount(LLWearableType::WT_HAIR) == 0 || - gAgentWearables.getWearableCount(LLWearableType::WT_EYES) == 0 || - gAgentWearables.getWearableCount(LLWearableType::WT_SKIN) == 0) + S32 shape_count = gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE); + S32 hair_count = gAgentWearables.getWearableCount(LLWearableType::WT_HAIR); + S32 eye_count = gAgentWearables.getWearableCount(LLWearableType::WT_EYES); + S32 skin_count = gAgentWearables.getWearableCount(LLWearableType::WT_SKIN); + if (!shape_count || !hair_count || !eye_count || !skin_count) { - lldebugs << "No body parts" << llendl; + if (do_warn) + { + llinfos << "Self is clouded due to missing one or more required body parts: " + << (shape_count ? "" : "SHAPE ") + << (hair_count ? "" : "HAIR ") + << (eye_count ? "" : "EYES ") + << (skin_count ? "" : "SKIN ") + << llendl; + } return TRUE; } if (!isTextureDefined(TEX_HAIR, 0)) { - lldebugs << "No hair texture" << llendl; + if (do_warn) + { + llinfos << "Self is clouded because of no hair texture" << llendl; + } return TRUE; } if (!mPreviousFullyLoaded) { - if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) && + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_LOWER)) && (!isTextureDefined(TEX_LOWER_BAKED, 0))) { - lldebugs << "Lower textures not baked" << llendl; + if (do_warn) + { + llinfos << "Self is clouded because lower textures not baked" << llendl; + } return TRUE; } - if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) && + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_UPPER)) && (!isTextureDefined(TEX_UPPER_BAKED, 0))) { - lldebugs << "Upper textures not baked" << llendl; + if (do_warn) + { + llinfos << "Self is clouded because upper textures not baked" << llendl; + } return TRUE; } @@ -2000,7 +2019,11 @@ BOOL LLVOAvatarSelf::getIsCloud() const const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); if (!baked_img || !baked_img->hasGLTexture()) { - lldebugs << "Texture at index " << i << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl; + if (do_warn) + { + llinfos << "Self is clouded because texture at index " << i + << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl; + } return TRUE; } } @@ -2051,7 +2074,85 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); } -const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const +const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const +{ + std::ostringstream outbuf; + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + outbuf << "baked_index: " << baked_index << "\n"; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(tex_index)->mName; + outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":"; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); + if (local_tex_obj) + { + LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); + if (tex_index >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !image->isMissingAsset()) + { + outbuf << " id: " << image->getID() + << " refs: " << image->getNumRefs() + << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) + << " discard: " << image->getDiscardLevel() + << " desired: " << image->getDesiredDiscardLevel() + << " decode: " << image->getDecodePriority() + << " addl: " << image->getAdditionalDecodePriority() + << " ts: " << image->getTextureState() + << " bl: " << image->getBoostLevel() + << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. + << " cl: " << (image->isFullyLoaded() && image->getDiscardLevel()==0) // "completely loaded" + << " mvs: " << image->getMaxVirtualSize() + << " mvsc: " << image->getMaxVirtualSizeResetCounter() + << " mem: " << image->getTextureMemory(); + } + } + outbuf << "\n"; + } + } + } + break; + } + } + return outbuf.str(); +} + +void LLVOAvatarSelf::dumpAllTextures() const +{ + std::string vd_text = "Local textures per baked index and wearable:\n"; + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); + } + LL_DEBUGS("Avatar") << vd_text << llendl; +} + +const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; @@ -2059,21 +2160,21 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLTexLayer /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str()); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { @@ -2100,14 +2201,14 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); BOOL is_texture_final = TRUE; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -2119,20 +2220,14 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const return text; } + +#if 0 // Dump avatar metrics data. LLSD LLVOAvatarSelf::metricsData() { // runway - add region info LLSD result; result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); - std::vector<S32> rez_counts; - LLVOAvatar::getNearbyRezzedStats(rez_counts); - result["nearby"] = LLSD::emptyMap(); - for (S32 i=0; i<rez_counts.size(); ++i) - { - std::string rez_status_name = LLVOAvatar::rezStatusToString(i); - result["nearby"][rez_status_name] = rez_counts[i]; - } result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32(); result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32(); result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32(); @@ -2142,6 +2237,7 @@ LLSD LLVOAvatarSelf::metricsData() return result; } +#endif class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder { @@ -2159,6 +2255,7 @@ public: const std::string& reason, const LLSD& content) { + gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case. if (isGoodStatus(status)) { LL_DEBUGS("Avatar") << "OK" << LL_ENDL; @@ -2167,16 +2264,11 @@ public: else { LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL; - error(status,reason); + errorWithContent(status,reason,content); } } // virtual - void error(U32 status_num, const std::string & reason) - { - } - - // virtual void result(const LLSD & content) { if (mLiveSequence == mExpectedSequence) @@ -2191,19 +2283,121 @@ private: volatile bool & mReportingStarted; }; -void LLVOAvatarSelf::sendAppearanceChangeMetrics() +bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send) +{ + const F32 AV_METRICS_INTERVAL_QA = 30.0; + F32 send_period = 300.0; + if (gSavedSettings.getBOOL("QAModeMetrics")) + { + send_period = AV_METRICS_INTERVAL_QA; + } + + if (force_send || mTimeSinceLastRezMessage.getElapsedTimeF32() > send_period) + { + // Stats for completed phases have been getting logged as they + // complete. This will give us stats for any timers that + // haven't finished as of the metric's being sent. + + if (force_send) + { + LLVOAvatar::logPendingPhasesAllAvatars(); + } + sendViewerAppearanceChangeMetrics(); + } + + return false; +} + +void LLVOAvatarSelf::addMetricsTimerRecord(const LLSD& record) +{ + mPendingTimerRecords.push_back(record); +} + +bool operator<(const LLSD& a, const LLSD& b) +{ + std::ostringstream aout, bout; + aout << LLSDNotationStreamer(a); + bout << LLSDNotationStreamer(b); + std::string astring = aout.str(); + std::string bstring = bout.str(); + + return astring < bstring; + +} + +// Given a vector of LLSD records, return an LLSD array of bucketed stats for val_field. +LLSD summarize_by_buckets(std::vector<LLSD> in_records, + std::vector<std::string> by_fields, + std::string val_field) +{ + LLSD result = LLSD::emptyArray(); + std::map<LLSD,LLViewerStats::StatsAccumulator> accum; + for (std::vector<LLSD>::iterator in_record_iter = in_records.begin(); + in_record_iter != in_records.end(); ++in_record_iter) + { + LLSD& record = *in_record_iter; + LLSD key; + for (std::vector<std::string>::iterator field_iter = by_fields.begin(); + field_iter != by_fields.end(); ++field_iter) + { + const std::string& field = *field_iter; + key[field] = record[field]; + } + LLViewerStats::StatsAccumulator& stats = accum[key]; + F32 value = record[val_field].asReal(); + stats.push(value); + } + for (std::map<LLSD,LLViewerStats::StatsAccumulator>::iterator accum_it = accum.begin(); + accum_it != accum.end(); ++accum_it) + { + LLSD out_record = accum_it->first; + out_record["stats"] = accum_it->second.getData(); + result.append(out_record); + } + return result; +} + +void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics() { // gAgentAvatarp->stopAllPhases(); static volatile bool reporting_started(false); static volatile S32 report_sequence(0); - LLSD msg = metricsData(); + LLSD msg; // = metricsData(); msg["message"] = "ViewerAppearanceChangeMetrics"; msg["session_id"] = gAgentSessionID; msg["agent_id"] = gAgentID; msg["sequence"] = report_sequence; msg["initial"] = !reporting_started; msg["break"] = false; + msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32(); + + // Status of our own rezzing. + msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); + + // Status of all nearby avs including ourself. + msg["nearby"] = LLSD::emptyArray(); + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + for (S32 rez_stat=0; rez_stat < rez_counts.size(); ++rez_stat) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); + msg["nearby"][rez_status_name] = rez_counts[rez_stat]; + } + + // std::vector<std::string> bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake"); + std::vector<std::string> by_fields; + by_fields.push_back("timer_name"); + by_fields.push_back("completed"); + by_fields.push_back("grid_x"); + by_fields.push_back("grid_y"); + by_fields.push_back("is_using_server_bakes"); + by_fields.push_back("is_self"); + by_fields.push_back("central_bake_version"); + LLSD summary = summarize_by_buckets(mPendingTimerRecords, by_fields, std::string("elapsed")); + msg["timers"] = summary; + + mPendingTimerRecords.clear(); // Update sequence number if (S32_MAX == ++report_sequence) @@ -2218,20 +2412,79 @@ void LLVOAvatarSelf::sendAppearanceChangeMetrics() } if (!caps_url.empty()) { + gPendingMetricsUploads++; LLCurlRequest::headers_t headers; LLHTTPClient::post(caps_url, msg, new ViewerAppearanceChangeMetricsResponder(report_sequence, report_sequence, reporting_started)); + mTimeSinceLastRezMessage.reset(); } } +class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder +{ +public: + CheckAgentAppearanceServiceResponder() + { + } + + virtual ~CheckAgentAppearanceServiceResponder() + { + } + + /* virtual */ void result(const LLSD& content) + { + LL_DEBUGS("Avatar") << "status OK" << llendl; + } + + // Error + /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + { + if (isAgentAvatarValid()) + { + LL_DEBUGS("Avatar") << "failed, will rebake [status:" + << status << "]: " << content << llendl; + forceAppearanceUpdate(); + } + } + + static void forceAppearanceUpdate() + { + // Trying to rebake immediately after crossing region boundary + // seems to be failure prone; adding a delay factor. Yes, this + // fix is ad-hoc and not guaranteed to work in all cases. + doAfterInterval(boost::bind(&LLVOAvatarSelf::forceBakeAllTextures, + gAgentAvatarp.get(), true), 5.0); + } +}; + +void LLVOAvatarSelf::checkForUnsupportedServerBakeAppearance() +{ + // Need to check only if we have a server baked appearance and are + // in a non-baking region. + if (!gAgentAvatarp->isUsingServerBakes()) + return; + if (!gAgent.getRegion() || gAgent.getRegion()->getCentralBakeVersion()!=0) + return; + + // if baked image service is unknown, need to refresh. + if (LLAppearanceMgr::instance().getAppearanceServiceURL().empty()) + { + CheckAgentAppearanceServiceResponder::forceAppearanceUpdate(); + } + // query baked image service to check status. + std::string image_url = gAgentAvatarp->getImageURL(TEX_HEAD_BAKED, + getTE(TEX_HEAD_BAKED)->getID()); + LLHTTPClient::head(image_url, new CheckAgentAppearanceServiceResponder); +} + const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const { if (canGrabBakedTexture(baked_index)) { - ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return LLUUID::null; @@ -2243,7 +2496,7 @@ const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) c BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const { - ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return FALSE; @@ -2262,19 +2515,19 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const // baked texture. We don't want people copying people's // work via baked textures. - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); iter != baked_dict->mLocalTextures.end(); ++iter) { const ETextureIndex t_index = (*iter); - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(t_index); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(t_index); U32 count = gAgentWearables.getWearableCount(wearable_type); lldebugs << "Checking index " << (U32) t_index << " count: " << count << llendl; for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) { - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, wearable_index); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, wearable_index); if (wearable) { const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); @@ -2316,26 +2569,34 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const } void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index ) + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) { if (!isIndexLocalTexture(type)) return; - if (!covered_by_baked) + // Sunshine - ignoring covered_by_baked will force local textures + // to always load. Fix for SH-4001 and many related issues. Do + // not restore this without some more targetted fix for the local + // textures failing to load issue. + //if (!covered_by_baked) { - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) + if (imagep->getID() != IMG_DEFAULT_AVATAR) { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - imagep->setBoostLevel(getAvatarBoostLevel()); - - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) + imagep->setNoDelete(); + if (imagep->getDiscardLevel() != 0) { - mHasGrey = TRUE; // for statistics gathering + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } } } else @@ -2346,10 +2607,10 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe } } -LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const +LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const { - LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); - LLWearable* wearable = gAgentWearables.getWearable(type, wearable_index); + LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_index); if (wearable) { return wearable->getLocalTextureObject(i); @@ -2362,7 +2623,7 @@ LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::E // getBakedTE() // Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) //----------------------------------------------------------------------------- -ETextureIndex LLVOAvatarSelf::getBakedTE( const LLTexLayerSet* layerset ) const +ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset ) const { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { @@ -2376,9 +2637,9 @@ ETextureIndex LLVOAvatarSelf::getBakedTE( const LLTexLayerSet* layerset ) const } -void LLVOAvatarSelf::setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid) +void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid) { - ETextureIndex index = LLVOAvatarDictionary::bakedToLocalTextureIndex(i); + ETextureIndex index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(i); setNewBakedTexture(index, uuid); } @@ -2391,7 +2652,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) { // Baked textures live on other sims. LLHost target_host = getObjectHost(); - setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, target_host ) ); + setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) ); updateMeshTextures(); dirtyMesh(); @@ -2400,7 +2661,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) /* switch(te) case TEX_HEAD_BAKED: llinfos << "New baked texture: HEAD" << llendl; */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); if (texture_dict->mIsBakedTexture) { debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish. @@ -2465,7 +2726,7 @@ void LLVOAvatarSelf::outputRezDiagnostics() const LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl; - for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + for (U32 i = 0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) { std::stringstream out; out << "\t\t (" << i << ") "; @@ -2493,27 +2754,29 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } } LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl; - for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + for (U32 i = 0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) { LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; } - for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLTexLayerSet *layerset = debugGetLayerSet(baked_index); + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); if (!layerset) continue; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) continue; LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } + + dumpAllTextures(); } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const { - LL_INFOS("Avatar") + LL_DEBUGS("Avatar") << avString() << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) << LL_ENDL; @@ -2538,7 +2801,8 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid mHeadLayerSet->cancelUpload(); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if ( mBakedTextureDatas[i].mTextureIndex == te && layerset) { if (mInitialBakeIDs[i] != LLUUID::null) { @@ -2552,7 +2816,7 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid } mInitialBakeIDs[i] = LLUUID::null; } - mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); + layerset->cancelUpload(); } } } @@ -2571,17 +2835,17 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = TEX_HEAD_BAKED, TEX_UPPER_BAKED, */ - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsBakedTexture) { if (texture_id == gAgentAvatarp->getTEImage(index)->getID()) { - LLTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index); + LLViewerTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index); if (layer_set) { llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; @@ -2605,15 +2869,6 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) } } -BOOL LLVOAvatarSelf::isUsingBakedTextures() const -{ - // Composite textures are used during appearance mode. - if (gAgentCamera.cameraCustomizeAvatar()) - return FALSE; - - return TRUE; -} - void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) { @@ -2622,7 +2877,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; - LLTexLayerSet* layer_set = getLayerSet(baked_index); + LLViewerTexLayerSet* layer_set = getLayerSet(baked_index); if (layer_set) { if (slam_for_debug) @@ -2654,7 +2909,7 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) case LOCTEX_UPPER_SHIRT: if( mUpperBodyLayerSet ) mUpperBodyLayerSet->requestUpdate(); */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) return; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -2664,22 +2919,22 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) } } -LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const +LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const { - /* switch(index) - case TEX_HEAD_BAKED: - case TEX_HEAD_BODYPAINT: - return mHeadLayerSet; */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); - if (texture_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return mBakedTextureDatas[baked_index].mTexLayerSet; - } - return NULL; + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + return getLayerSet(baked_index); + } + return NULL; } -LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const +LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const { /* switch(index) case TEX_HEAD_BAKED: @@ -2687,26 +2942,60 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const return mHeadLayerSet; */ if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) { - return mBakedTextureDatas[baked_index].mTexLayerSet; + return getTexLayerSet(baked_index); } return NULL; } + + // static -void LLVOAvatarSelf::onCustomizeStart() +void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) { - // We're no longer doing any baking or invalidating on entering - // appearance editing mode. Leaving function in place in case - // further changes require us to do something at this point - Nyx + if (isAgentAvatarValid()) + { + gAgentAvatarp->mIsEditingAppearance = true; + gAgentAvatarp->mUseLocalAppearance = true; + + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToCustomizeAvatar(); + } + +#if 0 + gAgentAvatarp->clearVisualParamWeights(); + gAgentAvatarp->idleUpdateAppearanceAnimation(); +#endif + + gAgentAvatarp->invalidateAll(); // mark all bakes as dirty, request updates + gAgentAvatarp->updateMeshTextures(); // make sure correct textures are applied to the avatar mesh. + gAgentAvatarp->updateTextures(); // call updateTextureStats + } } // static -void LLVOAvatarSelf::onCustomizeEnd() +void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch) { + if (isAgentAvatarValid()) { + gAgentAvatarp->mIsEditingAppearance = false; + if (gAgentAvatarp->getRegion() && !gAgentAvatarp->getRegion()->getCentralBakeVersion()) + { + // FIXME DRANO - move to sendAgentSetAppearance, make conditional on upload complete. + gAgentAvatarp->mUseLocalAppearance = false; + } + gAgentAvatarp->invalidateAll(); + + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToDefault(); + gAgentCamera.resetView(); + } + + LLAppearanceMgr::instance().updateAppearanceFromCOF(); } } @@ -2719,12 +3008,12 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { LLUUID texture_id[TEX_NUM_INDICES]; // pack away current TEs to make sure we don't send them out - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsBakedTexture) { LLTextureEntry* entry = getTE((U8) index); @@ -2736,12 +3025,12 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const bool success = packTEMessage(mesgsys); // unpack TEs to make sure we don't re-trigger a bake - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsBakedTexture) { LLTextureEntry* entry = getTE((U8) index); @@ -2797,3 +3086,36 @@ void LLVOAvatarSelf::dumpScratchTextureByteCount() { llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl; } + +void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) +{ + apr_file_t* file = outfile.getFileHandle(); + if (!file) + { + return; + } + + + apr_file_printf( file, "\n<wearable_info>\n" ); + + LLWearableData *wd = getWearableData(); + for (S32 type = 0; type < LLWearableType::WT_COUNT; type++) + { + const std::string& type_name = LLWearableType::getTypeName((LLWearableType::EType)type); + for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++) + { + LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j); + apr_file_printf( file, "\n\t <wearable type=\"%s\" name=\"%s\"/>\n", + type_name.c_str(), wearable->getName().c_str() ); + LLWearable::visual_param_vec_t v_params; + wearable->getVisualParams(v_params); + for (LLWearable::visual_param_vec_t::iterator it = v_params.begin(); + it != v_params.end(); ++it) + { + LLVisualParam *param = *it; + dump_visual_param(file, param, param->getWeight()); + } + } + } + apr_file_printf( file, "\n</wearable_info>\n" ); +} diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 7bd0c0bf93..3b7b6bac64 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -67,9 +67,8 @@ public: protected: /*virtual*/ BOOL loadAvatar(); BOOL loadAvatarSelf(); - BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info); + BOOL buildSkeletonSelf(const LLAvatarSkeletonInfo *info); BOOL buildMenus(); - /*virtual*/ BOOL loadLayersets(); /** Initialization ** ** @@ -97,7 +96,7 @@ public: void resetJointPositions( void ); - /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ void updateVisualParams(); @@ -111,7 +110,7 @@ public: private: // helper function. Passed in param is assumed to be in avatar's parameter list. - BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); + BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); @@ -131,6 +130,7 @@ private: public: /*virtual*/ bool isSelf() const { return true; } + /*virtual*/ BOOL isValid() const; //-------------------------------------------------------------------- // Updates @@ -177,8 +177,8 @@ private: // LLVOAvatar Constants //-------------------------------------------------------------------- public: - /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_SELF; } - /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED_SELF; } + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLGLTexture::BOOST_AVATAR_SELF; } + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED_SELF; } /*virtual*/ S32 getTexImageSize() const { return LLVOAvatar::getTexImageSize()*4; } /** Rendering @@ -195,32 +195,32 @@ public: //-------------------------------------------------------------------- public: /*virtual*/ bool hasPendingBakedUploads() const; - S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + S32 getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; bool areTexturesCurrent() const; - BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const; - BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const; - BOOL isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const; + BOOL isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const; + BOOL isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const; + BOOL isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const; // If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index - /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const; - /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; + /*virtual*/ BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; + /*virtual*/ BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + /*virtual*/ BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- public: - BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; - LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const; - const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + BOOL getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; + LLViewerFetchedTexture* getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; + const LLUUID& getLocalTextureID(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; void setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index); - /*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); + /*virtual*/ void setLocalTexture(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); protected: - /*virtual*/ void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); + /*virtual*/ void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void getLocalTextureByteCount(S32* gl_byte_count) const; - /*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index); - LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index) const; + /*virtual*/ void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); + LLLocalTextureObject* getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 index) const; private: static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); @@ -233,13 +233,12 @@ private: // Baked textures //-------------------------------------------------------------------- public: - LLVOAvatarDefines::ETextureIndex getBakedTE(const LLTexLayerSet* layerset ) const; - void setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid); - void setNewBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); - void setCachedBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); + LLAvatarAppearanceDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const; + void setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid); + void setNewBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid); + void setCachedBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid); void forceBakeAllTextures(bool slam_for_debug = false); static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); - BOOL isUsingBakedTextures() const; // e.g. false if in appearance edit mode protected: /*virtual*/ void removeMissingBakedTextures(); @@ -248,10 +247,11 @@ protected: //-------------------------------------------------------------------- public: void requestLayerSetUploads(); - void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); - void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + void requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i); + void requestLayerSetUpdate(LLAvatarAppearanceDefines::ETextureIndex i); + LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::ETextureIndex index) const; + //-------------------------------------------------------------------- // Composites @@ -265,8 +265,8 @@ public: void setupComposites(); void updateComposites(); - const LLUUID& grabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; - BOOL canGrabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- @@ -300,10 +300,9 @@ protected: **/ public: - /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type) const; void wearableUpdated(LLWearableType::EType type, BOOL upload_result); protected: - U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; + U32 getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const; //-------------------------------------------------------------------- // Attachments @@ -340,8 +339,8 @@ private: **/ public: - static void onCustomizeStart(); - static void onCustomizeEnd(); + static void onCustomizeStart(bool disable_camera_switch = false); + static void onCustomizeEnd(bool disable_camera_switch = false); //-------------------------------------------------------------------- // Visibility @@ -365,6 +364,7 @@ public: static void dumpTotalLocalTextureByteCount(); void dumpLocalTextures() const; static void dumpScratchTextureByteCount(); + void dumpWearableInfo(LLAPRFile& outfile); //-------------------------------------------------------------------- // Avatar Rez Metrics @@ -372,34 +372,43 @@ public: public: struct LLAvatarTexData { - LLAvatarTexData(const LLUUID& id, LLVOAvatarDefines::ETextureIndex index) : + LLAvatarTexData(const LLUUID& id, LLAvatarAppearanceDefines::ETextureIndex index) : mAvatarID(id), mIndex(index) {} LLUUID mAvatarID; - LLVOAvatarDefines::ETextureIndex mIndex; + LLAvatarAppearanceDefines::ETextureIndex mIndex; }; + + LLTimer mTimeSinceLastRezMessage; + bool updateAvatarRezMetrics(bool force_send); + + std::vector<LLSD> mPendingTimerRecords; + void addMetricsTimerRecord(const LLSD& record); + void debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); } void debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); } void outputRezDiagnostics() const; void outputRezTiming(const std::string& msg) const; void reportAvatarRezTime() const; - void debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished); + void debugBakedTextureUpload(LLAvatarAppearanceDefines::EBakedTextureIndex index, BOOL finished); static void debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); BOOL isAllLocalTextureDataFinal() const; - const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } - const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer + const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return (LLViewerTexLayerSet*)(mBakedTextureDatas[index].mTexLayerSet); } + const std::string verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer + void dumpAllTextures() const; + const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD - LLSD metricsData(); - void sendAppearanceChangeMetrics(); // send data associated with completing a change. + void sendViewerAppearanceChangeMetrics(); // send data associated with completing a change. + void checkForUnsupportedServerBakeAppearance(); private: LLFrameTimer mDebugSelfLoadTimer; F32 mDebugTimeWearablesLoaded; F32 mDebugTimeAvatarVisible; - F32 mDebugTextureLoadTimes[LLVOAvatarDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // load time for each texture at each discard level - F32 mDebugBakedTextureTimes[LLVOAvatarDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture + F32 mDebugTextureLoadTimes[LLAvatarAppearanceDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // load time for each texture at each discard level + F32 mDebugBakedTextureTimes[LLAvatarAppearanceDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture void debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); /** Diagnostics @@ -413,8 +422,7 @@ extern LLPointer<LLVOAvatarSelf> gAgentAvatarp; BOOL isAgentAvatarValid(); void selfStartPhase(const std::string& phase_name); -void selfStopPhase(const std::string& phase_name); -void selfStopAllPhases(); +void selfStopPhase(const std::string& phase_name, bool err_check = true); void selfClearPhases(); #endif // LL_VO_AVATARSELF_H diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 4dca87652d..6a25b765cf 100755 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -102,7 +102,7 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index ceff75a0cc..ac2a34ba1e 100755 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -56,7 +56,8 @@ class LLVoiceCallCapResponder : public LLHTTPClient::Responder public: LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {}; - virtual void error(U32 status, const std::string& reason); // called with bad status codes + // called with bad status codes + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); virtual void result(const LLSD& content); private: @@ -64,11 +65,10 @@ private: }; -void LLVoiceCallCapResponder::error(U32 status, const std::string& reason) +void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("Voice") << "LLVoiceCallCapResponder::error(" - << status << ": " << reason << ")" - << LL_ENDL; + LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:" + << status << "]: " << content << LL_ENDL; LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); if ( channelp ) { diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index b497f80560..9281334d81 100755 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -125,7 +125,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) { mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); + mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FTT_LOCAL_FILE, FALSE, LLGLTexture::BOOST_UI); mSoundSymbol.mWaveActive [i] = false; mSoundSymbol.mWaveOpacity [i] = 1.0f; mSoundSymbol.mWaveExpansion [i] = 1.0f; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index c3cc90f040..9b5d981aa5 100755 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -130,17 +130,18 @@ public: mRetries = retries; } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { + LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, " + << ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" ) + << status << "]: " << content << LL_ENDL; + if ( mRetries > 0 ) { - LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; - LLVivoxVoiceClient::getInstance()->requestVoiceAccountProvision( - mRetries - 1); + LLVivoxVoiceClient::getInstance()->requestVoiceAccountProvision(mRetries - 1); } else { - LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; LLVivoxVoiceClient::getInstance()->giveUp(); } } @@ -199,18 +200,18 @@ class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder public: LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {}; - virtual void error(U32 status, const std::string& reason); // called with bad status codes + // called with bad status codes + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); virtual void result(const LLSD& content); private: LLVivoxVoiceClient::state mRequestingState; // state }; -void LLVivoxVoiceClientCapResponder::error(U32 status, const std::string& reason) +void LLVivoxVoiceClientCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder::error(" - << status << ": " << reason << ")" - << LL_ENDL; + LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder error [status:" + << status << "]: " << content << LL_ENDL; LLVivoxVoiceClient::getInstance()->sessionTerminate(); } @@ -2249,7 +2250,8 @@ void LLVivoxVoiceClient::giveUp() static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel) { - F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the new position and velocity + F32 nat[3], nup[3], nl[3]; // the new at, up, left vectors and the new position and velocity +// F32 nvel[3]; F64 npos[3]; // The original XML command was sent like this: @@ -2299,9 +2301,9 @@ static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVe npos[1] = pos.mdV[VZ]; npos[2] = pos.mdV[VY]; - nvel[0] = vel.mV[VX]; - nvel[1] = vel.mV[VZ]; - nvel[2] = vel.mV[VY]; +// nvel[0] = vel.mV[VX]; +// nvel[1] = vel.mV[VZ]; +// nvel[2] = vel.mV[VY]; for(int i=0;i<3;++i) { at.mV[i] = nat[i]; @@ -3938,7 +3940,6 @@ void LLVivoxVoiceClient::messageEvent( bool is_do_not_disturb = gAgent.isDoNotDisturb(); bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat); bool is_linden = LLMuteList::getInstance()->isLinden(session->mName); - bool quiet_chat = false; LLChat chat; chat.mMuted = is_muted && !is_linden; @@ -3951,7 +3952,6 @@ void LLVivoxVoiceClient::messageEvent( if(is_do_not_disturb && !is_linden) { - quiet_chat = true; // TODO: Question: Return do not disturb mode response here? Or maybe when session is started instead? } diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 31358df85f..36793017ed 100755 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -298,7 +298,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL); + mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -384,9 +384,9 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mSun.setIntensity(SUN_INTENSITY); mMoon.setIntensity(0.1f * SUN_INTENSITY); - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -478,9 +478,9 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index cb905d02da..de15f0ef43 100755 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -467,7 +467,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, S32 vertex_count = 0; S32 i, x, y; - S32 num_vertices, num_indices; + S32 num_vertices; U32 render_stride = mLastStride; S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); @@ -485,7 +485,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, if (north_stride == render_stride) { num_vertices = 2 * length + 1; - num_indices = length * 6 - 3; facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; @@ -536,7 +535,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { // North stride is longer (has less vertices) num_vertices = length + length/2 + 1; - num_indices = half_length*9 - 3; facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; @@ -595,7 +593,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, length = patch_size / north_stride; half_length = length / 2; num_vertices = length + half_length + 1; - num_indices = 9*half_length - 3; facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; @@ -666,7 +663,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { S32 i, x, y; - S32 num_vertices, num_indices; + S32 num_vertices; U32 render_stride = mLastStride; S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); @@ -679,7 +676,6 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, if (east_stride == render_stride) { num_vertices = 2 * length + 1; - num_indices = length * 6 - 3; facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; @@ -728,7 +724,6 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { // East stride is longer (has less vertices) num_vertices = length + half_length + 1; - num_indices = half_length*9 - 3; facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; @@ -783,7 +778,6 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, length = patch_size / east_stride; half_length = length / 2; num_vertices = length + length/2 + 1; - num_indices = 9*(length/2) - 3; facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 6687ce432f..145a0380d6 100755 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -316,7 +316,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d94cd01a0b..8730ef66bb 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -370,7 +370,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // Unpack texture entry data // - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); if (result & teDirtyBits) { updateTEData(); @@ -747,7 +747,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) { F32 area = (F32) camera->getScreenPixelArea(); vsize = area; - imagep->setBoostLevel(LLViewerTexture::BOOST_HUD); + imagep->setBoostLevel(LLGLTexture::BOOST_HUD); face->setPixelArea(area); // treat as full screen face->setVirtualSize(vsize); } @@ -803,7 +803,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (mSculptTexture.notNull()) { mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLViewerTexture::BOOST_SCULPTED)); + (S32)LLGLTexture::BOOST_SCULPTED)); mSculptTexture->setForSculpt() ; if(!mSculptTexture->isCachedRawImageReady()) @@ -1006,7 +1006,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (is404) { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); //render prim proxy when mesh loading attempts give up volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); @@ -1090,7 +1090,7 @@ void LLVOVolume::updateSculptTexture() LLUUID id = sculpt_params->getSculptTexture(); if (id.notNull()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } } else @@ -2743,7 +2743,7 @@ void LLVOVolume::updateSpotLightPriority() if (mLightTexture.notNull()) { mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS); + mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); } } diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 7f17fd3e56..4e26587184 100755 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -724,8 +724,8 @@ void LLVOWLSky::updateStarColors() const F32 var = 0.15f; const F32 min = 0.5f; //0.75f; - const F32 sunclose_max = 0.6f; - const F32 sunclose_range = 1 - sunclose_max; + //const F32 sunclose_max = 0.6f; + //const F32 sunclose_range = 1 - sunclose_max; //F32 below_horizon = - llmin(0.0f, gSky.mVOSkyp->getToSunLast().mV[2]); //F32 brightness_factor = llmin(1.0f, below_horizon * 20); @@ -739,14 +739,14 @@ void LLVOWLSky::updateStarColors() U32 x; for (x = 0; x < getStarsNumVerts(); ++x) { - F32 sundir_factor = 1; + //F32 sundir_factor = 1; LLVector3 tostar = *v_p; tostar.normVec(); - const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast(); - if (how_close_to_sun > sunclose_max) - { - sundir_factor = (1 - how_close_to_sun) / sunclose_range; - } + //const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast(); + //if (how_close_to_sun > sunclose_max) + //{ + // sundir_factor = (1 - how_close_to_sun) / sunclose_range; + //} intensity = *(v_i); F32 alpha = v_c->mV[VALPHA] + (ll_frand() - 0.5f) * var * intensity; if (alpha < min * intensity) diff --git a/indra/newview/llwaterparamset.cpp b/indra/newview/llwaterparamset.cpp index 39d366b023..9cc91d2246 100755 --- a/indra/newview/llwaterparamset.cpp +++ b/indra/newview/llwaterparamset.cpp @@ -185,8 +185,6 @@ LLVector3 LLWaterParamSet::getVector3(const std::string& paramName, bool& error) LLVector2 LLWaterParamSet::getVector2(const std::string& paramName, bool& error) { // test to see if right type - int ttest; - ttest = mParamValues.size(); LLSD cur_val = mParamValues.get(paramName); if (!cur_val.isArray() || cur_val.size() != 2) { diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp deleted file mode 100755 index 402504933c..0000000000 --- a/indra/newview/llwearable.cpp +++ /dev/null @@ -1,1285 +0,0 @@ -/** - * @file llwearable.cpp - * @brief LLWearable class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "lldictionary.h" -#include "llfloatersidepanelcontainer.h" -#include "lllocaltextureobject.h" -#include "llnotificationsutil.h" -#include "llviewertexturelist.h" -#include "llinventorymodel.h" -#include "llinventoryobserver.h" -#include "llsidepanelappearance.h" -#include "lltexlayer.h" -#include "lltexglobalcolor.h" -#include "lltrans.h" -#include "llviewerregion.h" -#include "llvisualparam.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "llvoavatardefines.h" -#include "llwearable.h" -#include "llviewercontrol.h" - -using namespace LLVOAvatarDefines; - -// static -S32 LLWearable::sCurrentDefinitionVersion = 1; - -// support class - remove for 2.1 (hackity hack hack) -class LLOverrideBakedTextureUpdate -{ -public: - LLOverrideBakedTextureUpdate(bool temp_state) - { - U32 num_bakes = (U32) LLVOAvatarDefines::BAKED_NUM_INDICES; - for( U32 index = 0; index < num_bakes; ++index ) - { - composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); - } - gAgentAvatarp->setCompositeUpdatesEnabled(temp_state); - } - - ~LLOverrideBakedTextureUpdate() - { - U32 num_bakes = (U32)LLVOAvatarDefines::BAKED_NUM_INDICES; - for( U32 index = 0; index < num_bakes; ++index ) - { - gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); - } - } -private: - bool composite_enabled[LLVOAvatarDefines::BAKED_NUM_INDICES]; -}; - -// Private local functions -static std::string terse_F32_to_string(F32 f); -static std::string asset_id_to_filename(const LLUUID &asset_id); - -LLWearable::LLWearable(const LLTransactionID& transaction_id) : - mDefinitionVersion(LLWearable::sCurrentDefinitionVersion), - mType(LLWearableType::WT_INVALID) -{ - mTransactionID = transaction_id; - mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); -} - -LLWearable::LLWearable(const LLAssetID& asset_id) : - mDefinitionVersion( LLWearable::sCurrentDefinitionVersion ), - mType(LLWearableType::WT_INVALID) -{ - mAssetID = asset_id; - mTransactionID.setNull(); -} - -LLWearable::~LLWearable() -{ -} - -const std::string& LLWearable::getTypeLabel() const -{ - return LLWearableType::getTypeLabel(mType); -} - -const std::string& LLWearable::getTypeName() const -{ - return LLWearableType::getTypeName(mType); -} - -LLAssetType::EType LLWearable::getAssetType() const -{ - return LLWearableType::getAssetType(mType); -} - -BOOL LLWearable::exportFile(LLFILE* file) const -{ - // header and version - if( fprintf( file, "LLWearable version %d\n", mDefinitionVersion ) < 0 ) - { - return FALSE; - } - - // name - if( fprintf( file, "%s\n", mName.c_str() ) < 0 ) - { - return FALSE; - } - - // description - if( fprintf( file, "%s\n", mDescription.c_str() ) < 0 ) - { - return FALSE; - } - - // permissions - if( !mPermissions.exportFile( file ) ) - { - return FALSE; - } - - // sale info - if( !mSaleInfo.exportFile( file ) ) - { - return FALSE; - } - - // wearable type - S32 type = (S32)mType; - if( fprintf( file, "type %d\n", type ) < 0 ) - { - return FALSE; - } - - // parameters - S32 num_parameters = mVisualParamIndexMap.size(); - if( fprintf( file, "parameters %d\n", num_parameters ) < 0 ) - { - return FALSE; - } - - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); - ++iter) - { - S32 param_id = iter->first; - const LLVisualParam* param = iter->second; - F32 param_weight = param->getWeight(); - if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 ) - { - return FALSE; - } - } - - // texture entries - S32 num_textures = mTEMap.size(); - if( fprintf( file, "textures %d\n", num_textures ) < 0 ) - { - return FALSE; - } - - for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) - { - S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); - if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 ) - { - return FALSE; - } - } - return TRUE; -} - - -void LLWearable::createVisualParams() -{ - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if (param->getWearableType() == mType) - { - addVisualParam(param->cloneParam(this)); - } - } - - // resync driver parameters to point to the newly cloned driven parameters - for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); - param_iter != mVisualParamIndexMap.end(); - ++param_iter) - { - LLVisualParam* param = param_iter->second; - LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; - // need this line to disambiguate between versions of LLCharacter::getVisualParam() - LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam; - param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) - { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) - { - llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; - continue; - } - } - } -} - -BOOL LLWearable::importFile( LLFILE* file ) -{ - // *NOTE: changing the type or size of this buffer will require - // changes in the fscanf() code below. You would be better off - // rewriting this to use streams and not require an open FILE. - char text_buffer[2048]; /* Flawfinder: ignore */ - S32 fields_read = 0; - - // suppress texlayerset updates while wearables are being imported. Layersets will be updated - // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. - LLOverrideBakedTextureUpdate stop_bakes(false); - - // read header and version - fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion ); - if( fields_read != 1 ) - { - // Shouldn't really log the asset id for security reasons, but - // we need it in this case. - llwarns << "Bad Wearable asset header: " << mAssetID << llendl; - //gVFS->dumpMap(); - return FALSE; - } - - - // Temoprary hack to allow wearables with definition version 24 to still load. - // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 - // the extra check for version == 24 can be removed before release, once internal testers - // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that - // these wearables get re-saved with version definition 22. - if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) - { - llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; - return FALSE; - } - - // name - int next_char = fgetc( file ); /* Flawfinder: ignore */ - if( '\n' == next_char ) - { - // no name - mName = ""; - } - else - { - ungetc( next_char, file ); - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%2047[^\n]", - text_buffer); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ - { - llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; - } - mName = text_buffer; - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); - } - - // description - next_char = fgetc( file ); /* Flawfinder: ignore */ - if( '\n' == next_char ) - { - // no description - mDescription = ""; - } - else - { - ungetc( next_char, file ); - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%2047[^\n]", - text_buffer ); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ - { - llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; - } - mDescription = text_buffer; - LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); - } - - // permissions - S32 perm_version; - fields_read = fscanf( file, " permissions %d\n", &perm_version ); - if( (fields_read != 1) || (perm_version != 0) ) - { - llwarns << "Bad Wearable asset: missing permissions" << llendl; - return FALSE; - } - if( !mPermissions.importFile( file ) ) - { - return FALSE; - } - - // sale info - S32 sale_info_version; - fields_read = fscanf( file, " sale_info %d\n", &sale_info_version ); - if( (fields_read != 1) || (sale_info_version != 0) ) - { - llwarns << "Bad Wearable asset: missing sale_info" << llendl; - return FALSE; - } - // Sale info used to contain next owner perm. It is now in the - // permissions. Thus, we read that out, and fix legacy - // objects. It's possible this op would fail, but it should pick - // up the vast majority of the tasks. - BOOL has_perm_mask = FALSE; - U32 perm_mask = 0; - if( !mSaleInfo.importFile(file, has_perm_mask, perm_mask) ) - { - return FALSE; - } - if(has_perm_mask) - { - // fair use fix. - if(!(perm_mask & PERM_COPY)) - { - perm_mask |= PERM_TRANSFER; - } - mPermissions.setMaskNext(perm_mask); - } - - // wearable type - S32 type = -1; - fields_read = fscanf( file, "type %d\n", &type ); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: bad type" << llendl; - return FALSE; - } - if( 0 <= type && type < LLWearableType::WT_COUNT ) - { - setType((LLWearableType::EType)type); - } - else - { - mType = LLWearableType::WT_COUNT; - llwarns << "Bad Wearable asset: bad type #" << type << llendl; - return FALSE; - } - - // parameters header - S32 num_parameters = 0; - fields_read = fscanf( file, "parameters %d\n", &num_parameters ); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: missing parameters block" << llendl; - return FALSE; - } - - if( num_parameters != mVisualParamIndexMap.size() ) - { - llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. type: " << mType << llendl; - } - - // parameters - S32 i; - for( i = 0; i < num_parameters; i++ ) - { - S32 param_id = 0; - F32 param_weight = 0.f; - fields_read = fscanf( file, "%d %f\n", ¶m_id, ¶m_weight ); - if( fields_read != 2 ) - { - llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; - return FALSE; - } - mSavedVisualParamMap[param_id] = param_weight; - } - - // textures header - S32 num_textures = 0; - fields_read = fscanf( file, "textures %d\n", &num_textures); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: missing textures block" << llendl; - return FALSE; - } - - // textures - for( i = 0; i < num_textures; i++ ) - { - S32 te = 0; - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%d %2047s\n", - &te, text_buffer); - if( fields_read != 2 ) - { - llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; - return FALSE; - } - - if( !LLUUID::validate( text_buffer ) ) - { - llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl; - return FALSE; - } - LLUUID id = LLUUID(text_buffer); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id ); - if( mTEMap.find(te) != mTEMap.end() ) - { - delete mTEMap[te]; - } - if( mSavedTEMap.find(te) != mSavedTEMap.end() ) - { - delete mSavedTEMap[te]; - } - - if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) - { - image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(id, (LLVOAvatarDefines::ETextureIndex)te), NULL); - } - LLUUID textureid(text_buffer); - mTEMap[te] = new LLLocalTextureObject(image, textureid); - mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); - createLayers(te); - } - - // copy all saved param values to working params - revertValues(); - - return TRUE; -} - - -// Avatar parameter and texture definitions can change over time. -// This function returns true if parameters or textures have been added or removed -// since this wearable was created. -BOOL LLWearable::isOldVersion() const -{ - if (!isAgentAvatarValid()) return FALSE; - - if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion ) - { - llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; - llassert(0); - } - - if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion ) - { - return TRUE; - } - - S32 param_count = 0; - for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) && (param->isTweakable() ) ) - { - param_count++; - if( !is_in_map(mVisualParamIndexMap, param->getID() ) ) - { - return TRUE; - } - } - } - if( param_count != mVisualParamIndexMap.size() ) - { - return TRUE; - } - - - S32 te_count = 0; - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_count++; - if( !is_in_map(mTEMap, te ) ) - { - return TRUE; - } - } - } - if( te_count != mTEMap.size() ) - { - return TRUE; - } - - return FALSE; -} - -// Avatar parameter and texture definitions can change over time. -// * If parameters or textures have been REMOVED since the wearable was created, -// they're just ignored, so we consider the wearable clean even though isOldVersion() -// will return true. -// * If parameters or textures have been ADDED since the wearable was created, -// they are taken to have default values, so we consider the wearable clean -// only if those values are the same as the defaults. -BOOL LLWearable::isDirty() const -{ - if (!isAgentAvatarValid()) return FALSE; - - for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) - && (param->isTweakable() ) - && !param->getCrossWearable()) - { - F32 current_weight = getVisualParamWeight(param->getID()); - current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() ); - F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight()); - saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() ); - - U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); - U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); - if( a != b ) - { - return TRUE; - } - } - } - - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator current_iter = mTEMap.find(te); - if(current_iter != mTEMap.end()) - { - const LLUUID& current_image_id = current_iter->second->getID(); - te_map_t::const_iterator saved_iter = mSavedTEMap.find(te); - if(saved_iter != mSavedTEMap.end()) - { - const LLUUID& saved_image_id = saved_iter->second->getID(); - if (saved_image_id != current_image_id) - { - // saved vs current images are different, wearable is dirty - return TRUE; - } - } - else - { - // image found in current image list but not saved image list - return TRUE; - } - } - } - } - - return FALSE; -} - - -void LLWearable::setParamsToDefaults() -{ - if (!isAgentAvatarValid()) return; - - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) ) - { - setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE); - } - } -} - -void LLWearable::setTexturesToDefaults() -{ - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - LLUUID id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); - if( mTEMap.find(te) == mTEMap.end() ) - { - mTEMap[te] = new LLLocalTextureObject(image, id); - createLayers(te); - } - else - { - // Local Texture Object already created, just set image and UUID - LLLocalTextureObject *lto = mTEMap[te]; - lto->setID(id); - lto->setImage(image); - } - } - } -} - -// Updates the user's avatar's appearance -void LLWearable::writeToAvatar() -{ - if (!isAgentAvatarValid()) return; - - ESex old_sex = gAgentAvatarp->getSex(); - - // Pull params - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the - // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. - if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) - { - S32 param_id = param->getID(); - F32 weight = getVisualParamWeight(param_id); - - gAgentAvatarp->setVisualParamWeight( param_id, weight, FALSE ); - } - } - - // Pull texture entries - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = mTEMap.find(te); - LLUUID image_id; - if(iter != mTEMap.end()) - { - image_id = iter->second->getID(); - } - else - { - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); - // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. - gAgentAvatarp->setLocalTextureTE(te, image, 0); - } - } - - ESex new_sex = gAgentAvatarp->getSex(); - if( old_sex != new_sex ) - { - gAgentAvatarp->updateSexDependentLayerSets( FALSE ); - } - -// if( upload_bake ) -// { -// gAgent.sendAgentSetAppearance(); -// } -} - - -// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. -// static -void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ) -{ - if (!isAgentAvatarValid()) return; - - // You can't just remove body parts. - if( (type == LLWearableType::WT_SHAPE) || - (type == LLWearableType::WT_SKIN) || - (type == LLWearableType::WT_HAIR) || - (type == LLWearableType::WT_EYES) ) - { - return; - } - - // Pull params - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) ) - { - S32 param_id = param->getID(); - gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake ); - } - } - - if(gAgentCamera.cameraCustomizeAvatar()) - { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); - } - - gAgentAvatarp->updateVisualParams(); - gAgentAvatarp->wearableUpdated(type, FALSE); - -// if( upload_bake ) -// { -// gAgent.sendAgentSetAppearance(); -// } -} - -// Does not copy mAssetID. -// Definition version is current: removes obsolete enties and creates default values for new ones. -void LLWearable::copyDataFrom(const LLWearable* src) -{ - if (!isAgentAvatarValid()) return; - - mDefinitionVersion = LLWearable::sCurrentDefinitionVersion; - - mName = src->mName; - mDescription = src->mDescription; - mPermissions = src->mPermissions; - mSaleInfo = src->mSaleInfo; - - setType(src->mType); - - mSavedVisualParamMap.clear(); - // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) ) - { - S32 id = param->getID(); - F32 weight = src->getVisualParamWeight(id); - mSavedVisualParamMap[id] = weight; - } - } - - destroyTextures(); - // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - for (S32 te = 0; te < TEX_NUM_INDICES; te++) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = src->mTEMap.find(te); - LLUUID image_id; - LLViewerFetchedTexture *image = NULL; - if(iter != src->mTEMap.end()) - { - image = src->getLocalTextureObject(te)->getImage(); - image_id = src->getLocalTextureObject(te)->getID(); - mTEMap[te] = new LLLocalTextureObject(image, image_id); - mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); - mTEMap[te]->setBakedReady(src->getLocalTextureObject(te)->getBakedReady()); - mTEMap[te]->setDiscard(src->getLocalTextureObject(te)->getDiscard()); - } - else - { - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - image = LLViewerTextureManager::getFetchedTexture( image_id ); - mTEMap[te] = new LLLocalTextureObject(image, image_id); - mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); - } - createLayers(te); - } - } - - // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable - // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) - revertValues(); -} - -void LLWearable::setItemID(const LLUUID& item_id) -{ - mItemID = item_id; -} - -const LLUUID& LLWearable::getItemID() const -{ - return mItemID; -} - -void LLWearable::setType(LLWearableType::EType type) -{ - mType = type; - createVisualParams(); -} - -LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) -{ - te_map_t::iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const -{ - te_map_t::const_iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - const LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -std::vector<LLLocalTextureObject*> LLWearable::getLocalTextureListSeq() -{ - std::vector<LLLocalTextureObject*> result; - - for(te_map_t::const_iterator iter = mTEMap.begin(); - iter != mTEMap.end(); iter++) - { - LLLocalTextureObject* lto = iter->second; - result.push_back(lto); - } - - return result; -} - -void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) -{ - if( mTEMap.find(index) != mTEMap.end() ) - { - mTEMap.erase(index); - } - mTEMap[index] = new LLLocalTextureObject(lto); -} - - -void LLWearable::addVisualParam(LLVisualParam *param) -{ - if( mVisualParamIndexMap[param->getID()] ) - { - delete mVisualParamIndexMap[param->getID()]; - } - param->setIsDummy(FALSE); - mVisualParamIndexMap[param->getID()] = param; - mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); -} - -void LLWearable::setVisualParams() -{ - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - gAgentAvatarp->setVisualParamWeight(id, value, FALSE); - } -} - - -void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) -{ - if( is_in_map(mVisualParamIndexMap, param_index ) ) - { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; - wearable_param->setWeight(value, upload_bake); - } - else - { - llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; - } -} - -F32 LLWearable::getVisualParamWeight(S32 param_index) const -{ - if( is_in_map(mVisualParamIndexMap, param_index ) ) - { - const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; - return wearable_param->getWeight(); - } - else - { - llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; - } - return (F32)-1.0; -} - -LLVisualParam* LLWearable::getVisualParam(S32 index) const -{ - visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); - return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; -} - - -void LLWearable::getVisualParams(visual_param_vec_t &list) -{ - visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); - visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); - - // add all visual params to the passed-in vector - for( ; iter != end; ++iter ) - { - list.push_back(iter->second); - } -} - -void LLWearable::animateParams(F32 delta, BOOL upload_bake) -{ - for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); - ++iter) - { - LLVisualParam *param = (LLVisualParam*) iter->second; - param->animate(delta, upload_bake); - } -} - -LLColor4 LLWearable::getClothesColor(S32 te) const -{ - LLColor4 color; - U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - color.mV[index] = getVisualParamWeight(param_name[index]); - } - } - return color; -} - -void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) -{ - U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake); - } - } -} - -void LLWearable::revertValues() -{ - //update saved settings so wearable is no longer dirty - // non-driver params first - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && !dynamic_cast<LLDriverParam*>(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - //then driver params - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && dynamic_cast<LLDriverParam*>(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - // make sure that saved values are sane - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *param = getVisualParam(id); - if( param ) - { - mSavedVisualParamMap[id] = param->getWeight(); - } - } - - syncImages(mSavedTEMap, mTEMap); - - - LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel ) - { - panel->updateScrollingPanelList(); - } -} - -BOOL LLWearable::isOnTop() const -{ - return (this == gAgentWearables.getTopWearable(mType)); -} - -void LLWearable::createLayers(S32 te) -{ - LLTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); - if (layer_set) - { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); - } - else - { - llerrs << "could not find layerset for LTO in wearable!" << llendl; - } -} - -void LLWearable::saveValues() -{ - //update saved settings so wearable is no longer dirty - mSavedVisualParamMap.clear(); - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - mSavedVisualParamMap[id] = value; - } - - // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - syncImages(mTEMap, mSavedTEMap); - - - LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel ) - { - panel->updateScrollingPanelList(); - } -} - -void LLWearable::syncImages(te_map_t &src, te_map_t &dst) -{ - // Deep copy of src (copies only those tes that are current, filling in defaults where needed) - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = src.find(te); - LLUUID image_id; - LLViewerFetchedTexture *image = NULL; - LLLocalTextureObject *lto = NULL; - if(iter != src.end()) - { - // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. - lto = iter->second; - image = lto->getImage(); - image_id = lto->getID(); - } - else - { - // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - image = LLViewerTextureManager::getFetchedTexture( image_id ); - } - - if( dst.find(te) != dst.end() ) - { - // there's already an entry in the destination map for the texture. Just update its values. - dst[te]->setImage(image); - dst[te]->setID(image_id); - } - else - { - // no entry found in the destination map, we need to create a new Local Texture Object - dst[te] = new LLLocalTextureObject(image, image_id); - } - - if( lto ) - { - // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. - dst[te]->setBakedReady(lto->getBakedReady()); - dst[te]->setDiscard(lto->getDiscard()); - } - } - } -} - -void LLWearable::destroyTextures() -{ - for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mTEMap.clear(); - for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mSavedTEMap.clear(); -} - -void LLWearable::pullCrossWearableValues() -{ - // scan through all of the avatar's visual parameters - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if( param ) - { - LLDriverParam *driver_param = dynamic_cast<LLDriverParam*>(param); - if(driver_param) - { - // parameter is a driver parameter, have it update its - driver_param->updateCrossDrivenParams(getType()); - } - } - } -} - - -void LLWearable::setLabelUpdated() const -{ - gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); -} - -void LLWearable::refreshName() -{ - LLUUID item_id = getItemID(); - LLInventoryItem* item = gInventory.getItem(item_id); - if( item ) - { - mName = item->getName(); - } -} - -struct LLWearableSaveData -{ - LLWearableType::EType mType; -}; - -void LLWearable::saveNewAsset() const -{ -// llinfos << "LLWearable::saveNewAsset() type: " << getTypeName() << llendl; - //llinfos << *this << llendl; - - const std::string filename = asset_id_to_filename(mAssetID); - LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ - BOOL successful_save = FALSE; - if(fp && exportFile(fp)) - { - successful_save = TRUE; - } - if(fp) - { - fclose(fp); - fp = NULL; - } - if(!successful_save) - { - std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str()); - llwarns << buffer << llendl; - - LLSD args; - args["NAME"] = mName; - LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args); - return; - } - - // save it out to database - if( gAssetStorage ) - { - /* - std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); - if (!url.empty()) - { - llinfos << "Update Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); - body["asset_type"] = LLAssetType::lookup(getAssetType()); - body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); - body["name"] = getName(); - body["description"] = getDescription(); - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); - } - else - { - } - */ - LLWearableSaveData* data = new LLWearableSaveData; - data->mType = mType; - gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), - &LLWearable::onSaveNewAssetComplete, - (void*)data); - } -} - -// static -void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLWearableSaveData* data = (LLWearableSaveData*)userdata; - const std::string& type_name = LLWearableType::getTypeName(data->mType); - if(0 == status) - { - // Success - llinfos << "Saved wearable " << type_name << llendl; - } - else - { - std::string buffer = llformat("Unable to save %s to central asset store.", type_name.c_str()); - llwarns << buffer << " Status: " << status << llendl; - LLSD args; - args["NAME"] = type_name; - LLNotificationsUtil::add("CannotSaveToAssetStore", args); - } - - // Delete temp file - const std::string src_filename = asset_id_to_filename(new_asset_id); - LLFile::remove(src_filename); - - // delete the context data - delete data; - -} - -std::ostream& operator<<(std::ostream &s, const LLWearable &w) -{ - s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; - s << " Name: " << w.mName << "\n"; - s << " Desc: " << w.mDescription << "\n"; - //w.mPermissions - //w.mSaleInfo - - s << " Params:" << "\n"; - for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); - iter != w.mVisualParamIndexMap.end(); ++iter) - { - S32 param_id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 param_weight = wearable_param->getWeight(); - s << " " << param_id << " " << param_weight << "\n"; - } - - s << " Textures:" << "\n"; - for (LLWearable::te_map_t::const_iterator iter = w.mTEMap.begin(); - iter != w.mTEMap.end(); ++iter) - { - S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); - s << " " << te << " " << image_id << "\n"; - } - return s; -} - - -std::string terse_F32_to_string(F32 f) -{ - std::string r = llformat("%.2f", f); - S32 len = r.length(); - - // "1.20" -> "1.2" - // "24.00" -> "24." - while (len > 0 && ('0' == r[len - 1])) - { - r.erase(len-1, 1); - len--; - } - if ('.' == r[len - 1]) - { - // "24." -> "24" - r.erase(len-1, 1); - } - else if (('-' == r[0]) && ('0' == r[1])) - { - // "-0.59" -> "-.59" - r.erase(1, 1); - } - else if ('0' == r[0]) - { - // "0.59" -> ".59" - r.erase(0, 1); - } - return r; -} - -std::string asset_id_to_filename(const LLUUID &asset_id) -{ - std::string asset_id_string; - asset_id.toString(asset_id_string); - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl"; - return filename; -} diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 92697fb2eb..c196d70617 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -34,6 +34,7 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "lltransutil.h" #include "llviewerattachmenu.h" #include "llvoavatarself.h" @@ -788,23 +789,24 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() const uuid_vec_t& ids = mUUIDs; // selected items IDs LLUUID selected_id = ids.front(); // ID of the first selected item - functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1); - // Register handlers common for all wearable types. registrar.add("Wearable.Wear", boost::bind(wear_multiple, ids, true)); registrar.add("Wearable.Add", boost::bind(wear_multiple, ids, false)); registrar.add("Wearable.Edit", boost::bind(handleMultiple, LLAgentWearables::editWearable, ids)); registrar.add("Wearable.CreateNew", boost::bind(createNewWearable, selected_id)); registrar.add("Wearable.ShowOriginal", boost::bind(show_item_original, selected_id)); - registrar.add("Wearable.TakeOffDetach", boost::bind(handleMultiple, take_off, ids)); + registrar.add("Wearable.TakeOffDetach", + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); // Register handlers for clothing. - registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, ids)); + registrar.add("Clothing.TakeOff", + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); // Register handlers for body parts. // Register handlers for attachments. - registrar.add("Attachment.Detach", boost::bind(handleMultiple, take_off, ids)); + registrar.add("Attachment.Detach", + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); registrar.add("Attachment.Profile", boost::bind(show_item_profile, selected_id)); registrar.add("Object.Attach", boost::bind(LLViewerAttachMenu::attachObjects, ids, _2)); diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 6f6411ce3c..ef1a953f59 100755 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -42,20 +42,23 @@ struct LLWearableArrivedData { LLWearableArrivedData(LLAssetType::EType asset_type, const std::string& wearable_name, - void(*asset_arrived_callback)(LLWearable*, void* userdata), + LLAvatarAppearance* avatarp, + void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata) : mAssetType( asset_type ), mCallback( asset_arrived_callback ), mUserdata( userdata ), mName( wearable_name ), - mRetries(0) + mRetries(0), + mAvatarp(avatarp) {} LLAssetType::EType mAssetType; - void (*mCallback)(LLWearable*, void* userdata); + void (*mCallback)(LLViewerWearable*, void* userdata); void* mUserdata; std::string mName; S32 mRetries; + LLAvatarAppearance *mAvatarp; }; //////////////////////////////////////////////////////////////////////////// @@ -72,10 +75,10 @@ void LLWearableList::cleanup() mList.clear(); } -void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata) +void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAvatarAppearance* avatarp, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata) { llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) ); - LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL ); + LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL ); if( instance ) { asset_arrived_callback( instance, userdata ); @@ -85,7 +88,7 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara gAssetStorage->getAssetData(assetID, asset_type, LLWearableList::processGetAssetReply, - (void*)new LLWearableArrivedData( asset_type, wearable_name, asset_arrived_callback, userdata ), + (void*)new LLWearableArrivedData( asset_type, wearable_name, avatarp, asset_arrived_callback, userdata ), TRUE); } } @@ -95,25 +98,31 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID { BOOL isNewWearable = FALSE; LLWearableArrivedData* data = (LLWearableArrivedData*) userdata; - LLWearable* wearable = NULL; // NULL indicates failure + LLViewerWearable* wearable = NULL; // NULL indicates failure + LLAvatarAppearance *avatarp = data->mAvatarp; if( !filename ) { LL_WARNS("Wearable") << "Bad Wearable Asset: missing file." << LL_ENDL; } + else if(!avatarp) + { + LL_WARNS("Wearable") << "Bad asset request: missing avatar pointer." << LL_ENDL; + } else if (status >= 0) { // read the file - LLFILE* fp = LLFile::fopen(std::string(filename), "rb"); /*Flawfinder: ignore*/ - if( !fp ) + llifstream ifs(filename, llifstream::binary); + if( !ifs.is_open() ) { LL_WARNS("Wearable") << "Bad Wearable Asset: unable to open file: '" << filename << "'" << LL_ENDL; } else { - wearable = new LLWearable(uuid); - bool res = wearable->importFile( fp ); - if (!res) + wearable = new LLViewerWearable(uuid); + LLWearable::EImportResult result = wearable->importStream( + ifs, avatarp ); + if (LLWearable::SUCCESS != result) { if (wearable->getType() == LLWearableType::WT_COUNT) { @@ -123,9 +132,12 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID wearable = NULL; } - fclose( fp ); if(filename) { + if (ifs.is_open()) + { + ifs.close(); + } LLFile::remove(std::string(filename)); } } @@ -203,11 +215,11 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID } -LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name) +LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearable, const std::string& new_name) { lldebugs << "LLWearableList::createCopy()" << llendl; - LLWearable *wearable = generateNewWearable(); + LLViewerWearable *wearable = generateNewWearable(); wearable->copyDataFrom(old_wearable); LLPermissions perm(old_wearable->getPermissions()); @@ -222,12 +234,12 @@ LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std return wearable; } -LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) +LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type, LLAvatarAppearance *avatarp ) { lldebugs << "LLWearableList::createNewWearable()" << llendl; - LLWearable *wearable = generateNewWearable(); - wearable->setType( type ); + LLViewerWearable *wearable = generateNewWearable(); + wearable->setType( type, avatarp ); std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) ); wearable->setName( name ); @@ -237,6 +249,8 @@ LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); wearable->setPermissions(perm); + wearable->setDefinitionVersion(LLWearable::getCurrentDefinitionVersion()); + // Description and sale info have default values. wearable->setParamsToDefaults(); wearable->setTexturesToDefaults(); @@ -251,13 +265,13 @@ LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) return wearable; } -LLWearable *LLWearableList::generateNewWearable() +LLViewerWearable *LLWearableList::generateNewWearable() { LLTransactionID tid; tid.generate(); LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - LLWearable* wearable = new LLWearable(tid); + LLViewerWearable* wearable = new LLViewerWearable(tid); mList[new_asset_id] = wearable; return wearable; } diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index 12d0037aee..d6f0fd09a6 100755 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -28,7 +28,7 @@ #define LL_LLWEARABLELIST_H #include "llmemory.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "lluuid.h" #include "llassetstorage.h" @@ -50,20 +50,21 @@ public: void getAsset(const LLAssetID& assetID, const std::string& wearable_name, + LLAvatarAppearance *avatarp, LLAssetType::EType asset_type, - void(*asset_arrived_callback)(LLWearable*, void* userdata), + void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata); - LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string()); - LLWearable* createNewWearable(LLWearableType::EType type); + LLViewerWearable* createCopy(const LLViewerWearable* old_wearable, const std::string& new_name = std::string()); + LLViewerWearable* createNewWearable(LLWearableType::EType type, LLAvatarAppearance *avatarp); // Callback static void processGetAssetReply(const char* filename, const LLAssetID& assetID, void* user_data, S32 status, LLExtStat ext_status); protected: - LLWearable* generateNewWearable(); // used for the create... functions + LLViewerWearable* generateNewWearable(); // used for the create... functions private: - std::map<LLUUID, LLWearable*> mList; + std::map<LLUUID, LLViewerWearable*> mList; }; #endif // LL_LLWEARABLELIST_H diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp index 43b1a320c3..3a80051b9b 100755 --- a/indra/newview/llwebsharing.cpp +++ b/indra/newview/llwebsharing.cpp @@ -68,9 +68,9 @@ public: } } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("WebSharing") << "Error [" << status << "]: " << reason << LL_ENDL; + LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; } virtual void result(const LLSD& content) @@ -99,7 +99,7 @@ public: /// Left empty to override the default LLSD parsing behaviour. } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { if (HTTP_UNAUTHORIZED == status) { @@ -108,7 +108,7 @@ public: } else { - LL_WARNS("WebSharing") << "Error [" << status << "]: " << reason << LL_ENDL; + LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } @@ -152,9 +152,9 @@ public: } } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("WebSharing") << "Error [" << status << "]: " << reason << LL_ENDL; + LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } @@ -221,9 +221,9 @@ public: } } - virtual void error(U32 status, const std::string& reason) + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_WARNS("WebSharing") << "Error [" << status << "]: " << reason << LL_ENDL; + LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; } virtual void result(const LLSD& content) diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index be3e3ff30e..93eba5b604 100755 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -121,9 +121,11 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); } -/*virtual*/ void LLEnvironmentRequestResponder::error(U32 status, const std::string& reason) +/*virtual*/ +void LLEnvironmentRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - LL_INFOS("WindlightCaps") << "Got an error, not using region windlight..." << LL_ENDL; + LL_INFOS("WindlightCaps") << "Got an error, not using region windlight... [status:" + << status << "]: " << content << LL_ENDL; LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD()); } @@ -190,14 +192,15 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); } } -/*virtual*/ void LLEnvironmentApplyResponder::error(U32 status, const std::string& reason) +/*virtual*/ +void LLEnvironmentApplyResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { - std::stringstream msg; - msg << reason << " (Code " << status << ")"; - - LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! Reason: " << msg << LL_ENDL; + LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! [status:" + << status << "]: " << content << LL_ENDL; LLSD args(LLSD::emptyMap()); + std::stringstream msg; + msg << reason << " (Code " << status << ")"; args["FAIL_REASON"] = msg.str(); LLNotificationsUtil::add("WLRegionApplyFail", args); } diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h index 23558876da..598ce6d52a 100755 --- a/indra/newview/llwlhandlers.h +++ b/indra/newview/llwlhandlers.h @@ -47,7 +47,7 @@ class LLEnvironmentRequestResponder: public LLHTTPClient::Responder LOG_CLASS(LLEnvironmentRequestResponder); public: virtual void result(const LLSD& content); - virtual void error(U32 status, const std::string& reason); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); private: friend class LLEnvironmentRequest; @@ -89,7 +89,8 @@ public: */ virtual void result(const LLSD& content); - virtual void error(U32 status, const std::string& reason); // non-200 errors only + // non-200 errors only + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); private: friend class LLEnvironmentApply; diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 350ba39b45..5fa380e0e3 100755 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -34,6 +34,7 @@ #include "lluistring.h" #include "llviewertexturelist.h" #include "lltrans.h" +#include "llgltexture.h" // Timers to temporise database requests const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region @@ -78,7 +79,7 @@ void LLSimInfo::setLandForSaleImage (LLUUID image_id) // Fetch the image if (mMapImageID.notNull()) { - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); } else @@ -92,13 +93,13 @@ LLPointer<LLViewerFetchedTexture> LLSimInfo::getLandForSaleImage () if (mOverlayImage.isNull() && mMapImageID.notNull()) { // Fetch the image if it hasn't been done yet (unlikely but...) - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); } if (!mOverlayImage.isNull()) { // Boost the fetch level when we try to access that image - mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP); + mOverlayImage->setBoostLevel(LLGLTexture::BOOST_MAP); } return mOverlayImage; } diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 73530b9694..d514b2f14c 100755 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -36,6 +36,7 @@ #include "llsingleton.h" #include "llviewerregion.h" #include "llviewertexture.h" +#include "llgltexture.h" // Description of objects like hubs, events, land for sale, people and more (TBD). // Note: we don't store a "type" in there so we need to store instances of this class in diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 11b2770ec0..1940cf541e 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -421,7 +421,7 @@ void LLWorldMapView::draw() { // Inform the fetch mechanism of the size we need S32 draw_size = llround(sMapScale); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + overlayimage->setKnownDrawSize(llround(draw_size * LLUI::getScaleFactor().mV[VX]), llround(draw_size * LLUI::getScaleFactor().mV[VY])); // Draw something whenever we have enough info if (overlayimage->hasGLTexture()) { @@ -1317,7 +1317,7 @@ void LLWorldMapView::drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); - gGL.translatef((F32)x * LLUI::sGLScaleFactor.mV[VX], (F32)y * LLUI::sGLScaleFactor.mV[VY], 0.f); + gGL.translatef((F32)x * LLUI::getScaleFactor().mV[VX], (F32)y * LLUI::getScaleFactor().mV[VY], 0.f); gl_washer_segment_2d(inner_radius, outer_radius, start_theta, end_theta, 40, color, color); gGL.popMatrix(); diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 74ed844376..895ccaef5a 100755 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -74,21 +74,21 @@ void LLWorldMipmap::equalizeBoostLevels() { LLPointer<LLViewerFetchedTexture> img = iter->second; S32 current_boost_level = img->getBoostLevel(); - if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high - img->setBoostLevel(LLViewerTexture::BOOST_MAP); + img->setBoostLevel(LLGLTexture::BOOST_MAP); } else { // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw // so we drop its boost level to BOOST_NONE. - img->setBoostLevel(LLViewerTexture::BOOST_NONE); + img->setBoostLevel(LLGLTexture::BOOST_NONE); } #if DEBUG_TILES_STAT // Increment some stats if compile option on nb_tiles++; - if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { nb_visible++; } @@ -115,7 +115,7 @@ void LLWorldMipmap::dropBoostLevels() for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { LLPointer<LLViewerFetchedTexture> img = iter->second; - img->setBoostLevel(LLViewerTexture::BOOST_NONE); + img->setBoostLevel(LLGLTexture::BOOST_NONE); } } } @@ -172,7 +172,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 // Boost the tile level so to mark it's in use *if* load on if (load) { - img->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); + img->setBoostLevel(LLGLTexture::BOOST_MAP_VISIBLE); } return img; } @@ -189,8 +189,8 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - img->setBoostLevel(LLViewerTexture::BOOST_MAP); + LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + img->setBoostLevel(LLGLTexture::BOOST_MAP); // Return the smart pointer return img; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9f0e2906d0..f320f34f6e 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -71,6 +71,7 @@ #include "llhudtext.h" #include "lllightconstants.h" #include "llmeshrepository.h" +#include "llpipelinelistener.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llsky.h" @@ -377,6 +378,8 @@ BOOL LLPipeline::sMemAllocationThrottled = FALSE; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; +// EventHost API LLPipeline listener. +static LLPipelineListener sPipelineListener; static LLCullResult* sCull = NULL; @@ -491,19 +494,29 @@ void LLPipeline::init() LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) { - mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + clearAllRenderDebugFeatures(); } + else + { + setAllRenderDebugFeatures(); // By default, all debugging features on + } + clearAllRenderDebugDisplays(); // All debug displays off - mRenderDebugFeatureMask = 0xffffffff; // All debugging features on - mRenderDebugMask = 0; // All debug starts off - - // Don't turn on ground when this is set - // Mac Books with intel 950s need this - if(!gSavedSettings.getBOOL("RenderGround")) + if (gSavedSettings.getBOOL("DisableAllRenderTypes")) + { + clearAllRenderTypes(); + } + else { - toggleRenderType(RENDER_TYPE_GROUND); + setAllRenderTypes(); // By default, all rendering types start enabled + // Don't turn on ground when this is set + // Mac Books with intel 950s need this + if(!gSavedSettings.getBOOL("RenderGround")) + { + toggleRenderType(RENDER_TYPE_GROUND); + } } // make sure RenderPerformanceTest persists (hackity hack hack) @@ -5917,7 +5930,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (light->isLightSpotlight() // directional (spot-)light && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on { - LLVector3 spotparams = light->getSpotLightParams(); LLQuaternion quat = light->getRenderRotation(); LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction at_axis *= quat; @@ -6448,6 +6460,22 @@ void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value) } } +void LLPipeline::pushRenderDebugFeatureMask() +{ + mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); +} + +void LLPipeline::popRenderDebugFeatureMask() +{ + if (mRenderDebugFeatureStack.empty()) + { + llerrs << "Depleted render feature stack." << llendl; + } + + mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); + mRenderDebugFeatureStack.pop(); +} + // static void LLPipeline::setRenderScriptedBeacons(BOOL val) { @@ -9081,9 +9109,6 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector 3,7 }; - LLVector3 center = (max+min)*0.5f; - LLVector3 size = (max-min)*0.5f; - for (U32 i = 0; i < 12; i++) { for (U32 j = 0; j < 6; ++j) @@ -9309,7 +9334,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]); //currently used for amount to extrude frusta corners for constructing shadow frusta - LLVector3 n = RenderShadowNearDist; + //LLVector3 n = RenderShadowNearDist; //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; //put together a universal "near clip" plane for shadow frusta @@ -10414,6 +10439,22 @@ void LLPipeline::clearRenderTypeMask(U32 type, ...) } } +void LLPipeline::setAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; + } +} + +void LLPipeline::clearAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = FALSE; + } +} + void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color) { DebugBlip blip(position, color); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 36abeca295..a8db93585e 100755 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -324,20 +324,28 @@ public: BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; } - - + void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } + void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } + void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffff; } + void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } BOOL hasRenderType(const U32 type) const; BOOL hasAnyRenderType(const U32 type, ...) const; void setRenderTypeMask(U32 type, ...); - void orRenderTypeMask(U32 type, ...); + // This is equivalent to 'setRenderTypeMask' + //void orRenderTypeMask(U32 type, ...); void andRenderTypeMask(U32 type, ...); void clearRenderTypeMask(U32 type, ...); + void setAllRenderTypes(); + void clearAllRenderTypes(); void pushRenderTypeMask(); void popRenderTypeMask(); + void pushRenderDebugFeatureMask(); + void popRenderDebugFeatureMask(); + static void toggleRenderType(U32 type); // For UI control of render features @@ -634,6 +642,7 @@ protected: U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; + std::stack<U32> mRenderDebugFeatureStack; U32 mOldRenderDebugMask; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index df75f3f697..471a896019 100755 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -135,8 +135,8 @@ TOOLNO CURSOR "llno.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,1,1,0 - PRODUCTVERSION 2,1,1,0 + FILEVERSION 3,4,1,264760 + PRODUCTVERSION 3,4,1,264760 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -153,12 +153,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.1.1.0" + VALUE "FileVersion", "3.4.1.264760" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright � 2001-2010, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.1.1.0" + VALUE "ProductVersion", "3.4.1.264760" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 93c9cb02cb..fcab966dee 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -724,9 +724,6 @@ with the same filename but different name <texture name="icon_for_sale.tga" file_name="icons/Icon_For_Sale.png" /> <texture name="icon_top_pick.tga" /> - <texture name="inv_folder_mesh.tga"/> - <texture name="inv_item_mesh.tga"/> - <texture name="lag_status_critical.tga" /> <texture name="lag_status_good.tga" /> <texture name="lag_status_warning.tga" /> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index d8b085063f..2152a9f6e9 100755 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -42,58 +42,55 @@ <floater.string name="multiple_participants_added" value="[NAME] were invited to the conversation."/> - <floater.string + <floater.string name="tooltip_to_separate_window" value="Move this conversation to a separate window"/> - <floater.string + <floater.string name="tooltip_to_main_window" value="Move this conversation back to main window"/> - <floater.string + <floater.string name="start_call_button_tooltip" value="Open voice connection"/> - <floater.string + <floater.string name="end_call_button_tooltip" value="Close voice connection"/> - <floater.string + <floater.string name="expcol_button_not_tearoff_tooltip" value="Collapse this pane"/> - <floater.string + <floater.string name="expcol_button_tearoff_and_expanded_tooltip" value="Collapse participant list"/> - <floater.string + <floater.string name="expcol_button_tearoff_and_collapsed_tooltip" value="Expand participant list"/> <view - follows="all" - layout="topleft" - name="contents_view" - top="0" - left="0" - height="355" - width="394"> - <layout_stack - animate="false" - default_tab_group="2" - follows="all" - height="355" - width="394" - layout="topleft" - orientation="vertical" - name="main_stack" - tab_group="1" - top="0" - left="0"> - - <layout_panel - follows="left|top|right" - layout="topleft" - name="toolbar_panel" + follows="all" + layout="topleft" + name="contents_view" + top="0" + left="0" + right="-1" + bottom="-3"> + <layout_stack + animate="false" + default_tab_group="2" + follows="all" + right="-5" + bottom="-1" top="0" - left="0" - height="35" - min_height="35" - width="394"> - <menu_button + left="5" + border_size="0" + layout="topleft" + orientation="vertical" + name="main_stack" + tab_group="1"> + <layout_panel + auto_resize="false" + name="toolbar_panel" + height="35" + right="-1" + left="1"> + <menu_button menu_filename="menu_im_session_showmodes.xml" follows="top|left" height="25" @@ -107,22 +104,22 @@ tool_tip="View/sort options" top="5" width="31" /> - <menu_button - menu_filename="menu_im_conversation.xml" - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_pad="2" - name="gear_btn" - visible="false" - tool_tip="Actions on selected person" - width="31"/> - <button + <menu_button + menu_filename="menu_im_conversation.xml" + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="2" + name="gear_btn" + visible="false" + tool_tip="Actions on selected person" + width="31"/> + <button enabled="false" follows="top|left" height="25" @@ -136,7 +133,7 @@ name="add_btn" tool_tip="Add someone to this conversation" width="31"/> - <button + <button follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -149,19 +146,19 @@ name="voice_call_btn" tool_tip="Open voice connection" width="31"/> - <output_monitor - auto_update="true" - follows="top|left" - draw_border="false" - height="16" - layout="topleft" - top="10" - left_pad="10" - mouse_opaque="true" - name="speaking_indicator" - visible="false" - width="20" /> - <button + <output_monitor + auto_update="true" + follows="top|left" + draw_border="false" + height="16" + layout="topleft" + top="10" + left_pad="10" + mouse_opaque="true" + name="speaking_indicator" + visible="false" + width="20" /> + <button follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -170,232 +167,170 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left="292" + right="-67" name="close_btn" tool_tip="End this conversation" width="31" /> - <button + <button follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" image_overlay="Conv_toolbar_collapse" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" left_pad="2" name="expand_collapse_btn" tool_tip="Collapse/Expand this pane" width="31" /> - <button + <button follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" image_overlay="Conv_toolbar_arrow_ne" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" - top="5" left_pad="2" name="tear_off_btn" + top="5" width="31" /> - </layout_panel> - <layout_panel - name="body_panel" - follows="all" - width="394" - height="235" - user_resize="false" - auto_resize="true"> - <layout_stack - animate="true" - default_tab_group="2" - follows="all" - height="275" - width="394" - layout="topleft" - orientation="horizontal" - name="im_panels" - tab_group="1" - top_pad="0" - left="0"> - <layout_panel - name="speakers_list_panel" - follows="all" - expanded_min_dim="115" - min_dim="0" - width="150" - height="275" - user_resize="true" - auto_resize="false"> - </layout_panel> - <layout_panel - default_tab_group="3" - left="0" - tab_group="2" - follows="all" - top="0" - height="275" - width="244" - layout="topleft" - user_resize="true" - auto_resize="true" - visible="true" - name="right_part_holder" - min_width="221"> - <panel - name="trnsAndChat_panel" - follows="all" - layout="topleft" - visible="true" - height="240" - width="244"> - <layout_stack - animate="true" - default_tab_group="2" - follows="all" - height="240" - width="244" - layout="topleft" - visible="true" - orientation="vertical" - name="translate_and_chat_stack" - tab_group="1" - left_pad="0" - top="0" - left="0"> - <layout_panel - auto_resize="false" - user_resize="false" - height="26" - layout="topleft" - left_delta="0" - name="translate_chat_checkbox_lp" - top_delta="0" - visible="true" - width="210"> - <check_box - top="10" - control_name="TranslateChat" - enabled="true" - height="16" - label="Translate chat" - layout="topleft" - left="5" - name="translate_chat_checkbox" - width="230" /> </layout_panel> <layout_panel - width="210" - layout="topleft" - follows="all" - left_delta="0" - top_delta="0" - bottom="0" - visible="true" - user_resize="false" - auto_resize="true" - name="chat_holder"> - <chat_history - font="SansSerifSmall" - follows="all" - visible="true" - name="chat_history" - parse_highlights="true" - parse_urls="true" - layout="topleft" - right="-5" - left="5" - top="0" - bottom="1"> - </chat_history> + name="body_panel" + top="1" + bottom="-1"> + <layout_stack + default_tab_group="2" + follows="all" + orientation="horizontal" + name="im_panels" + tab_group="1" + top="0" + right="-1" + bottom="-1" + left="0"> + <layout_panel + name="speakers_list_panel" + expanded_min_dim="115" + min_dim="0" + width="150" + user_resize="true" + auto_resize="false" + bottom="-1" /> + <layout_panel + default_tab_group="3" + tab_group="2" + name="right_part_holder" + min_width="221" + bottom="-1"> + <layout_stack + animate="true" + default_tab_group="2" + follows="all" + orientation="vertical" + name="translate_and_chat_stack" + tab_group="1" + top="0" + left="0" + right="-1" + bottom="-1"> + <layout_panel + auto_resize="false" + height="26" + name="translate_chat_checkbox_lp"> + <check_box + top="10" + control_name="TranslateChat" + enabled="true" + height="16" + label="Translate chat" + left="5" + name="translate_chat_checkbox" + width="230" /> + </layout_panel> + <layout_panel + name="chat_holder"> + <chat_history + font="SansSerifSmall" + follows="all" + name="chat_history" + parse_highlights="true" + parse_urls="true" + right="-1" + left="5" + top="0" + bottom="-1" /> + </layout_panel> + </layout_stack> + </layout_panel> + </layout_stack> </layout_panel> - </layout_stack> - </panel> - </layout_panel> - </layout_stack> - </layout_panel> - <layout_panel - height="35" - layout="topleft" - follows="left|right|bottom" - left_delta="0" - right="0" + <layout_panel top_delta="0" - bottom="0" - visible="true" - user_resize="false" + top="0" + height="26" + bottom="-1" auto_resize="false" name="chat_layout_panel"> - <layout_stack - animate="true" - default_tab_group="2" - follows="all" - height="35" - right="0" - layout="topleft" - orientation="horizontal" - name="input_panels" - top_pad="0" - left="0"> - <layout_panel - height="35" - layout="topleft" - follows="left|right|bottom" - left_delta="0" - top_delta="0" - bottom="0" - visible="true" - user_resize="false" - auto_resize="true" - name="input_editor_layout_panel"> - <chat_editor - expand_lines_count="5" - follows="left|right|bottom" - font="SansSerifSmall" - visible="true" - height="20" - is_expandable="true" - label="To" - text_tentative_color="TextFgTentativeColor" - layout="topleft" - name="chat_editor" - max_length="1023" - spellcheck="true" - tab_group="3" - width="160" - top="6" - left="5" - right="-5" - wrap="true"> - </chat_editor> + <layout_stack + animate="false" + default_tab_group="2" + follows="all" + orientation="horizontal" + name="input_panels" + top="0" + bottom="-2" + left="0" + right="-1"> + <layout_panel + name="input_editor_layout_panel" + auto_resize="true" + user_resize="false" + top="0" + bottom="-1"> + <chat_editor + layout="topleft" + expand_lines_count="5" + follows="left|right|bottom" + font="SansSerifSmall" + height="20" + is_expandable="true" + text_tentative_color="TextFgTentativeColor" + name="chat_editor" + max_length="1023" + spellcheck="true" + tab_group="3" + top="1" + bottom="-2" + left="4" + right="-4" + wrap="true" /> + </layout_panel> + <layout_panel + auto_resize="false" + user_resize="false" + name="input_button_layout_panel" + width="30" + top="0" + bottom="-1"> + <button + layout="topleft" + left="1" + right="-1" + top="1" + height="22" + follows="left|right|top" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_expand_one_line" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + name="minz_btn" + tool_tip="Shows/hides message panel" /> + </layout_panel> + </layout_stack> </layout_panel> - <layout_panel - height="35" - layout="topleft" - follows="left|right|bottom" - left_delta="0" - top_delta="0" - bottom="0" - width="35" - visible="true" - user_resize="false" - auto_resize="false" - name="input_button_layout_panel"> - <button - follows="left|right|bottom" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_expand_one_line" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - name="minz_btn" - tool_tip="Shows/hides message panel" - width="28"/> - </layout_panel> - </layout_stack> - </layout_panel> - </layout_stack> + </layout_stack> </view> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index b46b62ec4d..46ba4bd29d 100755 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -79,6 +79,14 @@ <menu_item_call.on_visible function="IsGodCustomerService"/> </menu_item_call> + <menu_item_call + label="Dump XML" + name="Dump XML"> + <menu_item_call.on_click + function="Advanced.AppearanceToXML" /> + <menu_item_call.on_visible + function="Advanced.EnableAppearanceToXML"/> + </menu_item_call> <menu_item_call label="Zoom In" name="Zoom In"> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index b8128da358..28e032ce5f 100755 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -123,6 +123,14 @@ name="Edit Outfit"> <menu_item_call.on_visible function="IsGodCustomerService"/> </menu_item_call> + <menu_item_call + label="Dump XML" + name="Dump XML"> + <menu_item_call.on_click + function="Advanced.AppearanceToXML" /> + <menu_item_call.on_visible + function="Advanced.EnableAppearanceToXML"/> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index 276b5f106f..e7c2b80da2 100755 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -79,6 +79,14 @@ <menu_item_call.on_visible function="IsGodCustomerService"/> </menu_item_call> + <menu_item_call + label="Dump XML" + name="Dump XML"> + <menu_item_call.on_click + function="Advanced.AppearanceToXML" /> + <menu_item_call.on_visible + function="Advanced.EnableAppearanceToXML"/> + </menu_item_call> <menu_item_call label="Zoom In" name="Zoom In"> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml index d9bdfece38..c1ff026a74 100755 --- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -261,4 +261,12 @@ <menu_item_call.on_visible function="IsGodCustomerService"/> </menu_item_call> + <menu_item_call + label="Dump XML" + name="Dump XML"> + <menu_item_call.on_click + function="Advanced.AppearanceToXML" /> + <menu_item_call.on_visible + function="Advanced.EnableAppearanceToXML"/> + </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 101e104eab..52c4fb1613 100755 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -180,7 +180,8 @@ name="Set Logging Level" tear_off="true"> <menu_item_check - label="Debug"> + name="Debug" + label="Debug"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" parameter="0" /> @@ -189,7 +190,8 @@ parameter="0" /> </menu_item_check> <menu_item_check - label="Info"> + name="Info" + label="Info"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" parameter="1" /> @@ -198,7 +200,8 @@ parameter="1" /> </menu_item_check> <menu_item_check - label="Warning"> + name="Warning" + label="Warning"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" parameter="2" /> @@ -207,7 +210,8 @@ parameter="2" /> </menu_item_check> <menu_item_check - label="Error"> + name="Error" + label="Error"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" parameter="3" /> @@ -216,7 +220,8 @@ parameter="3" /> </menu_item_check> <menu_item_check - label="None"> + name="None" + label="None"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" parameter="4" /> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 544f06ac0c..a11cd13fdb 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -131,6 +131,7 @@ name="Status" tear_off="true"> <menu_item_check + name="Away" label="Away"> <menu_item_check.on_check function="View.Status.CheckAway" /> @@ -138,6 +139,7 @@ function="World.SetAway" /> </menu_item_check> <menu_item_check + name="Do Not Disturb" label="Do Not Disturb"> <menu_item_check.on_check function="View.Status.CheckDoNotDisturb" /> @@ -257,6 +259,7 @@ parameter="speak" /> </menu_item_check> <menu_item_check + name="Conversation Log..." label="Conversation Log..."> <menu_item_check.on_check function="Floater.Visible" @@ -352,6 +355,7 @@ </menu_item_call> <menu_item_separator/> <menu_item_check + name="Do Not Disturb" label="Do Not Disturb"> <menu_item_check.on_check function="View.Status.CheckDoNotDisturb" /> @@ -3051,13 +3055,6 @@ <menu_item_call.on_click function="Advanced.PrintAgentInfo" /> </menu_item_call> - <menu_item_call - label="Memory Stats" - name="Memory Stats" - shortcut="control|alt|shift|M"> - <menu_item_call.on_click - function="Advanced.PrintTextureMemoryStats" /> - </menu_item_call> <menu_item_check label="Region Debug Console" name="Region Debug Console" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c681e39002..105bef7321 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -352,7 +352,7 @@ Save all changes to clothing/body parts? icon="alertmodal.tga" name="FriendsAndGroupsOnly" type="alertmodal"> - Non-friends won't know that you've choosen to ignore their calls and instant messages. + Non-friends won't know that you've chosen to ignore their calls and instant messages. <usetemplate name="okbutton" yestext="OK"/> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 5aa743b32d..7c08aef65e 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2987,6 +2987,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Higher">Higher</string> <string name="Hip Length">Hip Length</string> <string name="Hip Width">Hip Width</string> +<string name="Hover">Hover</string> <string name="In">In</string> <string name="In Shdw Color">Inner Shadow Color</string> <string name="In Shdw Opacity">Inner Shadow Opacity</string> diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index 0254c5881f..41cb344808 100755 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -126,7 +126,9 @@ void LLHTTPClient::post( result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY]; if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 ) { - responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason"); + LLSD content; + content["reason"] = "fake reason"; + responder->errorWithContent(HTTP_SERVICE_UNAVAILABLE, "fake reason", content); return; } else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index f8923b9868..a331d9aa9e 100755 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -37,30 +37,6 @@ #include "llregionhandle.h" #include "../llvoavatar.h" -void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) -{ - counts.resize(3); - counts[0] = 0; - counts[1] = 0; - counts[2] = 1; -} - -// static -std::string LLVOAvatar::rezStatusToString(S32 rez_status) -{ - if (rez_status==0) return "cloud"; - if (rez_status==1) return "gray"; - if (rez_status==2) return "textured"; - return "unknown"; -} - -// static -LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) -{ - static LLViewerStats::StatsAccumulator junk; - return junk; -} - static const char * all_keys[] = { "duration", @@ -123,31 +99,34 @@ is_empty_map(const LLSD & sd) { return sd.isMap() && 0 == sd.size(); } +#endif +#if 0 static bool is_single_key_map(const LLSD & sd, const std::string & key) { return sd.isMap() && 1 == sd.size() && sd.has(key); } +#endif static bool is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2) { return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2); } -#endif +#if 0 static bool is_triple_key_map(const LLSD & sd, const std::string & key1, const std::string & key2, const std::string& key3) { return sd.isMap() && 3 == sd.size() && sd.has(key1) && sd.has(key2) && sd.has(key3); } - +#endif static bool is_no_stats_map(const LLSD & sd) { - return is_triple_key_map(sd, "duration", "regions", "avatar"); + return is_double_key_map(sd, "duration", "regions"); } static bool @@ -258,7 +237,7 @@ namespace tut // Once the region is set, we will get a response even with no data collection it->setRegion(region1_handle); sd_full = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd_full, "duration", "regions", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle)); LLSD sd = sd_full["regions"][0]; @@ -299,7 +278,7 @@ namespace tut it->setRegion(region1_handle); LLSD sd = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd[0]; @@ -324,7 +303,7 @@ namespace tut LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -364,7 +343,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -414,7 +393,7 @@ namespace tut // std::cout << sd << std::endl; - ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); + ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -437,7 +416,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = sd["regions"][0]; @@ -486,7 +465,7 @@ namespace tut LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); + ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -509,7 +488,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = get_region(sd, region2_handle); ensure("Region2 is present in results", sd2.isMap()); @@ -555,7 +534,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); + ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = get_region(sd, region1_handle); ensure("Region1 is present in results", sd.isMap()); diff --git a/indra/newview/tests/llviewertexture_stub.cpp b/indra/newview/tests/llviewertexture_stub.cpp new file mode 100644 index 0000000000..889ab9bea5 --- /dev/null +++ b/indra/newview/tests/llviewertexture_stub.cpp @@ -0,0 +1,34 @@ +/** + * @file llviewertexture_stub.cpp + * @brief stub class to allow unit testing + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../llviewertexture.h" +#include "../../llrender/llgltexture.h" + +void LLViewerTexture::setBoostLevel(int level) +{ +} + diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp index acc6e814bc..84194adb5d 100755 --- a/indra/newview/tests/llworldmap_test.cpp +++ b/indra/newview/tests/llworldmap_test.cpp @@ -47,9 +47,9 @@ // * A simulator for a class can be implemented here. Please comment and document thoroughly. // Stub image calls -void LLViewerTexture::setBoostLevel(S32 ) { } -void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, BOOL, LLViewerTexture::EBoostLevel, S8, +void LLGLTexture::setBoostLevel(S32 ) { } +void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { } +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, FTType, BOOL, LLGLTexture::EBoostLevel, S8, LLGLint, LLGLenum, LLHost ) { return NULL; } // Stub related map calls diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index e7ef017760..142d75bcfd 100755 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -42,8 +42,8 @@ // * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) // * A simulator for a class can be implemented here. Please comment and document thoroughly. -void LLViewerTexture::setBoostLevel(S32 ) { } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, BOOL, LLViewerTexture::EBoostLevel, S8, +void LLGLTexture::setBoostLevel(S32 ) { } +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, FTType, BOOL, LLGLTexture::EBoostLevel, S8, LLGLint, LLGLenum, const LLUUID& ) { return NULL; } LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e7108141ee..e2b914aae8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -367,10 +367,14 @@ class WindowsManifest(ViewerManifest): print err.message print "Skipping COLLADA and GLOD libraries (assumming linked statically)" - - # Get fmod dll, continue if missing - if not self.path("fmod.dll"): - print "Skipping fmod.dll" + # Get fmodex dll, continue if missing + try: + if self.args['configuration'].lower() == 'debug': + self.path("fmodexL.dll") + else: + self.path("fmodex.dll") + except: + print "Skipping fmodex audio library(assuming other audio engine)" # For textures if self.args['configuration'].lower() == 'debug': @@ -743,6 +747,7 @@ class DarwinManifest(ViewerManifest): "libcollada14dom.dylib", "libexpat.1.5.2.dylib", "libexception_handler.dylib", + "libfmodex.dylib", "libGLOD.dylib", ): dylibs += path_optional(os.path.join(libdir, libfile), libfile) @@ -757,11 +762,7 @@ class DarwinManifest(ViewerManifest): 'SLVoice', ): self.path2basename(libdir, libfile) - - # FMOD for sound - libfile = "libfmodwrapper.dylib" - path_optional(os.path.join(self.args['configuration'], libfile), libfile) - + # our apps for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"), ("mac_updater", "mac-updater.app"), @@ -1081,7 +1082,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libcrypto.so.*") self.path("libexpat.so.*") self.path("libssl.so.1.0.0") - self.path("libglod.so") + self.path("libGLOD.so") self.path("libminizip.so") self.path("libuuid.so*") self.path("libSDL-1.2.so.*") @@ -1122,11 +1123,13 @@ class Linux_i686Manifest(LinuxManifest): pass try: - self.path("libfmod-3.75.so") + self.path("libfmodex-*.so") + self.path("libfmodex.so") pass except: - print "Skipping libfmod-3.75.so - not found" + print "Skipping libfmodex.so - not found" pass + self.end_prefix("lib") # Vivox runtimes diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 816f1d7175..31e1d89c68 100755 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -28,6 +28,10 @@ include_directories( ${GOOGLEMOCK_INCLUDE_DIRS} ${TUT_INCLUDE_DIR} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(test_SOURCE_FILES io.cpp diff --git a/indra/test/io.cpp b/indra/test/io.cpp index ce747f667d..47a67deed0 100755 --- a/indra/test/io.cpp +++ b/indra/test/io.cpp @@ -1140,7 +1140,7 @@ namespace tut bool connected = client->blockingConnect(server_host); ensure("Connected to server", connected); lldebugs << "connected" << llendl; - F32 elapsed = pump_loop(mPump,0.1f); + pump_loop(mPump,0.1f); count = mPump->runningChains(); ensure_equals("server chain onboard", count, 2); lldebugs << "** Client is connected." << llendl; @@ -1156,20 +1156,20 @@ namespace tut chain.clear(); // pump for a bit and make sure all 3 chains are running - elapsed = pump_loop(mPump,0.1f); + pump_loop(mPump,0.1f); count = mPump->runningChains(); ensure_equals("client chain onboard", count, 3); lldebugs << "** request should have been sent." << llendl; // pump for long enough the the client socket closes, and the // server socket should not be closed yet. - elapsed = pump_loop(mPump,0.2f); + pump_loop(mPump,0.2f); count = mPump->runningChains(); ensure_equals("client chain timed out ", count, 2); lldebugs << "** client chain should be closed." << llendl; // At this point, the socket should be closed by the timeout - elapsed = pump_loop(mPump,1.0f); + pump_loop(mPump,1.0f); count = mPump->runningChains(); ensure_equals("accepted socked close", count, 1); lldebugs << "** Sleeper should have timed out.." << llendl; diff --git a/indra/test/llpermissions_tut.cpp b/indra/test/llpermissions_tut.cpp index bf6766424c..bc2c87ba46 100755 --- a/indra/test/llpermissions_tut.cpp +++ b/indra/test/llpermissions_tut.cpp @@ -407,7 +407,7 @@ namespace tut LLFILE* fp = LLFile::fopen("linden_file.dat","w+"); if(!fp) { - llerrs << "file coudnt be opened\n" << llendl; + llerrs << "file couldn't be opened\n" << llendl; return; } LLPermissions perm,perm1; @@ -425,15 +425,15 @@ namespace tut perm.initMasks(base, ownerp, everyone, groupp, next); - perm.exportFile(fp); + ensure("Permissions export failed", perm.exportFile(fp)); fclose(fp); fp = LLFile::fopen("linden_file.dat","r+"); if(!fp) { - llerrs << "file coudnt be opened\n" << llendl; + llerrs << "file couldn't be opened\n" << llendl; return; } - perm1.importFile(fp); + ensure("Permissions import failed", perm1.importFile(fp)); fclose(fp); ensure_equals("exportFile()/importFile():failed to export and import the data ", perm1, perm); } @@ -461,7 +461,7 @@ namespace tut std::istringstream istream(ostream.str()); perm1.importLegacyStream(istream); - ensure_equals("exportLegacyStream()/importLegacyStream():failed to export and import the data ", perm1, perm); + ensure_equals("exportStream()/importStream():failed to export and import the data ", perm1, perm); } template<> template<> diff --git a/indra/test/llsaleinfo_tut.cpp b/indra/test/llsaleinfo_tut.cpp index 09fca2abba..2689eaa15e 100755 --- a/indra/test/llsaleinfo_tut.cpp +++ b/indra/test/llsaleinfo_tut.cpp @@ -154,8 +154,9 @@ namespace tut BOOL has_perm_mask = FALSE; llsaleinfo1.importLegacyStream(istream, has_perm_mask, perm_mask); - ensure("importLegacyStream() fn failed ", llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice() && - llsaleinfo.getSaleType() == llsaleinfo1.getSaleType()); + ensure("importStream() fn failed ", + llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice() && + llsaleinfo.getSaleType() == llsaleinfo1.getSaleType()); } template<> template<> diff --git a/indra/test/llstreamtools_tut.cpp b/indra/test/llstreamtools_tut.cpp index a93f2e8f65..0f6436f0f4 100755 --- a/indra/test/llstreamtools_tut.cpp +++ b/indra/test/llstreamtools_tut.cpp @@ -385,16 +385,15 @@ namespace tut std::string expected_result; std::string actual_result; std::istringstream is; - bool ret; is.clear(); is.str(str = " First Second \t \r \n Third Fourth-ShouldThisBePartOfFourth Fifth\n"); actual_result = ""; - ret = get_word(actual_result, is); // First + get_word(actual_result, is); // First actual_result = ""; - ret = get_word(actual_result, is); // Second + get_word(actual_result, is); // Second actual_result = ""; - ret = get_word(actual_result, is); // Third + get_word(actual_result, is); // Third // the current implementation of get_word seems inconsistent with // skip_to_next_word. skip_to_next_word treats any character other @@ -403,22 +402,22 @@ namespace tut // carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v') // as delimiters actual_result = ""; - ret = get_word(actual_result, is); // will copy Fourth-ShouldThisBePartOfFourth + get_word(actual_result, is); // will copy Fourth-ShouldThisBePartOfFourth actual_result = ""; - ret = get_word(actual_result, is); // will copy Fifth + get_word(actual_result, is); // will copy Fifth is.clear(); is.str(str = " First Second \t \r \n Third Fourth_ShouldThisBePartOfFourth Fifth\n"); - ret = skip_to_next_word(is); // should now point to First - ret = skip_to_next_word(is); // should now point to Second - ret = skip_to_next_word(is); // should now point to Third - ret = skip_to_next_word(is); // should now point to Fourth - ret = skip_to_next_word(is); // should now point to ShouldThisBePartOfFourth + skip_to_next_word(is); // should now point to First + skip_to_next_word(is); // should now point to Second + skip_to_next_word(is); // should now point to Third + skip_to_next_word(is); // should now point to Fourth + skip_to_next_word(is); // should now point to ShouldThisBePartOfFourth expected_result = ""; // will copy ShouldThisBePartOfFourth, the fifth word, // while using get_word above five times result in getting "Fifth" - ret = get_word(expected_result, is); + get_word(expected_result, is); ensure_equals("get_word: skip_to_next_word compatibility", actual_result, expected_result); } @@ -480,39 +479,38 @@ namespace tut std::string expected_result; std::string actual_result; std::istringstream is; - bool ret; is.clear(); is.str(str = "First Second \t \r\n Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n"); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "First Second \t \r\n"; ensure_equals("get_line: 1", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = " Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n"; ensure_equals("get_line: 2", actual_result, expected_result); is.clear(); is.str(str = "\nFirst Line.\n\nSecond Line.\n"); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "\n"; ensure_equals("get_line: First char as newline", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "First Line.\n"; ensure_equals("get_line: 3", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "\n"; ensure_equals("get_line: 4", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "Second Line.\n"; ensure_equals("get_line: 5", actual_result, expected_result); } @@ -544,13 +542,12 @@ namespace tut std::string expected_result; std::string actual_result; std::istringstream is; - bool ret; // need to be check if this test case is wrong or the implementation is wrong. is.clear(); is.str(str = "Should not skip lone \r.\r\n"); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "Should not skip lone \r.\r\n"; ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result); } @@ -563,12 +560,11 @@ namespace tut std::string expected_result; std::string actual_result; std::istringstream is; - bool ret; is.clear(); is.str(str = "\n"); actual_result = ""; - ret = get_line(actual_result, is); + get_line(actual_result, is); expected_result = "\n"; ensure_equals("get_line: Just newline", actual_result, expected_result); } @@ -582,36 +578,35 @@ namespace tut std::string expected_result; std::string actual_result; std::istringstream is; - bool ret; is.clear(); is.str(str = "First Line.\nSecond Line.\n"); actual_result = ""; - ret = get_line(actual_result, is, 255); + get_line(actual_result, is, 255); expected_result = "First Line.\n"; ensure_equals("get_line: Basic Operation", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is, sizeof("Second")-1); + get_line(actual_result, is, sizeof("Second")-1); expected_result = "Second\n"; ensure_equals("get_line: Insufficient length 1", actual_result, expected_result); actual_result = ""; - ret = get_line(actual_result, is, 255); + get_line(actual_result, is, 255); expected_result = " Line.\n"; ensure_equals("get_line: Remainder after earlier insufficient length", actual_result, expected_result); is.clear(); is.str(str = "One Line only with no newline with limited length"); actual_result = ""; - ret = get_line(actual_result, is, sizeof("One Line only with no newline with limited length")-1); + get_line(actual_result, is, sizeof("One Line only with no newline with limited length")-1); expected_result = "One Line only with no newline with limited length\n"; ensure_equals("get_line: No newline with limited length", actual_result, expected_result); is.clear(); is.str(str = "One Line only with no newline"); actual_result = ""; - ret = get_line(actual_result, is, 255); + get_line(actual_result, is, 255); expected_result = "One Line only with no newline"; ensure_equals("get_line: No newline", actual_result, expected_result); } diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp index 6e1c82bb24..6c0b70edd2 100755 --- a/indra/test/lltemplatemessagebuilder_tut.cpp +++ b/indra/test/lltemplatemessagebuilder_tut.cpp @@ -937,7 +937,7 @@ namespace tut // build message with single block LLMessageTemplate messageTemplate = defaultTemplate(); messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE)); - U32 outValue, outValue2, inValue = 0xbbbbbbbb; + U32 outValue, inValue = 0xbbbbbbbb; LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate); builder->addU32(_PREHASH_Test0, inValue); const U32 bufferSize = 1024; @@ -962,7 +962,6 @@ namespace tut memset(buffer, 0xcc, bufferSize); reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize, outBuffer); - outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1); ensure_equals("Ensure present value ", outValue, inValue); ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0); delete reader; diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt index 1211bb7e5a..8179be66f5 100755 --- a/indra/test_apps/llplugintest/CMakeLists.txt +++ b/indra/test_apps/llplugintest/CMakeLists.txt @@ -2,7 +2,7 @@ project(llplugintest) include(00-Common) -include(FindOpenGL) +include(OpenGL) include(LLCommon) include(LLPlugin) include(Linking) @@ -25,6 +25,9 @@ include_directories( ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) if (DARWIN) include(CMakeFindFrameworks) diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt index 7720619df3..658f167c2e 100755 --- a/indra/viewer_components/login/CMakeLists.txt +++ b/indra/viewer_components/login/CMakeLists.txt @@ -15,6 +15,10 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(login_SOURCE_FILES lllogin.cpp diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index ef82290b47..de7e336341 100755 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -20,6 +20,9 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) set(updater_service_SOURCE_FILES llupdaterservice.cpp diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 50633599ab..3c9a4b9756 100755 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -21,6 +21,10 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ) set(win_crash_logger_SOURCE_FILES win_crash_logger.cpp diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 2cb0a833d4..6702de9b4a 100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -2939,6 +2939,10 @@ version 2.0 PidStat Single { PID S32 } } + { + RegionInfo Variable + { RegionFlagsExtended U64 } + } } // viewer -> sim @@ -2991,6 +2995,10 @@ version 2.0 { HardMaxAgents U32 } { HardMaxObjects U32 } } + { + RegionInfo3 Variable + { RegionFlagsExtended U64 } + } } // GodUpdateRegionInfo @@ -3016,6 +3024,10 @@ version 2.0 { RedirectGridX S32 } { RedirectGridY S32 } } + { + RegionInfo2 Variable + { RegionFlagsExtended U64 } + } } //NearestLandingRegionRequest @@ -3116,6 +3128,11 @@ version 2.0 { ProductSKU Variable 1 } // string { ProductName Variable 1 } // string } + { + RegionInfo4 Variable + { RegionFlagsExtended U64 } + { RegionProtocols U64 } + } } // RegionHandshakeReply @@ -3571,6 +3588,12 @@ version 2.0 VisualParam Variable { ParamValue U8 } } + { + AppearanceData Variable + { AppearanceVersion U8 } + { CofVersion S32 } + { Flags U32 } + } } // AvatarSitResponse - response to a request to sit on an object diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 index 6486d92851..7a31177f11 100755 --- a/scripts/messages/message_template.msg.sha1 +++ b/scripts/messages/message_template.msg.sha1 @@ -1 +1 @@ -465164e1a07f63d68c4ad1f00c19805dfb6ee2d7
\ No newline at end of file +4dbf88396c3188ad4c54c4f847a7d8817793668d
\ No newline at end of file |