diff --git a/.hgtags b/.hgtags index d104ee312471d19354ff8277217c9ba7f666e804..1187586eb8229b6103941618a35c8dedc4b81dad 100644 --- a/.hgtags +++ b/.hgtags @@ -103,6 +103,10 @@ d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1 ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1 d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1 +0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2 +0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2 74cd32a06837b0c2cb793b2e8d4d82f5d49462b2 2.6.4-start 74cd32a06837b0c2cb793b2e8d4d82f5d49462b2 2.6.4-start f632f87bb71b0f13d21f2f64b0c42cedb008c749 2.6.4-start +800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start +ce588bc1ae8e3a90ee5e1f5de71a346886a9fd8b 2.6.7-start diff --git a/BuildParams b/BuildParams index 13ff697b6984ac9a2b5cae59b3c3f029578d3c82..2b374e133c78a763829ec0f9bab62b318dd3b20a 100644 --- a/BuildParams +++ b/BuildParams @@ -69,14 +69,13 @@ viewer-pre-release.viewer_channel = "Second Life Release" viewer-pre-release.login_channel = "Second Life Release" viewer-pre-release.build_debug_release_separately = true viewer-pre-release.build_viewer_update_version_manager = true -viewer-pre-release.release-viewer.jira = DRTVWR-42 #viewer-pre-release.release-viewer.jira = DRTVWR-13 viewer-pre-release.release-viewer.jira = DRTVWR-46 + # ======================================= # brad # ======================================== - debug-halting.email = cg@lindenlab.com debug-halting.build_server = false debug-halting.build_server_tests = false @@ -190,8 +189,10 @@ media.build_viewer_update_version_manager = false oz_viewer-devreview.build_debug_release_separately = true oz_project-1.build_debug_release_separately = true oz_project-2.build_debug_release_separately = true -oz_project-3.build_debug_release_separately = true +oz-project-3.build_debug_release_separately = true + +oz_viewer-beta-review.build_debug_release_separately = true # ======================================== # enus # ======================================== diff --git a/autobuild.xml b/autobuild.xml index f4e718916657ffee0a8d4ef91e37b49657aa67ee..04f789ef01f8d5f7cb621625efaea9d7f0a63f13 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1134,9 +1134,9 @@ <key>archive</key> <map> <key>hash</key> - <string>9f8579663eeac8ed5cfc6390560f0e24</string> + <string>95a1d483f3d01f480b55801e841b2151</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecomposition/rev/226714/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110415.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecomposition/rev/227989/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110428.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -1784,739 +1784,736 @@ </map> </map> </map> - <key>package_description</key> - <map> - <key>name</key> - <string>viewer_development</string> - <key>platforms</key> + <key>package_description</key> <map> - <key>common</key> + <key>name</key> + <string>viewer_development</string> + <key>platforms</key> <map> - <key>configurations</key> + <key>common</key> <map> - <key>Debug</key> - <map> - <key>build</key> - <map> - </map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=Debug</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> + <key>configurations</key> + <map> + <key>Debug</key> + <map> + <key>build</key> + <map> + </map> + <key>configure</key> + <map> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=Debug</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> <string>-DINSTALL_PROPRIETARY=TRUE</string> - </array> - </map> - <key>name</key> - <string>Debug</string> - </map> - <key>DebugOS</key> - <map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=Debug</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> - <string>-DINSTALL_PROPRIETARY=FALSE</string> - </array> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - </map> - <key>name</key> - <string>DebugOS</string> - </map> - <key>RelWithDebInfo</key> - <map> - <key>build</key> - <map> - </map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> + </array> + </map> + <key>name</key> + <string>Debug</string> + </map> + <key>DebugOS</key> + <map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=Debug</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> + <string>-DINSTALL_PROPRIETARY=FALSE</string> + </array> + </map> + <key>name</key> + <string>DebugOS</string> + </map> + <key>RelWithDebInfo</key> + <map> + <key>build</key> + <map> + </map> + <key>configure</key> + <map> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> <string>-DINSTALL_PROPRIETARY=TRUE</string> - </array> - </map> - <key>name</key> - <string>RelWithDebInfo</string> - </map> - <key>RelWithDebInfoOS</key> - <map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> - <string>-DINSTALL_PROPRIETARY=FALSE</string> - </array> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - </map> - <key>name</key> - <string>RelWithDebInfoOS</string> - </map> - <key>Release</key> - <map> - <key>build</key> - <map> - </map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=Release</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> - <string>-DUSE_PRECOMPILED_HEADERS=ON</string> - <string>-DLL_RELEASE_FOR_DOWNLOAD:BOOL=TRUE</string> + </array> + </map> + <key>name</key> + <string>RelWithDebInfo</string> + </map> + <key>RelWithDebInfoOS</key> + <map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> + <string>-DINSTALL_PROPRIETARY=FALSE</string> + </array> + </map> + <key>name</key> + <string>RelWithDebInfoOS</string> + </map> + <key>Release</key> + <map> + <key>build</key> + <map> + </map> + <key>configure</key> + <map> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=Release</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> <string>-DINSTALL_PROPRIETARY=TRUE</string> - </array> - </map> - <key>name</key> - <string>Release</string> - </map> - <key>ReleaseOS</key> - <map> - <key>configure</key> - <map> - <key>command</key> - <string>cmake</string> - <key>options</key> - <array> - <string>-DCMAKE_BUILD_TYPE:STRING=Release</string> - <string>-DWORD_SIZE:STRING=32</string> - <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> - <string>-DINSTALL_PROPRIETARY=FALSE</string> - <string>-DLL_RELEASE_FOR_DOWNLOAD:BOOL=YES</string> - </array> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - </map> - <key>name</key> - <string>ReleaseOS</string> - </map> + </array> + </map> + <key>name</key> + <string>Release</string> + </map> + <key>ReleaseOS</key> + <map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>command</key> + <string>cmake</string> + <key>options</key> + <array> + <string>-DCMAKE_BUILD_TYPE:STRING=Release</string> + <string>-DWORD_SIZE:STRING=32</string> + <string>-DROOT_PROJECT_NAME:STRING=SecondLife</string> + <string>-DINSTALL_PROPRIETARY=FALSE</string> + </array> + </map> + <key>name</key> + <string>ReleaseOS</string> + </map> + </map> + <key>name</key> + <string>common</string> </map> - <key>name</key> - <string>common</string> - </map> - <key>darwin</key> - <map> - <key>build_directory</key> - <string>build-darwin-i386</string> - <key>configurations</key> + <key>darwin</key> <map> - <key>Debug</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>|</string> - <string>grep</string> - <string>-v</string> - <string>setenv</string> - </array> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration Debug</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>name</key> - <string>Debug</string> - </map> - <key>DebugOS</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration Debug</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>name</key> - <string>DebugOS</string> - </map> - <key>RelWithDebInfo</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>|</string> - <string>grep</string> - <string>-v</string> - <string>setenv</string> - </array> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration RelWithDebInfo</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>default</key> - <string>True</string> - <key>name</key> - <string>RelWithDebInfo</string> - </map> - <key>RelWithDebInfoOS</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration RelWithDebInfo</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>name</key> - <string>RelWithDebInfoOS</string> - </map> - <key>Release</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>|</string> - <string>grep</string> - <string>-v</string> - <string>setenv</string> - </array> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration Release</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>name</key> - <string>Release</string> - </map> - <key>ReleaseOS</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>xcodebuild</string> - <key>options</key> - <array> - <string>-configuration Release</string> - <string>-project SecondLife.xcodeproj</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Xcode'</string> - </array> - </map> - <key>name</key> - <string>ReleaseOS</string> - </map> + <key>build_directory</key> + <string>build-darwin-i386</string> + <key>configurations</key> + <map> + <key>Debug</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>|</string> + <string>grep</string> + <string>-v</string> + <string>setenv</string> + </array> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration Debug</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>name</key> + <string>Debug</string> + </map> + <key>DebugOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration Debug</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>name</key> + <string>DebugOS</string> + </map> + <key>RelWithDebInfo</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>|</string> + <string>grep</string> + <string>-v</string> + <string>setenv</string> + </array> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration RelWithDebInfo</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>default</key> + <string>True</string> + <key>name</key> + <string>RelWithDebInfo</string> + </map> + <key>RelWithDebInfoOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration RelWithDebInfo</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>name</key> + <string>RelWithDebInfoOS</string> + </map> + <key>Release</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>|</string> + <string>grep</string> + <string>-v</string> + <string>setenv</string> + </array> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration Release</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>name</key> + <string>Release</string> + </map> + <key>ReleaseOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>xcodebuild</string> + <key>options</key> + <array> + <string>-configuration Release</string> + <string>-project SecondLife.xcodeproj</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Xcode'</string> + </array> + </map> + <key>name</key> + <string>ReleaseOS</string> + </map> + </map> + <key>name</key> + <string>darwin</string> </map> - <key>name</key> - <string>darwin</string> - </map> - <key>linux</key> - <map> - <key>build_directory</key> - <string>build-linux-i686</string> - <key>configurations</key> + <key>linux</key> <map> - <key>Debug</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 12</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> - </map> - <key>name</key> - <string>Debug</string> - </map> - <key>DebugOS</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 2</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> - </map> - <key>name</key> - <string>DebugOS</string> - </map> - <key>RelWithDebInfo</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 12</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> + <key>build_directory</key> + <string>build-linux-i686</string> + <key>configurations</key> + <map> + <key>Debug</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 12</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>name</key> + <string>Debug</string> + </map> + <key>DebugOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 2</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>name</key> + <string>DebugOS</string> + </map> + <key>RelWithDebInfo</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 12</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>default</key> + <string>True</string> + <key>name</key> + <string>RelWithDebInfo</string> + </map> + <key>RelWithDebInfoOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 2</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>name</key> + <string>RelWithDebInfoOS</string> + </map> + <key>Release</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 12</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>../indra</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>name</key> + <string>Release</string> + </map> + <key>ReleaseOS</key> + <map> + <key>build</key> + <map> + <key>command</key> + <string>make</string> + <key>options</key> + <array> + <string>-j 2</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>'Unix Makefiles'</string> + </array> + </map> + <key>name</key> + <string>ReleaseOS</string> </map> <key>default</key> - <string>True</string> - <key>name</key> - <string>RelWithDebInfo</string> - </map> - <key>RelWithDebInfoOS</key> - <map> - <key>build</key> <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 2</string> - </array> + <key>build</key> + <map> + </map> + <key>name</key> + <string>default</string> </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> - </map> - <key>name</key> - <string>RelWithDebInfoOS</string> - </map> - <key>Release</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 12</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>../indra</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> - </map> - <key>name</key> - <string>Release</string> - </map> - <key>ReleaseOS</key> - <map> - <key>build</key> - <map> - <key>command</key> - <string>make</string> - <key>options</key> - <array> - <string>-j 2</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>'Unix Makefiles'</string> - </array> - </map> - <key>name</key> - <string>ReleaseOS</string> - </map> - <key>default</key> - <map> - <key>build</key> - <map> - </map> - <key>name</key> - <string>default</string> </map> + <key>name</key> + <string>linux</string> </map> - <key>name</key> - <string>linux</string> - </map> - <key>windows</key> - <map> - <key>build_directory</key> - <string>build-vc100</string> - <key>configurations</key> + <key>windows</key> <map> - <key>Debug</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>BuildConsole</string> - <key>options</key> - <array> - <string>/build</string> - <string>"/cfg=Debug|Win32"</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>..\indra</string> - <string>&&</string> - <string>..\indra\tools\vstool\VSTool.exe</string> - <string>--solution</string> - <string>SecondLife.sln</string> - <string>--config</string> - <string>Debug</string> - <string>--startup</string> - <string>secondlife-bin</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - </array> - </map> - <key>name</key> - <string>Debug</string> - </map> - <key>DebugOS</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>msbuild.exe</string> - <key>options</key> - <array> - <string>/p:Configuration=Debug</string> - <string>/p:Platform=Win32</string> - <string>/t:Build</string> - <string>/p:useenv=true</string> - <string>/verbosity:minimal</string> - <string>/toolsversion:4.0</string> - <string>/p:"VCBuildAdditionalOptions= /incremental"</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - <string>-DUNATTENDED:BOOL=ON</string> - <string>-DUSE_PRECOMPILED_HEADERS=ON</string> - <string>-DINSTALL_PROPRIETARY=TRUE</string> - <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> - </array> - </map> - <key>name</key> - <string>DebugOS</string> - </map> - <key>RelWithDebInfo</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>BuildConsole</string> - <key>options</key> - <array> - <string>/build</string> - <string>"/cfg=RelWithDebInfo|Win32"</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>..\indra</string> - <string>&&</string> - <string>..\indra\tools\vstool\VSTool.exe</string> - <string>--solution</string> - <string>SecondLife.sln</string> - <string>--config</string> - <string>RelWithDebInfo</string> - <string>--startup</string> - <string>secondlife-bin</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - </array> + <key>build_directory</key> + <string>build-vc100</string> + <key>configurations</key> + <map> + <key>Debug</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>BuildConsole</string> + <key>options</key> + <array> + <string>/build</string> + <string>"/cfg=Debug|Win32"</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>..\indra</string> + <string>&&</string> + <string>..\indra\tools\vstool\VSTool.exe</string> + <string>--solution</string> + <string>SecondLife.sln</string> + <string>--config</string> + <string>Debug</string> + <string>--startup</string> + <string>secondlife-bin</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + </array> + </map> + <key>name</key> + <string>Debug</string> + </map> + <key>DebugOS</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>msbuild.exe</string> + <key>options</key> + <array> + <string>/p:Configuration=Debug</string> + <string>/p:Platform=Win32</string> + <string>/t:Build</string> + <string>/p:useenv=true</string> + <string>/verbosity:minimal</string> + <string>/toolsversion:4.0</string> + <string>/p:"VCBuildAdditionalOptions= /incremental"</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + <string>-DUNATTENDED:BOOL=ON</string> + <string>-DUSE_PRECOMPILED_HEADERS=ON</string> + <string>-DINSTALL_PROPRIETARY=TRUE</string> + <string>-DUSE_KDU=FALSE</string> + <string>-DFMOD=FALSE</string> + </array> + </map> + <key>name</key> + <string>DebugOS</string> + </map> + <key>RelWithDebInfo</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>BuildConsole</string> + <key>options</key> + <array> + <string>/build</string> + <string>"/cfg=RelWithDebInfo|Win32"</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>..\indra</string> + <string>&&</string> + <string>..\indra\tools\vstool\VSTool.exe</string> + <string>--solution</string> + <string>SecondLife.sln</string> + <string>--config</string> + <string>RelWithDebInfo</string> + <string>--startup</string> + <string>secondlife-bin</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + </array> + </map> + <key>default</key> + <string>True</string> + <key>name</key> + <string>RelWithDebInfo</string> + </map> + <key>RelWithDebInfoOS</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>msbuild.exe</string> + <key>options</key> + <array> + <string>/p:Configuration=RelWithDebInfo</string> + <string>/p:Platform=Win32</string> + <string>/t:Build</string> + <string>/p:useenv=true</string> + <string>/verbosity:minimal</string> + <string>/toolsversion:4.0</string> + <string>/p:"VCBuildAdditionalOptions= /incremental"</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + <string>-DUNATTENDED:BOOL=ON</string> + <string>-DUSE_PRECOMPILED_HEADERS=ON</string> + <string>-DINSTALL_PROPRIETARY=TRUE</string> + <string>-DUSE_KDU=FALSE</string> + <string>-DFMOD=FALSE</string> + </array> + </map> + <key>name</key> + <string>RelWithDebInfoOS</string> + </map> + <key>Release</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>BuildConsole</string> + <key>options</key> + <array> + <string>/build</string> + <string>"/cfg=Release|Win32"</string> + <string>"/CL_ADD=/m:1"</string> + </array> + </map> + <key>configure</key> + <map> + <key>arguments</key> + <array> + <string>..\indra</string> + <string>&&</string> + <string>..\indra\tools\vstool\VSTool.exe</string> + <string>--solution</string> + <string>SecondLife.sln</string> + <string>--config</string> + <string>Release</string> + <string>--startup</string> + <string>secondlife-bin</string> + </array> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + </array> + </map> + <key>name</key> + <string>Release</string> + </map> + <key>ReleaseOS</key> + <map> + <key>build</key> + <map> + <key>arguments</key> + <array> + <string>SecondLife.sln</string> + </array> + <key>command</key> + <string>msbuild.exe</string> + <key>options</key> + <array> + <string>/p:Configuration=Release</string> + <string>/p:Platform=Win32</string> + <string>/t:Build</string> + <string>/p:useenv=true</string> + <string>/verbosity:minimal</string> + <string>/toolsversion:4.0</string> + <string>/p:"VCBuildAdditionalOptions= /incremental"</string> + </array> + </map> + <key>configure</key> + <map> + <key>options</key> + <array> + <string>-G</string> + <string>"Visual Studio 10"</string> + <string>-DUNATTENDED:BOOL=ON</string> + <string>-DUSE_PRECOMPILED_HEADERS=ON</string> + <string>-DINSTALL_PROPRIETARY=TRUE</string> + <string>-DUSE_KDU=FALSE</string> + <string>-DFMOD=FALSE</string> + </array> + </map> + <key>name</key> + <string>ReleaseOS</string> </map> - <key>default</key> - <string>True</string> - <key>name</key> - <string>RelWithDebInfo</string> - </map> - <key>RelWithDebInfoOS</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>msbuild.exe</string> - <key>options</key> - <array> - <string>/p:Configuration=RelWithDebInfo</string> - <string>/p:Platform=Win32</string> - <string>/t:Build</string> - <string>/p:useenv=true</string> - <string>/verbosity:minimal</string> - <string>/toolsversion:4.0</string> - <string>/p:"VCBuildAdditionalOptions= /incremental"</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - <string>-DUNATTENDED:BOOL=ON</string> - <string>-DUSE_PRECOMPILED_HEADERS=ON</string> - <string>-DINSTALL_PROPRIETARY=TRUE</string> - <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> - </array> - </map> - <key>name</key> - <string>RelWithDebInfoOS</string> - </map> - <key>Release</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>BuildConsole</string> - <key>options</key> - <array> - <string>/build</string> - <string>"/cfg=Release|Win32"</string> - <string>"/CL_ADD=/m:1"</string> - </array> - </map> - <key>configure</key> - <map> - <key>arguments</key> - <array> - <string>..\indra</string> - <string>&&</string> - <string>..\indra\tools\vstool\VSTool.exe</string> - <string>--solution</string> - <string>SecondLife.sln</string> - <string>--config</string> - <string>Release</string> - <string>--startup</string> - <string>secondlife-bin</string> - </array> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - </array> - </map> - <key>name</key> - <string>Release</string> - </map> - <key>ReleaseOS</key> - <map> - <key>build</key> - <map> - <key>arguments</key> - <array> - <string>SecondLife.sln</string> - </array> - <key>command</key> - <string>msbuild.exe</string> - <key>options</key> - <array> - <string>/p:Configuration=Release</string> - <string>/p:Platform=Win32</string> - <string>/t:Build</string> - <string>/p:useenv=true</string> - <string>/verbosity:minimal</string> - <string>/toolsversion:4.0</string> - <string>/p:"VCBuildAdditionalOptions= /incremental"</string> - </array> - </map> - <key>configure</key> - <map> - <key>options</key> - <array> - <string>-G</string> - <string>"Visual Studio 10"</string> - <string>-DUNATTENDED:BOOL=ON</string> - <string>-DUSE_PRECOMPILED_HEADERS=ON</string> - <string>-DINSTALL_PROPRIETARY=TRUE</string> - <string>-DUSE_KDU=FALSE</string> - <string>-DFMOD=FALSE</string> - </array> - </map> - <key>name</key> - <string>ReleaseOS</string> </map> + <key>name</key> + <string>windows</string> </map> - <key>name</key> - <string>windows</string> </map> </map> + <key>type</key> + <string>autobuild</string> + <key>version</key> + <string>1.2</string> </map> - <key>type</key> - <string>autobuild</string> - <key>version</key> - <string>1.2</string> -</map> </llsd> diff --git a/build.sh b/build.sh index 937c1f27ab70d96413b90ff8a1241868f84cc780..f00d403ad49880cfec866f7ba30d5dbe2d95380b 100755 --- a/build.sh +++ b/build.sh @@ -118,11 +118,12 @@ eval '$build_'"$arch" || pass # File no longer exists in code-sep branch, so let's make sure it exists in order to use it. if test -f scripts/update_version_files.py ; then begin_section UpdateVer - python scripts/update_version_files.py \ - --channel="$viewer_channel" \ - --server_channel="$server_channel" \ - --revision=$revision \ - --verbose \ + eval $(python scripts/update_version_files.py \ + --channel="$viewer_channel" \ + --server_channel="$server_channel" \ + --revision=$revision \ + --verbose \ + | sed -n -e "s,Setting viewer channel/version: '\([^']*\)' / '\([^']*\)',VIEWER_CHANNEL='\1';VIEWER_VERSION='\2',p")\ || fail update_version_files.py end_section UpdateVer fi @@ -262,6 +263,9 @@ then upload_item installer "$package" binary/octet-stream upload_item quicklink "$package" binary/octet-stream + echo "{\"Type\":\"viewer\",\"Version\":\"${VIEWER_VERSION}\"}" > summary.json + upload_item installer summary.json text/plain + # Upload crash reporter files. case "$last_built_variant" in Release) diff --git a/doc/contributions.txt b/doc/contributions.txt index 5531e0f7e464eb74e3a631c6e85aed224d6ee460..6f9cf353a6f8d4786a2dc8a9082e53d4c5b9fb6d 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -205,6 +205,7 @@ Boroondas Gupte SNOW-624 SNOW-737 STORM-318 + STORM-1182 VWR-233 VWR-20583 VWR-20891 @@ -244,6 +245,7 @@ Coaldust Numbers Cron Stardust VWR-10579 VWR-25120 + STORM-1075 Cypren Christenson STORM-417 Dale Glass @@ -426,6 +428,8 @@ Jonathan Yap STORM-1094 STORM-1077 STORM-953 + STORM-1128 + STORM-956 STORM-1095 Kage Pixel VWR-11 @@ -664,6 +668,7 @@ Robin Cornelius STORM-960 STORM-1019 STORM-1095 + STORM-1128 VWR-2488 VWR-9557 VWR-10579 @@ -801,6 +806,7 @@ Thickbrick Sleaford VWR-13483 VWR-13947 VWR-24420 + STORM-956 STORM-1147 Thraxis Epsilon SVC-371 diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index a8e7f9a40e7a9e3d707859ad66f4185ee191ac83..1a8b16dec7264be22b972aa0aa9b9f8a21a9dcdf 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -103,7 +103,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "4.2") - set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "DWARF with dSYM File") + set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym) # NOTE: To attempt an i386/PPC Universal build, add this on the configure line: # -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc' diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 365f5f758cdb9c5547814fb57fa6b151863b043a..60ddf63b218992e25fc0eb6a258209c5f7ada6e5 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -53,12 +53,32 @@ static const char USAGE[] = "\n" " -o, --output <file1 .. file2> OR <type>\n" " List of image files to create (assumes same order as for input files)\n" " OR 3 letters file type extension to convert each input file into.\n" +" -r, --region <x0, y0, x1, y1>\n" +" Crop region applied to the input files in pixels.\n" +" Only used for j2c images. Default is no region cropping.\n" +" -d, --discard_level <n>\n" +" Discard level max used on input. 0 is highest resolution. Max discard level is 5.\n" +" This allows the input image to be clamped in resolution when loading.\n" +" Only valid for j2c images. Default is no discard.\n" +" -p, --precincts <n>\n" +" Dimension of precincts in pixels. Precincts are assumed square and identical for\n" +" all levels. Note that this option also add PLT and tile markers to the codestream, \n" +" and uses RPCL order. Power of 2 must be used.\n" +" Only valid for output j2c images. Default is no precincts used.\n" +" -b, --blocks <n>\n" +" Dimension of coding blocks in pixels. Blocks are assumed square. Power of 2 must\n" +" be used. Blocks must be smaller than precincts. Like precincts, this option adds\n" +" PLT, tile markers and uses RPCL.\n" +" Only valid for output j2c images. Default is 64.\n" +" -rev, --reversible\n" +" Set the compression to be lossless (reversible in j2c parlance).\n" +" Only valid for output j2c images.\n" " -log, --logmetrics <metric>\n" " Log performance data for <metric>. Results in <metric>.slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" -" -r, --analyzeperformance\n" +" -a, --analyzeperformance\n" " Create a report comparing <metric>_baseline.slp with current <metric>.slp\n" -" Results in <metric>_report.csv" +" Results in <metric>_report.csv\n" " -s, --image-stats\n" " Output stats for each input and output image.\n" "\n"; @@ -69,31 +89,8 @@ static bool sAllDone = false; // Create an empty formatted image instance of the correct type from the filename LLPointer<LLImageFormatted> create_image(const std::string &filename) { - std::string exten = gDirUtilp->getExtension(filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); - - LLPointer<LLImageFormatted> image; - switch (codec) - { - case IMG_CODEC_BMP: - image = new LLImageBMP(); - break; - case IMG_CODEC_TGA: - image = new LLImageTGA(); - break; - case IMG_CODEC_JPEG: - image = new LLImageJPEG(); - break; - case IMG_CODEC_J2C: - image = new LLImageJ2C(); - break; - case IMG_CODEC_PNG: - image = new LLImagePNG(); - break; - default: - return NULL; - } - + std::string exten = gDirUtilp->getExtension(filename); + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromExtension(exten); return image; } @@ -110,10 +107,11 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi } // Load an image from file and return a raw (decompressed) instance of its data -LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats) +LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats) { LLPointer<LLImageFormatted> image = create_image(src_filename); - + + // This just loads the image file stream into a buffer. No decoding done. if (!image->load(src_filename)) { return NULL; @@ -131,6 +129,15 @@ LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_st } LLPointer<LLImageRaw> raw_image = new LLImageRaw; + + // Set the image restriction on load in the case of a j2c image + if ((image->getCodec() == IMG_CODEC_J2C) && ((discard_level != -1) || (region != NULL))) + { + // That method doesn't exist (and likely, doesn't make sense) for any other image file format + // hence the required cryptic cast. + ((LLImageJ2C*)(image.get()))->initDecode(*raw_image, discard_level, region); + } + if (!image->decode(raw_image, 0.0f)) { return NULL; @@ -140,10 +147,22 @@ LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_st } // Save a raw image instance into a file -bool save_image(const std::string &dest_filename, LLPointer<LLImageRaw> raw_image, bool output_stats) +bool save_image(const std::string &dest_filename, LLPointer<LLImageRaw> raw_image, int blocks_size, int precincts_size, bool reversible, bool output_stats) { LLPointer<LLImageFormatted> image = create_image(dest_filename); + // Set the image codestream parameters on output in the case of a j2c image + if (image->getCodec() == IMG_CODEC_J2C) + { + // That method doesn't exist (and likely, doesn't make sense) for any other image file format + // hence the required cryptic cast. + if ((blocks_size != -1) || (precincts_size != -1)) + { + ((LLImageJ2C*)(image.get()))->initEncode(*raw_image, blocks_size, precincts_size); + } + ((LLImageJ2C*)(image.get()))->setReversible(reversible); + } + if (!image->encode(raw_image, 0.0f)) { return false; @@ -280,8 +299,14 @@ int main(int argc, char** argv) // List of input and output files std::list<std::string> input_filenames; std::list<std::string> output_filenames; + // Other optional parsed arguments bool analyze_performance = false; bool image_stats = false; + int* region = NULL; + int discard_level = -1; + int precincts_size = -1; + int blocks_size = -1; + bool reversible = false; // Init whatever is necessary ll_init_apr(); @@ -323,6 +348,85 @@ int main(int argc, char** argv) file_name = argv[arg+1]; // Next argument and loop over } } + else if ((!strcmp(argv[arg], "--region") || !strcmp(argv[arg], "-r")) && arg < argc-1) + { + std::string value_str = argv[arg+1]; + int index = 0; + region = new int[4]; + while (value_str[0] != '-') // if arg starts with '-', it's the next option + { + int value = atoi(value_str.c_str()); + region[index++] = value; + arg += 1; // Definitely skip that arg now we know it's a number + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + if (index == 4) // Break out of the loop if we captured 4 values already + break; + value_str = argv[arg+1]; // Next argument and loop over + } + if (index != 4) + { + std::cout << "--region arguments invalid" << std::endl; + delete [] region; + region = NULL; + } + } + else if (!strcmp(argv[arg], "--discard_level") || !strcmp(argv[arg], "-d")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --discard_level argument given, discard_level ignored" << std::endl; + } + else + { + discard_level = atoi(value_str.c_str()); + // Clamp to the values accepted by the viewer + discard_level = llclamp(discard_level,0,5); + } + } + else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --precincts argument given, precincts ignored" << std::endl; + } + else + { + precincts_size = atoi(value_str.c_str()); + // *TODO: make sure precincts_size is a power of 2 + } + } + else if (!strcmp(argv[arg], "--blocks") || !strcmp(argv[arg], "-b")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --blocks argument given, blocks ignored" << std::endl; + } + else + { + blocks_size = atoi(value_str.c_str()); + // *TODO: make sure blocks_size is a power of 2 + } + } + else if (!strcmp(argv[arg], "--reversible") || !strcmp(argv[arg], "-rev")) + { + reversible = true; + } else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log")) { // '--logmetrics' needs to be specified with a named test metric argument @@ -346,7 +450,7 @@ int main(int argc, char** argv) break; } } - else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-r")) + else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { analyze_performance = true; } @@ -364,7 +468,7 @@ int main(int argc, char** argv) } if (analyze_performance && !LLFastTimer::sMetricLog) { - std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -r) -> exit" << std::endl; + std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -a) -> exit" << std::endl; return 0; } @@ -382,10 +486,10 @@ int main(int argc, char** argv) std::list<std::string>::iterator out_file = output_filenames.begin(); std::list<std::string>::iterator in_end = input_filenames.end(); std::list<std::string>::iterator out_end = output_filenames.end(); - for (; in_file != in_end; ++in_file) + for (; in_file != in_end; ++in_file, ++out_file) { // Load file - LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats); + LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, image_stats); if (!raw_image) { std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; @@ -395,7 +499,7 @@ int main(int argc, char** argv) // Save file if (out_file != out_end) { - if (!save_image(*out_file, raw_image, image_stats)) + if (!save_image(*out_file, raw_image, blocks_size, precincts_size, reversible, image_stats)) { std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; } @@ -403,29 +507,28 @@ int main(int argc, char** argv) { std::cout << *in_file << " -> " << *out_file << std::endl; } - ++out_file; } } - // Stop the perf gathering system if needed - if (LLFastTimer::sMetricLog) - { - LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName); - sAllDone = true; - } - // Output perf data if requested by user if (analyze_performance) { - std::cout << "Analyzing performance" << std::endl; - std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp"; std::string current_name = LLFastTimer::sLogName + ".slp"; std::string report_name = LLFastTimer::sLogName + "_report.csv"; + std::cout << "Analyzing performance, check report in : " << report_name << std::endl; + LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline_name, current_name, report_name); } + // Stop the perf gathering system if needed + if (LLFastTimer::sMetricLog) + { + LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName); + sAllDone = true; + } + // Cleanup and exit LLImage::cleanupClass(); if (fast_timer_log_thread) diff --git a/indra/lib/python/indra/ipc/llmessage.py b/indra/lib/python/indra/ipc/llmessage.py index 6161badc70632abe113467390aa057d444209b20..91fb36b72c62b4979c9ca1cde2f3f4ab00fc2833 100644 --- a/indra/lib/python/indra/ipc/llmessage.py +++ b/indra/lib/python/indra/ipc/llmessage.py @@ -26,8 +26,6 @@ $/LicenseInfo$ """ -from sets import Set, ImmutableSet - from compatibility import Incompatible, Older, Newer, Same from tokenstream import TokenStream @@ -44,8 +42,8 @@ def addMessage(self, m): def compatibleWithBase(self, base): messagenames = ( - ImmutableSet(self.messages.keys()) - | ImmutableSet(base.messages.keys()) + frozenset(self.messages.keys()) + | frozenset(base.messages.keys()) ) compatibility = Same() diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 532a2c1b0d779281253d84609cedb775f45ff4fc..f3cf950afae70deffcafc7a07adabcb4878f415e 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -42,10 +42,10 @@ using namespace std; #define INCHES_TO_METERS 0.02540005f -const F32 POSITION_KEYFRAME_THRESHOLD = 0.03f; +const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.03f * 0.03f; const F32 ROTATION_KEYFRAME_THRESHOLD = 0.01f; -const F32 POSITION_MOTION_THRESHOLD = 0.001f; +const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.001f * 0.001f; const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ @@ -1196,7 +1196,7 @@ void LLBVHLoader::optimize() if (ki_prev == ki_last_good_pos) { joint->mNumPosKeys++; - if (dist_vec(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } @@ -1209,12 +1209,12 @@ void LLBVHLoader::optimize() LLVector3 current_pos(ki->mPos); LLVector3 interp_pos = lerp(current_pos, last_good_pos, 1.f / (F32)numPosFramesConsidered); - if (dist_vec(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } - if (dist_vec(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD) + if (dist_vec_squared(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD_SQUARED) { ki_prev->mIgnorePos = TRUE; numPosFramesConsidered++; diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 95cb606240276669b171d4113d18b213e4cd46a5..d0f287657ed0b46d3a0743f9cc3af910640ffed9 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -312,6 +312,14 @@ const F32 CHAT_SHOUT_RADIUS = 100.f; const F32 CHAT_MAX_RADIUS = CHAT_SHOUT_RADIUS; const F32 CHAT_MAX_RADIUS_BY_TWO = CHAT_MAX_RADIUS / 2.f; +// squared editions of the above for distance checks +const F32 CHAT_WHISPER_RADIUS_SQUARED = CHAT_WHISPER_RADIUS * CHAT_WHISPER_RADIUS; +const F32 CHAT_NORMAL_RADIUS_SQUARED = CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS; +const F32 CHAT_SHOUT_RADIUS_SQUARED = CHAT_SHOUT_RADIUS * CHAT_SHOUT_RADIUS; +const F32 CHAT_MAX_RADIUS_SQUARED = CHAT_SHOUT_RADIUS_SQUARED; +const F32 CHAT_MAX_RADIUS_BY_TWO_SQUARED = CHAT_MAX_RADIUS_BY_TWO * CHAT_MAX_RADIUS_BY_TWO; + + // this times above gives barely audible radius const F32 CHAT_BARELY_AUDIBLE_FACTOR = 2.0f; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index df5afcbf1ce27e5574da1db703fc43a777ea313c..08026c38a6344d9ae6461d1251e34eec6d181ede 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 2; const S32 LL_VERSION_MINOR = 6; -const S32 LL_VERSION_PATCH = 6; +const S32 LL_VERSION_PATCH = 8; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 39211bf7fa5158f1ccce04111f67a3d3159fd1c6..f0d15d9607f6d49597337da5cfcba535c0b2bcf6 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1254,28 +1254,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip return false; } - LLPointer<LLImageFormatted> image; - switch(codec) - { - //case IMG_CODEC_RGB: - case IMG_CODEC_BMP: - image = new LLImageBMP(); - break; - case IMG_CODEC_TGA: - image = new LLImageTGA(); - break; - case IMG_CODEC_JPEG: - image = new LLImageJPEG(); - break; - case IMG_CODEC_J2C: - image = new LLImageJ2C(); - break; - case IMG_CODEC_DXT: - image = new LLImageDXT(); - break; - default: - return false; - } + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); llassert(image.notNull()); U8 *buffer = image->allocateData(length); diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 80fec7f8a04b571b8f172a1ef3e616eee9a5d1e5..a90df0f1c17139eb320d40e4dd8d22873a07dc8b 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -139,6 +139,15 @@ BOOL LLImageJ2C::updateData() return res; } +BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region) +{ + return mImpl->initDecode(*this,raw_image,discard_level,region); +} + +BOOL LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + return mImpl->initEncode(*this,raw_image,blocks_size,precincts_size); +} BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) { @@ -251,6 +260,9 @@ S32 LLImageJ2C::calcHeaderSizeJ2C() //static S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) { + // Note: this only provides an *estimate* of the size in bytes of an image level + // *TODO: find a way to read the true size (when available) and convey the fact + // that the result is an estimate in the other cases if (rate <= 0.f) rate = .125f; while (discard_level > 0) { diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index dd5bec8b2e2cc0bfb8086d99c587ed7bb84e0fa0..6bba81aab539a54b1264bc7dfa2ea0ccf2339267 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -56,6 +56,8 @@ class LLImageJ2C : public LLImageFormatted /*virtual*/ void resetLastError(); /*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string()); + BOOL initDecode(LLImageRaw &raw_image, int discard_level, int* region); + BOOL initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size); // Encode with comment text BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0); @@ -117,6 +119,8 @@ class LLImageJ2CImpl virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0; virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible=FALSE) = 0; + virtual BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0; + virtual BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1) = 0; friend class LLImageJ2C; }; diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 13b12c0928c27d4a542e40c90bd15edaabc5eaa9..8288fa1f5c383270ec326ebf0d6632768f083c68 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -107,6 +107,17 @@ LLImageJ2COJ::~LLImageJ2COJ() { } +BOOL LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +{ + // No specific implementation for this method in the OpenJpeg case + return FALSE; +} + +BOOL LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + // No specific implementation for this method in the OpenJpeg case + return FALSE; +} BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h index 9476665ccbb57ed034ee4d4e594775f4539dc8f2..9c7cc09fcbcacdd1c35222d05f01f28aa58b606c 100644 --- a/indra/llimagej2coj/llimagej2coj.h +++ b/indra/llimagej2coj/llimagej2coj.h @@ -39,6 +39,8 @@ class LLImageJ2COJ : public LLImageJ2CImpl /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count); /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible = FALSE); + /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); + /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1); }; #endif diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 10ea5685e86ca797d26da2a5a8f4767c7f933576..ae456a48be68fafbd283cc3fc7627cec0d596fd4 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -34,35 +34,35 @@ class kdc_flow_control { -public: // Member functions - kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream); - ~kdc_flow_control(); - bool advance_components(); - void process_components(); +public: + kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream); + ~kdc_flow_control(); + bool advance_components(); + void process_components(); + +private: -private: // Data - - struct kdc_component_flow_control { - public: // Data - kdu_image_in_base *reader; - int vert_subsampling; - int ratio_counter; /* Initialized to 0, decremented by `count_delta'; + struct kdc_component_flow_control { + public: + kdu_image_in_base *reader; + int vert_subsampling; + int ratio_counter; /* Initialized to 0, decremented by `count_delta'; when < 0, a new line must be processed, after which it is incremented by `vert_subsampling'. */ - int initial_lines; - int remaining_lines; - kdu_line_buf *line; - }; - - kdu_codestream codestream; - kdu_dims valid_tile_indices; - kdu_coords tile_idx; - kdu_tile tile; - int num_components; - kdc_component_flow_control *components; - int count_delta; // Holds the minimum of the `vert_subsampling' fields - kdu_multi_analysis engine; - kdu_long max_buffer_memory; + int initial_lines; + int remaining_lines; + kdu_line_buf *line; + }; + + kdu_codestream codestream; + kdu_dims valid_tile_indices; + kdu_coords tile_idx; + kdu_tile tile; + int num_components; + kdc_component_flow_control *components; + int count_delta; // Holds the minimum of the `vert_subsampling' fields + kdu_multi_analysis engine; + kdu_long max_buffer_memory; }; // @@ -72,7 +72,8 @@ void set_default_colour_weights(kdu_params *siz); const char* engineInfoLLImageJ2CKDU() { - return "KDU v6.4.1"; + std::string version = llformat("KDU %s", KDU_CORE_VERSION); + return version.c_str(); } LLImageJ2CKDU* createLLImageJ2CKDU() @@ -105,7 +106,11 @@ const char* fallbackEngineInfoLLImageJ2CImpl() class LLKDUDecodeState { public: + LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap); + ~LLKDUDecodeState(); + BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE); +private: S32 mNumComponents; BOOL mUseYCC; kdu_dims mDims; @@ -113,22 +118,12 @@ class LLKDUDecodeState kdu_tile_comp mComps[4]; kdu_line_buf mLines[4]; kdu_pull_ifc mEngines[4]; - bool mReversible[4]; // Some components may be reversible and others not. - int mBitDepths[4]; // Original bit-depth may be quite different from 8. - + bool mReversible[4]; // Some components may be reversible and others not + int mBitDepths[4]; // Original bit-depth may be quite different from 8 + kdu_tile mTile; kdu_byte *mBuf; S32 mRowGap; - - LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap); - ~LLKDUDecodeState(); - BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE); - -public: - int *AssignLayerBytes(siz_params *siz, int &num_specs); - - void setupCodeStream(BOOL keep_codestream, LLImageJ2CKDU::ECodeStreamMode mode); - BOOL initDecode(LLImageRaw &raw_image, F32 decode_time, LLImageJ2CKDU::ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ); }; void ll_kdu_error( void ) @@ -153,7 +148,7 @@ class LLKDUMessageError : public kdu_message public: /*virtual*/ void put_text(const char *s); /*virtual*/ void put_text(const kdu_uint16 *s); - /*virtual*/ void flush(bool end_of_message=false); + /*virtual*/ void flush(bool end_of_message = false); static LLKDUMessageError sDefaultMessage; }; @@ -179,7 +174,7 @@ void LLKDUMessageError::put_text(const kdu_uint16 *s) void LLKDUMessageError::flush(bool end_of_message) { - if( end_of_message ) + if (end_of_message) { throw "KDU throwing an exception"; } @@ -195,7 +190,9 @@ mCodeStreamp(NULL), mTPosp(NULL), mTileIndicesp(NULL), mRawImagep(NULL), -mDecodeState(NULL) +mDecodeState(NULL), +mBlocksSize(-1), +mPrecinctsSize(-1) { } @@ -210,7 +207,7 @@ void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision); void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode) { S32 data_size = base.getDataSize(); - S32 max_bytes = base.getMaxBytes() ? base.getMaxBytes() : data_size; + S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size); // // Initialization @@ -247,21 +244,21 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod // Set the maximum number of bytes to use from the codestream mCodeStreamp->set_max_bytes(max_bytes); - // If you want to flip or rotate the image for some reason, change + // If you want to flip or rotate the image for some reason, change // the resolution, or identify a restricted region of interest, this is // the place to do it. You may use "kdu_codestream::change_appearance" // and "kdu_codestream::apply_input_restrictions" for this purpose. - // If you wish to truncate the code-stream prior to decompression, you + // If you wish to truncate the code-stream prior to decompression, you // may use "kdu_codestream::set_max_bytes". - // If you wish to retain all compressed data so that the material + // If you wish to retain all compressed data so that the material // can be decompressed multiple times, possibly with different appearance // parameters, you should call "kdu_codestream::set_persistent" here. - // There are a variety of other features which must be enabled at + // There are a variety of other features which must be enabled at // this point if you want to take advantage of them. See the // descriptions appearing with the "kdu_codestream" interface functions // in "kdu_compressed.h" for an itemized account of these capabilities. - switch( mode ) + switch (mode) { case MODE_FAST: mCodeStreamp->set_fast(); @@ -326,7 +323,19 @@ void LLImageJ2CKDU::cleanupCodeStream() mTileIndicesp = NULL; } -BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ) +BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +{ + return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region); +} + +BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + mBlocksSize = blocks_size; + mPrecinctsSize = precincts_size; + return TRUE; +} + +BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { base.resetLastError(); @@ -339,17 +348,36 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); - mCodeStreamp->apply_input_restrictions(first_channel,max_channel_count,base.getRawDiscardLevel(),0,NULL); - kdu_dims dims; mCodeStreamp->get_dims(0,dims); - S32 channels = base.getComponents() - first_channel; - if( channels > max_channel_count ) + // Apply loading discard level and cropping if required + kdu_dims* region_kdu = NULL; + if (region != NULL) { - channels = max_channel_count; + region_kdu = new kdu_dims; + region_kdu->pos.x = region[0]; + region_kdu->pos.y = region[1]; + region_kdu->size.x = region[2] - region[0]; + region_kdu->size.y = region[3] - region[1]; } + int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel()); + + // Apply loading restrictions + mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); + + // Clean-up + if (region_kdu) + { + delete region_kdu; + region_kdu = NULL; + } + + // Resize raw_image according to the image to be decoded + kdu_dims dims; mCodeStreamp->get_dims(0,dims); + S32 channels = base.getComponents() - first_channel; + channels = llmin(channels,max_channel_count); raw_image.resize(dims.size.x, dims.size.y, channels); + // llinfos << "Resizing raw_image to " << dims.size.x << ":" << dims.size.y << llendl; - // llinfos << "Resizing to " << dims.size.x << ":" << dims.size.y << llendl; if (!mTileIndicesp) { mTileIndicesp = new kdu_dims; @@ -426,7 +454,7 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco // canvas coordinate system. Comparing the two tells // us where the current tile is in the buffer. S32 channels = base.getComponents() - first_channel; - if( channels > max_channel_count ) + if (channels > max_channel_count) { channels = max_channel_count; } @@ -452,14 +480,14 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco return FALSE; } } - catch( const char* msg ) + catch (const char* msg) { base.setLastError(ll_safe_string(msg)); base.decodeFailed(); cleanupCodeStream(); return TRUE; // done } - catch( ... ) + catch (...) { base.setLastError( "Unknown J2C error" ); base.decodeFailed(); @@ -482,28 +510,17 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) { - // Collect simple arguments. - bool transpose, vflip, hflip; - bool allow_rate_prediction, mem, quiet, no_weights; - int cpu_iterations; - std::ostream *record_stream; - - transpose = false; - record_stream = NULL; - allow_rate_prediction = true; - no_weights = false; - cpu_iterations = -1; - mem = false; - quiet = false; - vflip = true; - hflip = false; + // Declare and set simple arguments + bool transpose = false; + bool vflip = true; + bool hflip = false; try { - // Set up input image files. + // Set up input image files siz_params siz; - // Should set rate someplace here. + // Should set rate someplace here LLKDUMemIn mem_in(raw_image.getData(), raw_image.getDataSize(), raw_image.getWidth(), @@ -521,26 +538,17 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co siz.set(Sprecision,0,0,8); // Image samples have original bit-depth of 8 siz.set(Ssigned,0,0,false); // Image samples are originally unsigned - kdu_params *siz_ref = &siz; siz_ref->finalize(); - siz_params transformed_siz; // Use this one to construct code-strea + kdu_params *siz_ref = &siz; + siz_ref->finalize(); + siz_params transformed_siz; // Use this one to construct code-stream transformed_siz.copy_from(&siz,-1,-1,-1,0,transpose,false,false); - // Construct the `kdu_codestream' object and parse all remaining arguments. - + // Construct the `kdu_codestream' object and parse all remaining arguments U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents(); - if (max_output_size < 1000) - { - max_output_size = 1000; - } + max_output_size = (max_output_size < 1000 ? 1000 : max_output_size); U8 *output_buffer = new U8[max_output_size]; - - U32 output_size = max_output_size; // gets modified - LLKDUMemTarget output(output_buffer, output_size, base.getWidth()*base.getHeight()*base.getComponents()); - if (output_size > max_output_size) - { - llerrs << llformat("LLImageJ2C::encode output_size(%d) > max_output_size(%d)", - output_size,max_output_size) << llendl; - } + U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size + LLKDUMemTarget output(output_buffer, output_size, max_output_size); kdu_codestream codestream; codestream.create(&transformed_siz,&output); @@ -558,16 +566,22 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co kdu_long layer_bytes[64]; U32 max_bytes = 0; - if ((num_components >= 3) && !no_weights) + if (num_components >= 3) { + // Note that we always use YCC and not YUV + // *TODO: Verify this doesn't screws up reversible textures (like sculpties) as YCC is not reversible but YUV is... set_default_colour_weights(codestream.access_siz()); } if (reversible) { - // If we're doing reversible, assume we're not using quality layers. - // Yes, I know this is incorrect! codestream.access_siz()->parse_string("Creversible=yes"); + // *TODO: we should use yuv in reversible mode and one level since those images are small. + // Don't turn this on now though as both create problems on decoding for the moment + //codestream.access_siz()->parse_string("Clevels=1"); + //codestream.access_siz()->parse_string("Cycc=no"); + // If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers. + // *TODO: this is incorrect and unecessary. Try using the regular layer setting. codestream.access_siz()->parse_string("Clayers=1"); num_layer_specs = 1; layer_bytes[0] = 0; @@ -577,6 +591,7 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co // Rate is the argument passed into the LLImageJ2C which // specifies the target compression rate. The default is 8:1. // Possibly if max_bytes < 500, we should just use the default setting? + // *TODO: mRate is actually always 8:1 in the viewer. Test different values. Also force to reversible for small (< 500 bytes) textures. if (base.mRate != 0.f) { max_bytes = (U32)(base.mRate*base.getWidth()*base.getHeight()*base.getComponents()); @@ -617,42 +632,56 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co codestream.access_siz()->parse_string(layer_string.c_str()); } } - codestream.access_siz()->finalize_all(); - if (cpu_iterations >= 0) + + // Set up data ordering, markers, etc... if precincts or blocks specified + if ((mBlocksSize != -1) || (mPrecinctsSize != -1)) { - codestream.collect_timing_stats(cpu_iterations); + if (mPrecinctsSize != -1) + { + std::string precincts_string = llformat("Cprecincts={%d,%d}",mPrecinctsSize,mPrecinctsSize); + codestream.access_siz()->parse_string(precincts_string.c_str()); + } + if (mBlocksSize != -1) + { + std::string blocks_string = llformat("Cblk={%d,%d}",mBlocksSize,mBlocksSize); + codestream.access_siz()->parse_string(blocks_string.c_str()); + } + std::string ordering_string = llformat("Corder=RPCL"); + codestream.access_siz()->parse_string(ordering_string.c_str()); + std::string PLT_string = llformat("ORGgen_plt=yes"); + codestream.access_siz()->parse_string(PLT_string.c_str()); + std::string Parts_string = llformat("ORGtparts=R"); + codestream.access_siz()->parse_string(Parts_string.c_str()); } + + codestream.access_siz()->finalize_all(); codestream.change_appearance(transpose,vflip,hflip); // Now we are ready for sample data processing. - kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream); - bool done = false; - while (!done) - { - // Process line by line - done = true; - if (tile->advance_components()) - { - done = false; - tile->process_components(); - } - } + kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream); + bool done = false; + while (!done) + { + // Process line by line + if (tile->advance_components()) + { + tile->process_components(); + } + else + { + done = true; + } + } // Produce the compressed output - codestream.flush(layer_bytes,num_layer_specs); + codestream.flush(layer_bytes,num_layer_specs); // Cleanup - delete tile; - + delete tile; codestream.destroy(); - if (record_stream != NULL) - { - delete record_stream; - } // Now that we're done encoding, create the new data buffer for the compressed // image and stick it there. - base.copyData(output_buffer, output_size); base.updateData(); // set width, height delete[] output_buffer; @@ -674,19 +703,19 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) { // *FIX: kdu calls our callback function if there's an error, and - // then bombs. To regain control, we throw an exception, and + // then bombs. To regain control, we throw an exception, and // catch it here. try { setupCodeStream(base, FALSE, MODE_FAST); return TRUE; } - catch( const char* msg ) + catch (const char* msg) { base.setLastError(ll_safe_string(msg)); return FALSE; } - catch( ... ) + catch (...) { base.setLastError( "Unknown J2C error" ); return FALSE; @@ -699,37 +728,49 @@ void set_default_colour_weights(kdu_params *siz) assert(cod != NULL); bool can_use_ycc = true; - bool rev0=false; - int depth0=0, sub_x0=1, sub_y0=1; - for (int c=0; c < 3; c++) + bool rev0 = false; + int depth0 = 0, sub_x0 = 1, sub_y0 = 1; + for (int c = 0; c < 3; c++) { - int depth=0; siz->get(Sprecision,c,0,depth); - int sub_y=1; siz->get(Ssampling,c,0,sub_y); - int sub_x=1; siz->get(Ssampling,c,1,sub_x); + int depth = 0; siz->get(Sprecision,c,0,depth); + int sub_y = 1; siz->get(Ssampling,c,0,sub_y); + int sub_x = 1; siz->get(Ssampling,c,1,sub_x); kdu_params *coc = cod->access_relation(-1,c); - bool rev=false; coc->get(Creversible,0,0,rev); + bool rev = false; coc->get(Creversible,0,0,rev); if (c == 0) - { rev0=rev; depth0=depth; sub_x0=sub_x; sub_y0=sub_y; } - else if ((rev != rev0) || (depth != depth0) || - (sub_x != sub_x0) || (sub_y != sub_y0)) + { + rev0 = rev; depth0 = depth; sub_x0 = sub_x; sub_y0 = sub_y; + } + else if ((rev != rev0) || (depth != depth0) || + (sub_x != sub_x0) || (sub_y != sub_y0)) + { can_use_ycc = false; + } } if (!can_use_ycc) + { return; + } bool use_ycc; if (!cod->get(Cycc,0,0,use_ycc)) + { cod->set(Cycc,0,0,use_ycc=true); + } if (!use_ycc) + { return; + } float weight; - if (cod->get(Clev_weights,0,0,weight) || - cod->get(Cband_weights,0,0,weight)) - return; // Weights already specified explicitly. + if (cod->get(Clev_weights,0,0,weight) || cod->get(Cband_weights,0,0,weight)) + { + // Weights already specified explicitly -> nothing to do + return; + } - /* These example weights are adapted from numbers generated by Marcus Nadenau - at EPFL, for a viewing distance of 15 cm and a display resolution of - 300 DPI. */ + // These example weights are adapted from numbers generated by Marcus Nadenau + // at EPFL, for a viewing distance of 15 cm and a display resolution of + // 300 DPI. cod->parse_string("Cband_weights:C0=" "{0.0901},{0.2758},{0.2758}," @@ -775,7 +816,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:255; + val = (val < 0 ? 0 : 255); } *dest = (kdu_byte) val; } @@ -793,7 +834,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:255; + val = (val < 0 ? 0 : 255); } *dest = (kdu_byte) val; } @@ -816,7 +857,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:255; + val = (val < 0 ? 0 : 255); } *dest = (kdu_byte) val; } @@ -835,7 +876,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:(256-(1<<upshift)); + val = (val < 0 ? 0 : 256 - (1<<upshift)); } *dest = (kdu_byte) val; } @@ -857,7 +898,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:255; + val = (val < 0 ? 0 : 255); } *dest = (kdu_byte) val; } @@ -873,7 +914,7 @@ all necessary level shifting, type conversion, rounding and truncation. */ val += 128; if (val & ((-1)<<8)) { - val = (val<0)?0:(256-(1<<upshift)); + val = (val < 0 ? 0 : 256 - (1<<upshift)); } *dest = (kdu_byte) val; } @@ -892,17 +933,17 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap) mNumComponents = tile.get_num_components(); - llassert(mNumComponents<=4); + llassert(mNumComponents <= 4); mUseYCC = tile.get_ycc(); - for (c=0; c<4; ++c) + for (c = 0; c < 4; ++c) { mReversible[c] = false; mBitDepths[c] = 0; } // Open tile-components and create processing engines and resources - for (c=0; c < mNumComponents; c++) + for (c = 0; c < mNumComponents; c++) { mComps[c] = mTile.access_component(c); mReversible[c] = mComps[c].get_reversible(); @@ -929,7 +970,7 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap) } } mAllocator.finalize(); // Actually creates buffering resources - for (c=0; c < mNumComponents; c++) + for (c = 0; c < mNumComponents; c++) { mLines[c].create(); // Grabs resources from the allocator. } @@ -937,13 +978,11 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap) LLKDUDecodeState::~LLKDUDecodeState() { - S32 c; // Cleanup - for (c=0; c < mNumComponents; c++) + for (S32 c = 0; c < mNumComponents; c++) { mEngines[c].destroy(); // engines are interfaces; no default destructors } - mTile.close(); } @@ -962,7 +1001,7 @@ separation between consecutive rows in the real buffer. */ LLTimer decode_timer; while (mDims.size.y--) { - for (c=0; c < mNumComponents; c++) + for (c = 0; c < mNumComponents; c++) { mEngines[c].pull(mLines[c],true); } @@ -970,7 +1009,7 @@ separation between consecutive rows in the real buffer. */ { kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]); } - for (c=0; c < mNumComponents; c++) + for (c = 0; c < mNumComponents; c++) { transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]); } @@ -990,96 +1029,100 @@ separation between consecutive rows in the real buffer. */ kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream) { - int n; - - this->codestream = codestream; - codestream.get_valid_tiles(valid_tile_indices); - tile_idx = valid_tile_indices.pos; - tile = codestream.open_tile(tile_idx,NULL); - - // Set up the individual components - num_components = codestream.get_num_components(true); - components = new kdc_component_flow_control[num_components]; - count_delta = 0; - kdc_component_flow_control *comp = components; - for (n = 0; n < num_components; n++, comp++) - { - comp->line = NULL; - comp->reader = img_in; - kdu_coords subsampling; - codestream.get_subsampling(n,subsampling,true); - kdu_dims dims; - codestream.get_tile_dims(tile_idx,n,dims,true); - comp->vert_subsampling = subsampling.y; - if ((n == 0) || (comp->vert_subsampling < count_delta)) - { - count_delta = comp->vert_subsampling; - } - comp->ratio_counter = 0; - comp->remaining_lines = comp->initial_lines = dims.size.y; - } - assert(num_components >= 0); - - tile.set_components_of_interest(num_components); - max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false); + int n; + + this->codestream = codestream; + codestream.get_valid_tiles(valid_tile_indices); + tile_idx = valid_tile_indices.pos; + tile = codestream.open_tile(tile_idx,NULL); + + // Set up the individual components + num_components = codestream.get_num_components(true); + components = new kdc_component_flow_control[num_components]; + count_delta = 0; + kdc_component_flow_control *comp = components; + for (n = 0; n < num_components; n++, comp++) + { + comp->line = NULL; + comp->reader = img_in; + kdu_coords subsampling; + codestream.get_subsampling(n,subsampling,true); + kdu_dims dims; + codestream.get_tile_dims(tile_idx,n,dims,true); + comp->vert_subsampling = subsampling.y; + if ((n == 0) || (comp->vert_subsampling < count_delta)) + { + count_delta = comp->vert_subsampling; + } + comp->ratio_counter = 0; + comp->remaining_lines = comp->initial_lines = dims.size.y; + } + assert(num_components >= 0); + + tile.set_components_of_interest(num_components); + max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false); } kdc_flow_control::~kdc_flow_control() { - if (components != NULL) - delete[] components; - if (engine.exists()) - engine.destroy(); + if (components != NULL) + { + delete[] components; + } + if (engine.exists()) + { + engine.destroy(); + } } bool kdc_flow_control::advance_components() { - bool found_line = false; - while (!found_line) - { - bool all_done = true; - kdc_component_flow_control *comp = components; - for (int n = 0; n < num_components; n++, comp++) - { - assert(comp->ratio_counter >= 0); - if (comp->remaining_lines > 0) - { - all_done = false; - comp->ratio_counter -= count_delta; - if (comp->ratio_counter < 0) - { - found_line = true; - comp->line = engine.exchange_line(n,NULL,NULL); - assert(comp->line != NULL); + bool found_line = false; + while (!found_line) + { + bool all_done = true; + kdc_component_flow_control *comp = components; + for (int n = 0; n < num_components; n++, comp++) + { + assert(comp->ratio_counter >= 0); + if (comp->remaining_lines > 0) + { + all_done = false; + comp->ratio_counter -= count_delta; + if (comp->ratio_counter < 0) + { + found_line = true; + comp->line = engine.exchange_line(n,NULL,NULL); + assert(comp->line != NULL); if (comp->line->get_width()) { comp->reader->get(n,*(comp->line),0); } - } - } - } - if (all_done) - { - return false; - } - } - return true; + } + } + } + if (all_done) + { + return false; + } + } + return true; } void kdc_flow_control::process_components() { - kdc_component_flow_control *comp = components; - for (int n = 0; n < num_components; n++, comp++) - { - if (comp->ratio_counter < 0) - { - comp->ratio_counter += comp->vert_subsampling; - assert(comp->ratio_counter >= 0); - assert(comp->remaining_lines > 0); - comp->remaining_lines--; - assert(comp->line != NULL); - engine.exchange_line(n,comp->line,NULL); - comp->line = NULL; - } - } + kdc_component_flow_control *comp = components; + for (int n = 0; n < num_components; n++, comp++) + { + if (comp->ratio_counter < 0) + { + comp->ratio_counter += comp->vert_subsampling; + assert(comp->ratio_counter >= 0); + assert(comp->remaining_lines > 0); + comp->remaining_lines--; + assert(comp->line != NULL); + engine.exchange_line(n,comp->line,NULL); + comp->line = NULL; + } + } } diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h index 5628f69eeb6b44796af332978547f31bce0d2493..9fce58b76258a3ea77512d606755e5f22ad2f96b 100644 --- a/indra/llkdu/llimagej2ckdu.h +++ b/indra/llkdu/llimagej2ckdu.h @@ -58,17 +58,21 @@ class LLImageJ2CKDU : public LLImageJ2CImpl /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count); /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible=FALSE); + /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); + /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1); private: + BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL); void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode); void cleanupCodeStream(); - BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ); // Encode variable LLKDUMemSource *mInputp; kdu_codestream *mCodeStreamp; kdu_coords *mTPosp; // tile position kdu_dims *mTileIndicesp; + int mBlocksSize; + int mPrecinctsSize; // Temporary variables for in-progress decodes... LLImageRaw *mRawImagep; diff --git a/indra/llkdu/llkdumem.cpp b/indra/llkdu/llkdumem.cpp index 1f549cbbe0daa23c0f439f976bc60ef55ce9f818..0347475559d8844c2530c0ce63905c31ba9cf566 100644 --- a/indra/llkdu/llkdumem.cpp +++ b/indra/llkdu/llkdumem.cpp @@ -47,12 +47,12 @@ LLKDUMemIn::LLKDUMemIn(const U8 *data, num_components = in_num_components; alignment_bytes = 0; - for (n=0; n<3; ++n) + for (n = 0; n < 3; ++n) { precision[n] = 0; } - for (n=0; n < num_components; ++n) + for (n = 0; n < num_components; ++n) { siz->set(Sdims,n,0,rows); siz->set(Sdims,n,1,cols); @@ -80,12 +80,12 @@ LLKDUMemIn::~LLKDUMemIn() } image_line_buf *tmp; while ((tmp=incomplete_lines) != NULL) - { + { incomplete_lines = tmp->next; delete tmp; } while ((tmp=free_lines) != NULL) - { + { free_lines = tmp->next; delete tmp; } @@ -98,16 +98,16 @@ bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum) assert((idx >= 0) && (idx < num_components)); x_tnum = x_tnum*num_components+idx; image_line_buf *scan, *prev=NULL; - for (scan=incomplete_lines; scan != NULL; prev=scan, scan=scan->next) - { + for (scan = incomplete_lines; scan != NULL; prev = scan, scan = scan->next) + { assert(scan->next_x_tnum >= x_tnum); if (scan->next_x_tnum == x_tnum) { break; } - } + } if (scan == NULL) - { // Need to read a new image line. + { // Need to read a new image line. assert(x_tnum == 0); // Must consume in very specific order. if (num_unread_rows == 0) { @@ -134,7 +134,7 @@ bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum) num_unread_rows--; scan->accessed_samples = 0; scan->next_x_tnum = 0; - } + } assert((cols-scan->accessed_samples) >= line.get_width()); @@ -161,7 +161,7 @@ bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum) } } else - { + { kdu_sample16 *dp = line.get_buf16(); if (line.is_absolute()) { // 16-bit absolute integers @@ -177,7 +177,7 @@ bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum) dp->ival = (((kdu_int16)(*sp)) - 128) << (KDU_FIX_POINT-8); } } - } + } scan->next_x_tnum++; if (idx == (num_components-1)) diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h index 7064de4408d682aa87972804c592cfd917646bfd..9d923fc3674b2a7cfdb5ab0cf527270e4efae136 100644 --- a/indra/llkdu/llkdumem.h +++ b/indra/llkdu/llkdumem.h @@ -39,7 +39,7 @@ class LLKDUMemSource: public kdu_compressed_source { -public: // Member functions +public: LLKDUMemSource(U8 *input_buffer, U32 size) { mData = input_buffer; @@ -47,11 +47,11 @@ class LLKDUMemSource: public kdu_compressed_source mCurPos = 0; } - ~LLKDUMemSource() + ~LLKDUMemSource() { } - int read(kdu_byte *buf, int num_bytes) + int read(kdu_byte *buf, int num_bytes) { U32 num_out; num_out = num_bytes; @@ -70,7 +70,7 @@ class LLKDUMemSource: public kdu_compressed_source mCurPos = 0; } -private: // Data +private: U8 *mData; U32 mSize; U32 mCurPos; @@ -78,7 +78,7 @@ class LLKDUMemSource: public kdu_compressed_source class LLKDUMemTarget: public kdu_compressed_target { -public: // Member functions +public: LLKDUMemTarget(U8 *output_buffer, U32 &output_size, const U32 buffer_size) { mData = output_buffer; @@ -87,11 +87,11 @@ class LLKDUMemTarget: public kdu_compressed_target mOutputSize = &output_size; } - ~LLKDUMemTarget() - { + ~LLKDUMemTarget() + { } - bool write(const kdu_byte *buf, int num_bytes) + bool write(const kdu_byte *buf, int num_bytes) { U32 num_out; num_out = num_bytes; @@ -108,7 +108,7 @@ class LLKDUMemTarget: public kdu_compressed_target return true; } -private: // Data +private: U8 *mData; U32 mSize; U32 mCurPos; @@ -117,27 +117,27 @@ class LLKDUMemTarget: public kdu_compressed_target class LLKDUMemIn : public kdu_image_in_base { -public: // Member functions - LLKDUMemIn(const U8 *data, +public: + LLKDUMemIn(const U8 *data, const U32 size, const U16 rows, const U16 cols, U8 in_num_components, siz_params *siz); - ~LLKDUMemIn(); + ~LLKDUMemIn(); - bool get(int comp_idx, kdu_line_buf &line, int x_tnum); + bool get(int comp_idx, kdu_line_buf &line, int x_tnum); -private: // Data +private: const U8 *mData; - int first_comp_idx; - int num_components; - int rows, cols; - int alignment_bytes; // Number of 0's at end of each line. - int precision[3]; - image_line_buf *incomplete_lines; // Each "sample" represents a full pixel - image_line_buf *free_lines; - int num_unread_rows; + int first_comp_idx; + int num_components; + int rows, cols; + int alignment_bytes; // Number of 0's at end of each line. + int precision[3]; + image_line_buf *incomplete_lines; // Each "sample" represents a full pixel + image_line_buf *free_lines; + int num_unread_rows; U32 mCurPos; U32 mDataSize; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index dc360818d69b5cf3a964eb9e14ad36f233d51cbb..70e1e1f312e5b17c3351bcc9732ed665f0cf3987 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1,7233 +1,7233 @@ -/** - - * @file llvolume.cpp - * - * $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 "llmemory.h" -#include "llmath.h" - -#include <set> -#if !LL_WINDOWS -#include <stdint.h> -#endif - -#include "llerror.h" -#include "llmemtype.h" - -#include "llvolumemgr.h" -#include "v2math.h" -#include "v3math.h" -#include "v4math.h" -#include "m4math.h" -#include "m3math.h" -#include "llmatrix3a.h" -#include "lloctree.h" -#include "lldarray.h" -#include "llvolume.h" -#include "llvolumeoctree.h" -#include "llstl.h" -#include "llsdserialize.h" -#include "llvector4a.h" -#include "llmatrix4a.h" - -#define DEBUG_SILHOUETTE_BINORMALS 0 -#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette -#define DEBUG_SILHOUETTE_EDGE_MAP 0 // DaveP: Use this to display edge map using the silhouette - -const F32 CUT_MIN = 0.f; -const F32 CUT_MAX = 1.f; -const F32 MIN_CUT_DELTA = 0.02f; - -const F32 HOLLOW_MIN = 0.f; -const F32 HOLLOW_MAX = 0.95f; -const F32 HOLLOW_MAX_SQUARE = 0.7f; - -const F32 TWIST_MIN = -1.f; -const F32 TWIST_MAX = 1.f; - -const F32 RATIO_MIN = 0.f; -const F32 RATIO_MAX = 2.f; // Tom Y: Inverted sense here: 0 = top taper, 2 = bottom taper - -const F32 HOLE_X_MIN= 0.05f; -const F32 HOLE_X_MAX= 1.0f; - -const F32 HOLE_Y_MIN= 0.05f; -const F32 HOLE_Y_MAX= 0.5f; - -const F32 SHEAR_MIN = -0.5f; -const F32 SHEAR_MAX = 0.5f; - -const F32 REV_MIN = 1.f; -const F32 REV_MAX = 4.f; - -const F32 TAPER_MIN = -1.f; -const F32 TAPER_MAX = 1.f; - -const F32 SKEW_MIN = -0.95f; -const F32 SKEW_MAX = 0.95f; - -const F32 SCULPT_MIN_AREA = 0.002f; -const S32 SCULPT_MIN_AREA_DETAIL = 1; - -extern BOOL gDebugGL; - -void assert_aligned(void* ptr, uintptr_t alignment) -{ -#if 0 - uintptr_t t = (uintptr_t) ptr; - if (t%alignment != 0) - { - llerrs << "WTF?" << llendl; - } -#endif -} - -BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) -{ - LLVector3 test = (pt2-pt1)%(pt3-pt2); - - //answer - if(test * norm < 0) - { - return FALSE; - } - else - { - return TRUE; - } -} - -BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) -{ - return LLLineSegmentBoxIntersect(start.mV, end.mV, center.mV, size.mV); -} - -BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size) -{ - F32 fAWdU[3]; - F32 dir[3]; - F32 diff[3]; - - for (U32 i = 0; i < 3; i++) - { - dir[i] = 0.5f * (end[i] - start[i]); - diff[i] = (0.5f * (end[i] + start[i])) - center[i]; - fAWdU[i] = fabsf(dir[i]); - if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; - } - - float f; - f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; - f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; - f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; - - return true; -} - - - -// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. -// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, -// and returns the intersection point along dir in intersection_t. - -// Moller-Trumbore algorithm -BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - LLVector4a det; - det.setAllDot3(edge1, pvec); - - if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) - { - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - LLVector4a u; - u.setAllDot3(tvec,pvec); - - if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && - (u.lessEqual(det).getGatheredBits() & 0x7)) - { - /* prepare to test V parameter */ - LLVector4a qvec; - qvec.setCross3(tvec, edge1); - - /* calculate V parameter and test bounds */ - LLVector4a v; - v.setAllDot3(dir, qvec); - - - //if (!(v < 0.f || u + v > det)) - - LLVector4a sum_uv; - sum_uv.setAdd(u, v); - - S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; - S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; - - if (v_gequal && sum_lequal) - { - /* calculate t, scale parameters, ray intersects triangle */ - LLVector4a t; - t.setAllDot3(edge2,qvec); - - t.div(det); - u.div(det); - v.div(det); - - intersection_a = u[0]; - intersection_b = v[0]; - intersection_t = t[0]; - return TRUE; - } - } - } - - return FALSE; -} - -BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - F32 u, v, t; - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1.dot3(pvec).getF32(); - - - if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) - { - return FALSE; - } - - F32 inv_det = 1.f / det; - - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - u = (tvec.dot3(pvec).getF32()) * inv_det; - if (u < 0.f || u > 1.f) - { - return FALSE; - } - - /* prepare to test V parameter */ - tvec.sub(edge1); - - /* calculate V parameter and test bounds */ - v = (dir.dot3(tvec).getF32()) * inv_det; - - if (v < 0.f || u + v > 1.f) - { - return FALSE; - } - - /* calculate t, ray intersects triangle */ - t = (edge2.dot3(tvec).getF32()) * inv_det; - - intersection_a = u; - intersection_b = v; - intersection_t = t; - - - return TRUE; -} - -//helper for non-aligned vectors -BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided) -{ - LLVector4a vert0a, vert1a, vert2a, origa, dira; - vert0a.load3(vert0.mV); - vert1a.load3(vert1.mV); - vert2a.load3(vert2.mV); - origa.load3(orig.mV); - dira.load3(dir.mV); - - if (two_sided) - { - return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira, - intersection_a, intersection_b, intersection_t); - } - else - { - return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira, - intersection_a, intersection_b, intersection_t); - } -} - -class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle> -{ -public: - const LLVolumeFace* mFace; - - LLVolumeOctreeRebound(const LLVolumeFace* face) - { - mFace = face; - } - - virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) - { //this is a depth first traversal, so it's safe to assum all children have complete - //bounding data - - LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); - - LLVector4a& min = node->mExtents[0]; - LLVector4a& max = node->mExtents[1]; - - if (!branch->getData().empty()) - { //node has data, find AABB that binds data set - const LLVolumeTriangle* tri = *(branch->getData().begin()); - - //initialize min/max to first available vertex - min = *(tri->mV[0]); - max = *(tri->mV[0]); - - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - branch->getData().begin(); iter != branch->getData().end(); ++iter) - { //for each triangle in node - - //stretch by triangles in node - tri = *iter; - - min.setMin(min, *tri->mV[0]); - min.setMin(min, *tri->mV[1]); - min.setMin(min, *tri->mV[2]); - - max.setMax(max, *tri->mV[0]); - max.setMax(max, *tri->mV[1]); - max.setMax(max, *tri->mV[2]); - } - } - else if (!branch->getChildren().empty()) - { //no data, but child nodes exist - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); - - //initialize min/max to extents of first child - min = child->mExtents[0]; - max = child->mExtents[1]; - } - else - { - llerrs << "WTF? Empty leaf" << llendl; - } - - for (S32 i = 0; i < branch->getChildCount(); ++i) - { //stretch by child extents - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - min.setMin(min, child->mExtents[0]); - max.setMax(max, child->mExtents[1]); - } - - node->mBounds[0].setAdd(min, max); - node->mBounds[0].mul(0.5f); - - node->mBounds[1].setSub(max,min); - node->mBounds[1].mul(0.5f); - } -}; - -//------------------------------------------------------------------- -// statics -//------------------------------------------------------------------- - - -//---------------------------------------------------- - -LLProfile::Face* LLProfile::addCap(S16 faceID) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - Face *face = vector_append(mFaces, 1); - - face->mIndex = 0; - face->mCount = mTotal; - face->mScaleU= 1.0f; - face->mCap = TRUE; - face->mFaceID = faceID; - return face; -} - -LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BOOL flat) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - Face *face = vector_append(mFaces, 1); - - face->mIndex = i; - face->mCount = count; - face->mScaleU= scaleU; - - face->mFlat = flat; - face->mCap = FALSE; - face->mFaceID = faceID; - return face; -} - -// What is the bevel parameter used for? - DJS 04/05/02 -// Bevel parameter is currently unused but presumedly would support -// filleted and chamfered corners -void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - // Generate an n-sided "circular" path. - // 0 is (1,0), and we go counter-clockwise along a circular path from there. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - F32 scale = 0.5f; - F32 t, t_step, t_first, t_fraction, ang, ang_step; - LLVector3 pt1,pt2; - - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - - t_step = 1.0f / sides; - ang_step = 2.0f*F_PI*t_step*ang_scale; - - // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. - - S32 total_sides = llround(sides / ang_scale); // Total number of sides all around - - if (total_sides < 8) - { - scale = tableScale[total_sides]; - } - - t_first = floor(begin * sides) / (F32)sides; - - // pt1 is the first point on the fractional face. - // Starting t and ang values for the first face - t = t_first; - ang = 2.0f*F_PI*(t*ang_scale + offset); - pt1.setVec(cos(ang)*scale,sin(ang)*scale, t); - - // Increment to the next point. - // pt2 is the end point on the fractional face - t += t_step; - ang += ang_step; - pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); - - t_fraction = (begin - t_first)*sides; - - // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.9999f) - { - LLVector3 new_pt = lerp(pt1, pt2, t_fraction); - mProfile.push_back(new_pt); - } - - // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 - while (t < end) - { - // Iterate through all the integer steps of t. - pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); - - if (mProfile.size() > 0) { - LLVector3 p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); - } - } - mProfile.push_back(pt1); - - t += t_step; - ang += ang_step; - } - - t_fraction = (end - (t - t_step))*sides; - - // pt1 is the first point on the fractional face - // pt2 is the end point on the fractional face - pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); - - // Find the fraction that we need to add to the end point. - t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.0001f) - { - LLVector3 new_pt = lerp(pt1, pt2, t_fraction); - - if (mProfile.size() > 0) { - LLVector3 p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); - } - } - mProfile.push_back(new_pt); - } - - // If we're sliced, the profile is open. - if ((end - begin)*ang_scale < 0.99f) - { - if ((end - begin)*ang_scale > 0.5f) - { - mConcave = TRUE; - } - else - { - mConcave = FALSE; - } - mOpen = TRUE; - if (params.getHollow() <= 0) - { - // put center point if not hollow. - mProfile.push_back(LLVector3(0,0,0)); - } - } - else - { - // The profile isn't open. - mOpen = FALSE; - mConcave = FALSE; - } - - mTotal = mProfile.size(); -} - -void LLProfile::genNormals(const LLProfileParams& params) -{ - S32 count = mProfile.size(); - - S32 outer_count; - if (mTotalOut) - { - outer_count = mTotalOut; - } - else - { - outer_count = mTotal / 2; - } - - mEdgeNormals.resize(count * 2); - mEdgeCenters.resize(count * 2); - mNormals.resize(count); - - LLVector2 pt0,pt1; - - BOOL hollow = (params.getHollow() > 0); - - S32 i0, i1, i2, i3, i4; - - // Parametrically generate normal - for (i2 = 0; i2 < count; i2++) - { - mNormals[i2].mV[0] = mProfile[i2].mV[0]; - mNormals[i2].mV[1] = mProfile[i2].mV[1]; - if (hollow && (i2 >= outer_count)) - { - mNormals[i2] *= -1.f; - } - if (mNormals[i2].magVec() < 0.001) - { - // Special case for point at center, get adjacent points. - i1 = (i2 - 1) >= 0 ? i2 - 1 : count - 1; - i0 = (i1 - 1) >= 0 ? i1 - 1 : count - 1; - i3 = (i2 + 1) < count ? i2 + 1 : 0; - i4 = (i3 + 1) < count ? i3 + 1 : 0; - - pt0.setVec(mProfile[i1].mV[VX] + mProfile[i1].mV[VX] - mProfile[i0].mV[VX], - mProfile[i1].mV[VY] + mProfile[i1].mV[VY] - mProfile[i0].mV[VY]); - pt1.setVec(mProfile[i3].mV[VX] + mProfile[i3].mV[VX] - mProfile[i4].mV[VX], - mProfile[i3].mV[VY] + mProfile[i3].mV[VY] - mProfile[i4].mV[VY]); - - mNormals[i2] = pt0 + pt1; - mNormals[i2] *= 0.5f; - } - mNormals[i2].normVec(); - } - - S32 num_normal_sets = isConcave() ? 2 : 1; - for (S32 normal_set = 0; normal_set < num_normal_sets; normal_set++) - { - S32 point_num; - for (point_num = 0; point_num < mTotal; point_num++) - { - LLVector3 point_1 = mProfile[point_num]; - point_1.mV[VZ] = 0.f; - - LLVector3 point_2; - - if (isConcave() && normal_set == 0 && point_num == (mTotal - 1) / 2) - { - point_2 = mProfile[mTotal - 1]; - } - else if (isConcave() && normal_set == 1 && point_num == mTotal - 1) - { - point_2 = mProfile[(mTotal - 1) / 2]; - } - else - { - LLVector3 delta_pos; - S32 neighbor_point = (point_num + 1) % mTotal; - while(delta_pos.magVecSquared() < 0.01f * 0.01f) - { - point_2 = mProfile[neighbor_point]; - delta_pos = point_2 - point_1; - neighbor_point = (neighbor_point + 1) % mTotal; - if (neighbor_point == point_num) - { - break; - } - } - } - - point_2.mV[VZ] = 0.f; - LLVector3 face_normal = (point_2 - point_1) % LLVector3::z_axis; - face_normal.normVec(); - mEdgeNormals[normal_set * count + point_num] = face_normal; - mEdgeCenters[normal_set * count + point_num] = lerp(point_1, point_2, 0.5f); - } - } -} - - -// Hollow is percent of the original bounding box, not of this particular -// profile's geometry. Thus, a swept triangle needs lower hollow values than -// a swept square. -LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split) -{ - // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. - - // Total add has number of vertices on outside. - mTotalOut = mTotal; - - // Why is the "bevel" parameter -1? DJS 04/05/02 - genNGon(params, llfloor(sides),offset,-1, ang_scale, split); - - Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); - - std::vector<LLVector3> pt; - pt.resize(mTotal) ; - - for (S32 i=mTotalOut;i<mTotal;i++) - { - pt[i] = mProfile[i] * box_hollow; - } - - S32 j=mTotal-1; - for (S32 i=mTotalOut;i<mTotal;i++) - { - mProfile[i] = pt[j--]; - } - - for (S32 i=0;i<(S32)mFaces.size();i++) - { - if (mFaces[i].mCap) - { - mFaces[i].mCount *= 2; - } - } - - return face; -} - - - -BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, - BOOL is_sculpted, S32 sculpt_size) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - if ((!mDirty) && (!is_sculpted)) - { - return FALSE; - } - mDirty = FALSE; - - if (detail < MIN_LOD) - { - llinfos << "Generating profile with LOD < MIN_LOD. CLAMPING" << llendl; - detail = MIN_LOD; - } - - mProfile.clear(); - mFaces.clear(); - - // Generate the face data - S32 i; - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - F32 hollow = params.getHollow(); - - // Quick validation to eliminate some server crashes. - if (begin > end - 0.01f) - { - llwarns << "LLProfile::generate() assertion failed (begin >= end)" << llendl; - return FALSE; - } - - S32 face_num = 0; - - switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_SQUARE: - { - genNGon(params, 4,-0.375, 0, 1, split); - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); - } - - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 4 to generate proper tex coords. - mProfile[i].mV[2] *= 4.f; - } - - if (hollow) - { - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_TRIANGLE: - // This offset is not correct, but we can't change it now... DK 11/17/04 - addHole(params, TRUE, 3, -0.375f, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - // TODO: Compute actual detail levels for cubes - addHole(params, FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_SQUARE: - default: - addHole(params, TRUE, 4, -0.375f, hollow, 1.f, split); - break; - } - } - - if (path_open) { - mFaces[0].mCount = mTotal; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - case LL_PCODE_PROFILE_EQUALTRI: - { - genNGon(params, 3,0, 0, 1, split); - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 3 to generate proper tex coords. - mProfile[i].mV[2] *= 3.f; - } - - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); - } - if (hollow) - { - // Swept triangles need smaller hollowness values, - // because the triangle doesn't fill the bounding box. - F32 triangle_hollow = hollow / 2.f; - - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_CIRCLE: - // TODO: Actually generate level of detail for triangles - addHole(params, FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); - break; - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 4, 0, triangle_hollow, 1.f, split); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_TRIANGLE: - default: - addHole(params, TRUE, 3, 0, triangle_hollow, 1.f, split); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - F32 circle_detail = MIN_DETAIL_FACES * detail; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides, - // so that corners line up. - circle_detail = llceil(circle_detail / 4.0f) * 4.0f; - } - } - - S32 sides = (S32)circle_detail; - - if (is_sculpted) - sides = sculpt_size; - - genNGon(params, sides); - - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - if (mOpen && !hollow) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 4, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, TRUE, 3, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, FALSE, circle_detail, 0, hollow, 1.f); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE_HALF: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - // Number of faces is cut in half because it's only a half-circle. - F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides (div 2), - // so that corners line up. - circle_detail = llceil(circle_detail / 2.0f) * 2.0f; - } - } - genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - if (mOpen && !params.getHollow()) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 2, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, TRUE, 3, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, FALSE, circle_detail, 0.5f, hollow, 0.5f); - break; - } - } - - // Special case for openness of sphere - if ((params.getEnd() - params.getBegin()) < 1.f) - { - mOpen = TRUE; - } - else if (!hollow) - { - mOpen = FALSE; - mProfile.push_back(mProfile[0]); - mTotal++; - } - } - break; - default: - llerrs << "Unknown profile: getCurveType()=" << params.getCurveType() << llendl; - break; - }; - - if (path_open) - { - addCap(LL_FACE_PATH_END); // bottom - } - - if ( mOpen) // interior edge caps - { - addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, TRUE); - - if (hollow) - { - addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, TRUE); - } - else - { - addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE); - } - } - - //genNormals(params); - - return TRUE; -} - - - -BOOL LLProfileParams::importFile(LLFILE *fp) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - llwarns << "unknown keyword " << keyword << " in profile import" << llendl; - } - } - - return TRUE; -} - - -BOOL LLProfileParams::exportFile(LLFILE *fp) const -{ - fprintf(fp,"\t\tprofile 0\n"); - fprintf(fp,"\t\t{\n"); - fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); - fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); - fprintf(fp,"\t\t\tend\t%g\n", getEnd()); - fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); - fprintf(fp, "\t\t}\n"); - return TRUE; -} - - -BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, - valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - llwarns << "unknown keyword " << keyword << " in profile import" << llendl; - } - } - - return TRUE; -} - - -BOOL LLProfileParams::exportLegacyStream(std::ostream& output_stream) const -{ - output_stream <<"\t\tprofile 0\n"; - output_stream <<"\t\t{\n"; - output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; - output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; - output_stream <<"\t\t\tend\t" << getEnd() << "\n"; - output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; - output_stream << "\t\t}\n"; - return TRUE; -} - -LLSD LLProfileParams::asLLSD() const -{ - LLSD sd; - - sd["curve"] = getCurveType(); - sd["begin"] = getBegin(); - sd["end"] = getEnd(); - sd["hollow"] = getHollow(); - return sd; -} - -bool LLProfileParams::fromLLSD(LLSD& sd) -{ - setCurveType(sd["curve"].asInteger()); - setBegin((F32)sd["begin"].asReal()); - setEnd((F32)sd["end"].asReal()); - setHollow((F32)sd["hollow"].asReal()); - return true; -} - -void LLProfileParams::copyParams(const LLProfileParams ¶ms) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - setCurveType(params.getCurveType()); - setBegin(params.getBegin()); - setEnd(params.getEnd()); - setHollow(params.getHollow()); -} - - -LLPath::~LLPath() -{ -} - -void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) -{ - // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - - F32 revolutions = params.getRevolutions(); - F32 skew = params.getSkew(); - F32 skew_mag = fabs(skew); - F32 hole_x = params.getScaleX() * (1.0f - skew_mag); - F32 hole_y = params.getScaleY(); - - // Calculate taper begin/end for x,y (Negative means taper the beginning) - F32 taper_x_begin = 1.0f; - F32 taper_x_end = 1.0f - params.getTaperX(); - F32 taper_y_begin = 1.0f; - F32 taper_y_end = 1.0f - params.getTaperY(); - - if ( taper_x_end > 1.0f ) - { - // Flip tapering. - taper_x_begin = 2.0f - taper_x_end; - taper_x_end = 1.0f; - } - if ( taper_y_end > 1.0f ) - { - // Flip tapering. - taper_y_begin = 2.0f - taper_y_end; - taper_y_end = 1.0f; - } - - // For spheres, the radius is usually zero. - F32 radius_start = 0.5f; - if (sides < 8) - { - radius_start = tableScale[sides]; - } - - // Scale the radius to take the hole size into account. - radius_start *= 1.0f - hole_y; - - // Now check the radius offset to calculate the start,end radius. (Negative means - // decrease the start radius instead). - F32 radius_end = radius_start; - F32 radius_offset = params.getRadiusOffset(); - if (radius_offset < 0.f) - { - radius_start *= 1.f + radius_offset; - } - else - { - radius_end *= 1.f - radius_offset; - } - - // Is the path NOT a closed loop? - mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || - (skew_mag > 0.001f) || - (fabs(taper_x_end - taper_x_begin) > 0.001f) || - (fabs(taper_y_end - taper_y_begin) > 0.001f) || - (fabs(radius_end - radius_start) > 0.001f) ); - - F32 ang, c, s; - LLQuaternion twist, qang; - PathPt *pt; - LLVector3 path_axis (1.f, 0.f, 0.f); - //LLVector3 twist_axis(0.f, 0.f, 1.f); - F32 twist_begin = params.getTwistBegin() * twist_scale; - F32 twist_end = params.getTwist() * twist_scale; - - // We run through this once before the main loop, to make sure - // the path begins at the correct cut. - F32 step= 1.0f / sides; - F32 t = params.getBegin(); - pt = vector_append(mPath, 1); - ang = 2.0f*F_PI*revolutions * t; - s = sin(ang)*lerp(radius_start, radius_end, t); - c = cos(ang)*lerp(radius_start, radius_end, t); - - - pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); - pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - pt->mRot = twist * qang; - - t+=step; - - // Snap to a quantized parameter, so that cut does not - // affect most sample points. - t = ((S32)(t * sides)) / (F32)sides; - - // Run through the non-cut dependent points. - while (t < params.getEnd()) - { - pt = vector_append(mPath, 1); - - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - - pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); - pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - pt->mRot = twist * qang; - - t+=step; - } - - // Make one final pass for the end cut. - t = params.getEnd(); - pt = vector_append(mPath, 1); - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); - pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - pt->mRot = twist * qang; - - mTotal = mPath.size(); -} - -const LLVector2 LLPathParams::getBeginScale() const -{ - LLVector2 begin_scale(1.f, 1.f); - if (getScaleX() > 1) - { - begin_scale.mV[0] = 2-getScaleX(); - } - if (getScaleY() > 1) - { - begin_scale.mV[1] = 2-getScaleY(); - } - return begin_scale; -} - -const LLVector2 LLPathParams::getEndScale() const -{ - LLVector2 end_scale(1.f, 1.f); - if (getScaleX() < 1) - { - end_scale.mV[0] = getScaleX(); - } - if (getScaleY() < 1) - { - end_scale.mV[1] = getScaleY(); - } - return end_scale; -} - -BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, - BOOL is_sculpted, S32 sculpt_size) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - if ((!mDirty) && (!is_sculpted)) - { - return FALSE; - } - - if (detail < MIN_LOD) - { - llinfos << "Generating path with LOD < MIN! Clamping to 1" << llendl; - detail = MIN_LOD; - } - - mDirty = FALSE; - S32 np = 2; // hardcode for line - - mPath.clear(); - mOpen = TRUE; - - // Is this 0xf0 mask really necessary? DK 03/02/05 - switch (params.getCurveType() & 0xf0) - { - default: - case LL_PCODE_PATH_LINE: - { - // Take the begin/end twist into account for detail. - np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; - if (np < split+2) - { - np = split+2; - } - - mStep = 1.0f / (np-1); - - mPath.resize(np); - - LLVector2 start_scale = params.getBeginScale(); - LLVector2 end_scale = params.getEndScale(); - - for (S32 i=0;i<np;i++) - { - F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); - mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t), - lerp(0,params.getShear().mV[1],t), - t - 0.5f); - mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); - mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t); - mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t); - mPath[i].mTexT = t; - } - } - break; - - case LL_PCODE_PATH_CIRCLE: - { - // Increase the detail as the revolutions and twist increase. - F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); - - S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); - - if (is_sculpted) - sides = sculpt_size; - - genNGon(params, sides); - } - break; - - case LL_PCODE_PATH_CIRCLE2: - { - if (params.getEnd() - params.getBegin() >= 0.99f && - params.getScaleX() >= .99f) - { - mOpen = FALSE; - } - - //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); - genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); - - F32 t = 0.f; - F32 tStep = 1.0f / mPath.size(); - - F32 toggle = 0.5f; - for (S32 i=0;i<(S32)mPath.size();i++) - { - mPath[i].mPos.mV[0] = toggle; - if (toggle == 0.5f) - toggle = -0.5f; - else - toggle = 0.5f; - t += tStep; - } - } - - break; - - case LL_PCODE_PATH_TEST: - - np = 5; - mStep = 1.0f / (np-1); - - mPath.resize(np); - - for (S32 i=0;i<np;i++) - { - F32 t = (F32)i * mStep; - mPath[i].mPos.setVec(0, - lerp(0, -sin(F_PI*params.getTwist()*t)*0.5f,t), - lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t)); - mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t); - mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t); - mPath[i].mTexT = t; - mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0); - } - - break; - }; - - if (params.getTwist() != params.getTwistBegin()) mOpen = TRUE; - - //if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) { - // mOpen = TRUE; - //} - - return TRUE; -} - -BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, - BOOL is_sculpted, S32 sculpt_size) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - mOpen = TRUE; // Draw end caps - if (getPathLength() == 0) - { - // Path hasn't been generated yet. - // Some algorithms later assume at least TWO path points. - resizePath(2); - for (U32 i = 0; i < 2; i++) - { - mPath[i].mPos.setVec(0, 0, 0); - mPath[i].mRot.setQuat(0, 0, 0); - mPath[i].mScale.setVec(1, 1); - mPath[i].mTexT = 0; - } - } - - return TRUE; -} - - -BOOL LLPathParams::importFile(LLFILE *fp) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - - F32 tempF32; - F32 x, y; - U32 tempU32; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("scale",keyword)) - { - // Legacy for one dimensional scale per path - sscanf(valuestr,"%g",&tempF32); - setScale(tempF32, tempF32); - } - else if (!strcmp("scale_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setScaleX(x); - } - else if (!strcmp("scale_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setScaleY(y); - } - else if (!strcmp("shear_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setShearX(x); - } - else if (!strcmp("shear_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setShearY(y); - } - else if (!strcmp("twist",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setTwist(tempF32); - } - else if (!strcmp("twist_begin", keyword)) - { - sscanf(valuestr, "%g", &y); - setTwistBegin(y); - } - else if (!strcmp("radius_offset", keyword)) - { - sscanf(valuestr, "%g", &y); - setRadiusOffset(y); - } - else if (!strcmp("taper_x", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperX(y); - } - else if (!strcmp("taper_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperY(y); - } - else if (!strcmp("revolutions", keyword)) - { - sscanf(valuestr, "%g", &y); - setRevolutions(y); - } - else if (!strcmp("skew", keyword)) - { - sscanf(valuestr, "%g", &y); - setSkew(y); - } - else - { - llwarns << "unknown keyword " << " in path import" << llendl; - } - } - return TRUE; -} - - -BOOL LLPathParams::exportFile(LLFILE *fp) const -{ - fprintf(fp, "\t\tpath 0\n"); - fprintf(fp, "\t\t{\n"); - fprintf(fp, "\t\t\tcurve\t%d\n", getCurveType()); - fprintf(fp, "\t\t\tbegin\t%g\n", getBegin()); - fprintf(fp, "\t\t\tend\t%g\n", getEnd()); - fprintf(fp, "\t\t\tscale_x\t%g\n", getScaleX() ); - fprintf(fp, "\t\t\tscale_y\t%g\n", getScaleY() ); - fprintf(fp, "\t\t\tshear_x\t%g\n", getShearX() ); - fprintf(fp, "\t\t\tshear_y\t%g\n", getShearY() ); - fprintf(fp,"\t\t\ttwist\t%g\n", getTwist()); - - fprintf(fp,"\t\t\ttwist_begin\t%g\n", getTwistBegin()); - fprintf(fp,"\t\t\tradius_offset\t%g\n", getRadiusOffset()); - fprintf(fp,"\t\t\ttaper_x\t%g\n", getTaperX()); - fprintf(fp,"\t\t\ttaper_y\t%g\n", getTaperY()); - fprintf(fp,"\t\t\trevolutions\t%g\n", getRevolutions()); - fprintf(fp,"\t\t\tskew\t%g\n", getSkew()); - - fprintf(fp, "\t\t}\n"); - return TRUE; -} - - -BOOL LLPathParams::importLegacyStream(std::istream& input_stream) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - - F32 tempF32; - F32 x, y; - U32 tempU32; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("scale",keyword)) - { - // Legacy for one dimensional scale per path - sscanf(valuestr,"%g",&tempF32); - setScale(tempF32, tempF32); - } - else if (!strcmp("scale_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setScaleX(x); - } - else if (!strcmp("scale_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setScaleY(y); - } - else if (!strcmp("shear_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setShearX(x); - } - else if (!strcmp("shear_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setShearY(y); - } - else if (!strcmp("twist",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setTwist(tempF32); - } - else if (!strcmp("twist_begin", keyword)) - { - sscanf(valuestr, "%g", &y); - setTwistBegin(y); - } - else if (!strcmp("radius_offset", keyword)) - { - sscanf(valuestr, "%g", &y); - setRadiusOffset(y); - } - else if (!strcmp("taper_x", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperX(y); - } - else if (!strcmp("taper_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperY(y); - } - else if (!strcmp("revolutions", keyword)) - { - sscanf(valuestr, "%g", &y); - setRevolutions(y); - } - else if (!strcmp("skew", keyword)) - { - sscanf(valuestr, "%g", &y); - setSkew(y); - } - else - { - llwarns << "unknown keyword " << " in path import" << llendl; - } - } - return TRUE; -} - - -BOOL LLPathParams::exportLegacyStream(std::ostream& output_stream) const -{ - output_stream << "\t\tpath 0\n"; - output_stream << "\t\t{\n"; - output_stream << "\t\t\tcurve\t" << (S32) getCurveType() << "\n"; - output_stream << "\t\t\tbegin\t" << getBegin() << "\n"; - output_stream << "\t\t\tend\t" << getEnd() << "\n"; - output_stream << "\t\t\tscale_x\t" << getScaleX() << "\n"; - output_stream << "\t\t\tscale_y\t" << getScaleY() << "\n"; - output_stream << "\t\t\tshear_x\t" << getShearX() << "\n"; - output_stream << "\t\t\tshear_y\t" << getShearY() << "\n"; - output_stream <<"\t\t\ttwist\t" << getTwist() << "\n"; - - output_stream <<"\t\t\ttwist_begin\t" << getTwistBegin() << "\n"; - output_stream <<"\t\t\tradius_offset\t" << getRadiusOffset() << "\n"; - output_stream <<"\t\t\ttaper_x\t" << getTaperX() << "\n"; - output_stream <<"\t\t\ttaper_y\t" << getTaperY() << "\n"; - output_stream <<"\t\t\trevolutions\t" << getRevolutions() << "\n"; - output_stream <<"\t\t\tskew\t" << getSkew() << "\n"; - - output_stream << "\t\t}\n"; - return TRUE; -} - -LLSD LLPathParams::asLLSD() const -{ - LLSD sd = LLSD(); - sd["curve"] = getCurveType(); - sd["begin"] = getBegin(); - sd["end"] = getEnd(); - sd["scale_x"] = getScaleX(); - sd["scale_y"] = getScaleY(); - sd["shear_x"] = getShearX(); - sd["shear_y"] = getShearY(); - sd["twist"] = getTwist(); - sd["twist_begin"] = getTwistBegin(); - sd["radius_offset"] = getRadiusOffset(); - sd["taper_x"] = getTaperX(); - sd["taper_y"] = getTaperY(); - sd["revolutions"] = getRevolutions(); - sd["skew"] = getSkew(); - - return sd; -} - -bool LLPathParams::fromLLSD(LLSD& sd) -{ - setCurveType(sd["curve"].asInteger()); - setBegin((F32)sd["begin"].asReal()); - setEnd((F32)sd["end"].asReal()); - setScaleX((F32)sd["scale_x"].asReal()); - setScaleY((F32)sd["scale_y"].asReal()); - setShearX((F32)sd["shear_x"].asReal()); - setShearY((F32)sd["shear_y"].asReal()); - setTwist((F32)sd["twist"].asReal()); - setTwistBegin((F32)sd["twist_begin"].asReal()); - setRadiusOffset((F32)sd["radius_offset"].asReal()); - setTaperX((F32)sd["taper_x"].asReal()); - setTaperY((F32)sd["taper_y"].asReal()); - setRevolutions((F32)sd["revolutions"].asReal()); - setSkew((F32)sd["skew"].asReal()); - return true; -} - -void LLPathParams::copyParams(const LLPathParams ¶ms) -{ - setCurveType(params.getCurveType()); - setBegin(params.getBegin()); - setEnd(params.getEnd()); - setScale(params.getScaleX(), params.getScaleY() ); - setShear(params.getShearX(), params.getShearY() ); - setTwist(params.getTwist()); - setTwistBegin(params.getTwistBegin()); - setRadiusOffset(params.getRadiusOffset()); - setTaper( params.getTaperX(), params.getTaperY() ); - setRevolutions(params.getRevolutions()); - setSkew(params.getSkew()); -} - -S32 profile_delete_lock = 1 ; -LLProfile::~LLProfile() -{ - if(profile_delete_lock) - { - llerrs << "LLProfile should not be deleted here!" << llendl ; - } -} - - -S32 LLVolume::sNumMeshPoints = 0; - -LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) - : mParams(params) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - mUnique = is_unique; - mFaceMask = 0x0; - mDetail = detail; - mSculptLevel = -2; - mIsTetrahedron = FALSE; - mLODScaleBias.setVec(1,1,1); - mHullPoints = NULL; - mHullIndices = NULL; - mNumHullPoints = 0; - mNumHullIndices = 0; - - // set defaults - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) - { - mPathp = new LLDynamicPath(); - } - else - { - mPathp = new LLPath(); - } - mProfilep = new LLProfile(); - - mGenerateSingleFace = generate_single_face; - - generate(); - - if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) - { - createVolumeFaces(); - } -} - -void LLVolume::resizePath(S32 length) -{ - mPathp->resizePath(length); - mVolumeFaces.clear(); -} - -void LLVolume::regen() -{ - generate(); - createVolumeFaces(); -} - -void LLVolume::genBinormals(S32 face) -{ - mVolumeFaces[face].createBinormals(); -} - -LLVolume::~LLVolume() -{ - sNumMeshPoints -= mMesh.size(); - delete mPathp; - - profile_delete_lock = 0 ; - delete mProfilep; - profile_delete_lock = 1 ; - - mPathp = NULL; - mProfilep = NULL; - mVolumeFaces.clear(); - - free(mHullPoints); - mHullPoints = NULL; - free(mHullIndices); - mHullIndices = NULL; -} - -BOOL LLVolume::generate() -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - llassert_always(mProfilep); - - //Added 10.03.05 Dave Parks - // Split is a parameter to LLProfile::generate that tesselates edges on the profile - // to prevent lighting and texture interpolation errors on triangles that are - // stretched due to twisting or scaling on the path. - S32 split = (S32) ((mDetail)*0.66f); - - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && - (mParams.getPathParams().getScale().mV[0] != 1.0f || - mParams.getPathParams().getScale().mV[1] != 1.0f) && - (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) - { - split = 0; - } - - mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); - - F32 profile_detail = mDetail; - F32 path_detail = mDetail; - - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); - } - - //******************************************************************** - //debug info, to be removed - if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) - { - llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ; - llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; - llinfos << mParams << llendl ; - llinfos << "more info to check if mProfilep is deleted or not." << llendl ; - llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - - llerrs << "LLVolume corrupted!" << llendl ; - } - //******************************************************************** - - BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); - BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); - - if (regenPath || regenProf ) - { - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - //******************************************************************** - //debug info, to be removed - if((U32)(sizeS * sizeT) > (1u << 20)) - { - llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ; - llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ; - llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; - llinfos << mParams << llendl ; - llinfos << "more info to check if mProfilep is deleted or not." << llendl ; - llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - - llerrs << "LLVolume corrupted!" << llendl ; - } - //******************************************************************** - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeT * sizeS); - sNumMeshPoints += mMesh.size(); - - //generate vertex positions - - // Run along the path. - for (S32 s = 0; s < sizeS; ++s) - { - LLVector2 scale = mPathp->mPath[s].mScale; - LLQuaternion rot = mPathp->mPath[s].mRot; - - // Run along the profile. - for (S32 t = 0; t < sizeT; ++t) - { - S32 m = s*sizeT + t; - Point& pt = mMesh[m]; - - pt.mPos.mV[0] = mProfilep->mProfile[t].mV[0] * scale.mV[0]; - pt.mPos.mV[1] = mProfilep->mProfile[t].mV[1] * scale.mV[1]; - pt.mPos.mV[2] = 0.0f; - pt.mPos = pt.mPos * rot; - pt.mPos += mPathp->mPath[s].mPos; - } - } - - for (std::vector<LLProfile::Face>::iterator iter = mProfilep->mFaces.begin(); - iter != mProfilep->mFaces.end(); ++iter) - { - LLFaceID id = iter->mFaceID; - mFaceMask |= id; - } - - return TRUE; - } - return FALSE; -} - -void LLVolumeFace::VertexData::init() -{ - if (!mData) - { - mData = (LLVector4a*) malloc(sizeof(LLVector4a)*2); - } -} - -LLVolumeFace::VertexData::VertexData() -{ - mData = NULL; - init(); -} - -LLVolumeFace::VertexData::VertexData(const VertexData& rhs) -{ - mData = NULL; - *this = rhs; -} - -const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) -{ - if (this != &rhs) - { - init(); - LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); - mTexCoord = rhs.mTexCoord; - } - return *this; -} - -LLVolumeFace::VertexData::~VertexData() -{ - free(mData); - mData = NULL; -} - -LLVector4a& LLVolumeFace::VertexData::getPosition() -{ - return mData[POSITION]; -} - -LLVector4a& LLVolumeFace::VertexData::getNormal() -{ - return mData[NORMAL]; -} - -const LLVector4a& LLVolumeFace::VertexData::getPosition() const -{ - return mData[POSITION]; -} - -const LLVector4a& LLVolumeFace::VertexData::getNormal() const -{ - return mData[NORMAL]; -} - - -void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) -{ - mData[POSITION] = pos; -} - -void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) -{ - mData[NORMAL] = norm; -} - -bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const -{ - const F32* lp = this->getPosition().getF32ptr(); - const F32* rp = rhs.getPosition().getF32ptr(); - - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } - - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } - - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } - - lp = getNormal().getF32ptr(); - rp = rhs.getNormal().getF32ptr(); - - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } - - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } - - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } - - if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) - { - return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; - } - - return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; -} - -bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const -{ - return mData[POSITION].equals3(rhs.getPosition()) && - mData[NORMAL].equals3(rhs.getNormal()) && - mTexCoord == rhs.mTexCoord; -} - -bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const -{ - bool retval = false; - if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) - { - if (angle_cutoff > 1.f) - { - retval = (mData[NORMAL].equals3(rhs.mData[NORMAL])); - } - else - { - F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); - retval = cur_angle > angle_cutoff; - } - } - - return retval; -} - -bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) -{ - //input stream is now pointing at a zlib compressed block of LLSD - //decompress block - LLSD mdl; - if (!unzip_llsd(mdl, is, size)) - { - llwarns << "not a valid mesh asset!" << llendl; - return false; - } - - { - U32 face_count = mdl.size(); - - if (face_count == 0) - { - llerrs << "WTF?" << llendl; - } - - mVolumeFaces.resize(face_count); - - for (U32 i = 0; i < face_count; ++i) - { - LLSD::Binary pos = mdl[i]["Position"]; - LLSD::Binary norm = mdl[i]["Normal"]; - LLSD::Binary tc = mdl[i]["TexCoord0"]; - LLSD::Binary idx = mdl[i]["TriangleList"]; - - LLVolumeFace& face = mVolumeFaces[i]; - - //copy out indices - face.resizeIndices(idx.size()/2); - - if (idx.empty() || face.mNumIndices < 3) - { //why is there an empty index list? - llerrs <<"WTF?" << llendl; - continue; - } - - U16* indices = (U16*) &(idx[0]); - for (U32 j = 0; j < idx.size()/2; ++j) - { - face.mIndices[j] = indices[j]; - } - - //copy out vertices - U32 num_verts = pos.size()/(3*2); - face.resizeVertices(num_verts); - - if (mdl[i].has("Weights")) - { - face.allocateWeights(num_verts); - - LLSD::Binary weights = mdl[i]["Weights"]; - - U32 idx = 0; - - U32 cur_vertex = 0; - while (idx < weights.size() && cur_vertex < num_verts) - { - const U8 END_INFLUENCES = 0xFF; - U8 joint = weights[idx++]; - - U32 cur_influence = 0; - LLVector4 wght(0,0,0,0); - - while (joint != END_INFLUENCES && idx < weights.size()) - { - U16 influence = weights[idx++]; - influence |= ((U16) weights[idx++] << 8); - - F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); - wght.mV[cur_influence++] = (F32) joint + w; - - if (cur_influence >= 4) - { - joint = END_INFLUENCES; - } - else - { - joint = weights[idx++]; - } - } - - face.mWeights[cur_vertex].loadua(wght.mV); - - cur_vertex++; - } - - if (cur_vertex != num_verts || idx != weights.size()) - { - llwarns << "Vertex weight count does not match vertex count!" << llendl; - } - - } - - LLVector3 minp; - LLVector3 maxp; - LLVector2 min_tc; - LLVector2 max_tc; - - minp.setValue(mdl[i]["PositionDomain"]["Min"]); - maxp.setValue(mdl[i]["PositionDomain"]["Max"]); - LLVector4a min_pos, max_pos; - min_pos.load3(minp.mV); - max_pos.load3(maxp.mV); - - min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); - max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); - - LLVector4a pos_range; - pos_range.setSub(max_pos, min_pos); - LLVector2 tc_range = max_tc - min_tc; - - LLVector4a* pos_out = face.mPositions; - LLVector4a* norm_out = face.mNormals; - LLVector2* tc_out = face.mTexCoords; - - for (U32 j = 0; j < num_verts; ++j) - { - U16* v = (U16*) &(pos[j*3*2]); - - pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); - pos_out->div(65535.f); - pos_out->mul(pos_range); - pos_out->add(min_pos); - - pos_out++; - - U16* n = (U16*) &(norm[j*3*2]); - - norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); - norm_out->div(65535.f); - norm_out->mul(2.f); - norm_out->sub(1.f); - norm_out++; - - U16* t = (U16*) &(tc[j*2*2]); - - tc_out->mV[0] = (F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0]; - tc_out->mV[1] = (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]; - - tc_out++; - } - - - // modifier flags? - bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); - bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); - - - // translate to actions: - bool do_reflect_x = false; - bool do_reverse_triangles = false; - bool do_invert_normals = false; - - if (do_mirror) - { - do_reflect_x = true; - do_reverse_triangles = !do_reverse_triangles; - } - - if (do_invert) - { - do_invert_normals = true; - do_reverse_triangles = !do_reverse_triangles; - } - - // now do the work - - if (do_reflect_x) - { - LLVector4a* p = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - p[i].mul(-1.0f); - n[i].mul(-1.0f); - } - } - - if (do_invert_normals) - { - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - n[i].mul(-1.0f); - } - } - - if (do_reverse_triangles) - { - for (U32 j = 0; j < face.mNumIndices; j += 3) - { - // swap the 2nd and 3rd index - S32 swap = face.mIndices[j+1]; - face.mIndices[j+1] = face.mIndices[j+2]; - face.mIndices[j+2] = swap; - } - } - - //calculate bounding box - LLVector4a& min = face.mExtents[0]; - LLVector4a& max = face.mExtents[1]; - - min.clear(); - max.clear(); - min = max = face.mPositions[0]; - - for (S32 i = 1; i < face.mNumVertices; ++i) - { - min.setMin(min, face.mPositions[i]); - max.setMax(max, face.mPositions[i]); - } - } - } - - mSculptLevel = 0; // success! - - cacheOptimize(); - - return true; -} - -void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) -{ - LLVector4a v0; - v0.setSub(cv[1].getPosition(), cv[0].getNormal()); - LLVector4a v1; - v1.setSub(cv[2].getNormal(), cv[0].getPosition()); - - cv[0].getNormal().setCross3(v0,v1); - cv[0].getNormal().normalize3fast(); - cv[1].setNormal(cv[0].getNormal()); - cv[2].setNormal(cv[1].getNormal()); -} - -BOOL LLVolume::isTetrahedron() -{ - return mIsTetrahedron; -} - -void LLVolume::makeTetrahedron() -{ - mVolumeFaces.clear(); - - LLVolumeFace face; - - F32 x = 0.25f; - LLVector4a p[] = - { //unit tetrahedron corners - LLVector4a(x,x,x), - LLVector4a(-x,-x,x), - LLVector4a(-x,x,-x), - LLVector4a(x,-x,-x) - }; - - face.mExtents[0].splat(-x); - face.mExtents[1].splat(x); - - LLVolumeFace::VertexData cv[3]; - - //set texture coordinates - cv[0].mTexCoord = LLVector2(0,0); - cv[1].mTexCoord = LLVector2(1,0); - cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3); - - - //side 1 - cv[0].setPosition(p[1]); - cv[1].setPosition(p[0]); - cv[2].setPosition(p[2]); - - tetrahedron_set_normal(cv); - - face.resizeVertices(12); - face.resizeIndices(12); - - LLVector4a* v = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - LLVector2* tc = (LLVector2*) face.mTexCoords; - - v[0] = cv[0].getPosition(); - v[1] = cv[1].getPosition(); - v[2] = cv[2].getPosition(); - v += 3; - - n[0] = cv[0].getNormal(); - n[1] = cv[1].getNormal(); - n[2] = cv[2].getNormal(); - n += 3; - - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - - - //side 2 - cv[0].setPosition(p[3]); - cv[1].setPosition(p[0]); - cv[2].setPosition(p[1]); - - tetrahedron_set_normal(cv); - - v[0] = cv[0].getPosition(); - v[1] = cv[1].getPosition(); - v[2] = cv[2].getPosition(); - v += 3; - - n[0] = cv[0].getNormal(); - n[1] = cv[1].getNormal(); - n[2] = cv[2].getNormal(); - n += 3; - - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - - //side 3 - cv[0].setPosition(p[3]); - cv[1].setPosition(p[1]); - cv[2].setPosition(p[2]); - - tetrahedron_set_normal(cv); - - v[0] = cv[0].getPosition(); - v[1] = cv[1].getPosition(); - v[2] = cv[2].getPosition(); - v += 3; - - n[0] = cv[0].getNormal(); - n[1] = cv[1].getNormal(); - n[2] = cv[2].getNormal(); - n += 3; - - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - - //side 4 - cv[0].setPosition(p[2]); - cv[1].setPosition(p[0]); - cv[2].setPosition(p[3]); - - tetrahedron_set_normal(cv); - - v[0] = cv[0].getPosition(); - v[1] = cv[1].getPosition(); - v[2] = cv[2].getPosition(); - v += 3; - - n[0] = cv[0].getNormal(); - n[1] = cv[1].getNormal(); - n[2] = cv[2].getNormal(); - n += 3; - - tc[0] = cv[0].mTexCoord; - tc[1] = cv[1].mTexCoord; - tc[2] = cv[2].mTexCoord; - tc += 3; - - //set index buffer - for (U16 i = 0; i < 12; i++) - { - face.mIndices[i] = i; - } - - mVolumeFaces.push_back(face); - mSculptLevel = 0; - mIsTetrahedron = TRUE; -} - -void LLVolume::copyVolumeFaces(const LLVolume* volume) -{ - mVolumeFaces = volume->mVolumeFaces; - mSculptLevel = 0; - mIsTetrahedron = FALSE; -} - -void LLVolume::cacheOptimize() -{ - for (S32 i = 0; i < mVolumeFaces.size(); ++i) - { - mVolumeFaces[i].cacheOptimize(); - } -} - - -S32 LLVolume::getNumFaces() const -{ - U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); - - if (sculpt_type == LL_SCULPT_TYPE_MESH) - { - return LL_SCULPT_MESH_MAX_FACES; - } - - return (S32)mProfilep->mFaces.size(); -} - - -void LLVolume::createVolumeFaces() -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - if (mGenerateSingleFace) - { - // do nothing - } - else - { - S32 num_faces = getNumFaces(); - BOOL partial_build = TRUE; - if (num_faces != mVolumeFaces.size()) - { - partial_build = FALSE; - mVolumeFaces.resize(num_faces); - } - // Initialize volume faces with parameter data - for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) - { - LLVolumeFace& vf = mVolumeFaces[i]; - LLProfile::Face& face = mProfilep->mFaces[i]; - vf.mBeginS = face.mIndex; - vf.mNumS = face.mCount; - if (vf.mNumS < 0) - { - llerrs << "Volume face corruption detected." << llendl; - } - - vf.mBeginT = 0; - vf.mNumT= getPath().mPath.size(); - vf.mID = i; - - // Set the type mask bits correctly - if (mParams.getProfileParams().getHollow() > 0) - { - vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; - } - if (mProfilep->isOpen()) - { - vf.mTypeMask |= LLVolumeFace::OPEN_MASK; - } - if (face.mCap) - { - vf.mTypeMask |= LLVolumeFace::CAP_MASK; - if (face.mFaceID == LL_FACE_PATH_BEGIN) - { - vf.mTypeMask |= LLVolumeFace::TOP_MASK; - } - else - { - llassert(face.mFaceID == LL_FACE_PATH_END); - vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; - } - } - else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; - } - else - { - vf.mTypeMask |= LLVolumeFace::SIDE_MASK; - if (face.mFlat) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK; - } - if (face.mFaceID & LL_FACE_INNER_SIDE) - { - vf.mTypeMask |= LLVolumeFace::INNER_MASK; - if (face.mFlat && vf.mNumS > 2) - { //flat inner faces have to copy vert normals - vf.mNumS = vf.mNumS*2; - if (vf.mNumS < 0) - { - llerrs << "Volume face corruption detected." << llendl; - } - } - } - else - { - vf.mTypeMask |= LLVolumeFace::OUTER_MASK; - } - } - } - - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - (*iter).create(this, partial_build); - } - } -} - - -inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b) -{ - // maps RGB values to vector values [0..255] -> [-0.5..0.5] - LLVector3 value; - value.mV[VX] = r / 255.f - 0.5f; - value.mV[VY] = g / 255.f - 0.5f; - value.mV[VZ] = b / 255.f - 0.5f; - - return value; -} - -inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) -{ - U32 index = (x + y * sculpt_width) * sculpt_components; - return index; -} - - -inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) -{ - U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); - U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); - - return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); -} - - -inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data) -{ - LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); - - return v; -} - -inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) -{ - U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); - - return sculpt_index_to_vector(index, sculpt_data); -} - -inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) -{ - U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); - - return sculpt_index_to_vector(index, sculpt_data); -} - - -F32 LLVolume::sculptGetSurfaceArea() -{ - // test to see if image has enough variation to create non-degenerate geometry - - F32 area = 0; - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - for (S32 s = 0; s < sizeS-1; s++) - { - for (S32 t = 0; t < sizeT-1; t++) - { - // get four corners of quad - LLVector3 p1 = mMesh[(s )*sizeT + (t )].mPos; - LLVector3 p2 = mMesh[(s+1)*sizeT + (t )].mPos; - LLVector3 p3 = mMesh[(s )*sizeT + (t+1)].mPos; - LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos; - - // compute the area of the quad by taking the length of the cross product of the two triangles - LLVector3 cross1 = (p1 - p2) % (p1 - p3); - LLVector3 cross2 = (p4 - p2) % (p4 - p3); - area += (cross1.magVec() + cross2.magVec()) / 2.0; - } - } - - return area; -} - -// create placeholder shape -void LLVolume::sculptGeneratePlaceholder() -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - S32 line = 0; - - // for now, this is a sphere. - for (S32 s = 0; s < sizeS; s++) - { - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - Point& pt = mMesh[i]; - - - F32 u = (F32)s/(sizeS-1); - F32 v = (F32)t/(sizeT-1); - - const F32 RADIUS = (F32) 0.3; - - pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); - pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); - pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS); - - } - line += sizeT; - } -} - -// create the vertices from the map -void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) -{ - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - - LLMemType m1(LLMemType::MTYPE_VOLUME); - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - S32 line = 0; - for (S32 s = 0; s < sizeS; s++) - { - // Run along the profile. - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - Point& pt = mMesh[i]; - - S32 reversed_t = t; - - if (reverse_horizontal) - { - reversed_t = sizeT - t - 1; - } - - U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); - U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); - - - if (y == 0) // top row stitching - { - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (y == sculpt_height) // bottom row stitching - { - // wrap? - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - { - y = 0; - } - else - { - y = sculpt_height - 1; - } - - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (x == sculpt_width) // side stitching - { - // wrap? - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - { - x = 0; - } - - else - { - x = sculpt_width - 1; - } - } - - pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); - - if (sculpt_mirror) - { - pt.mPos.mV[VX] *= -1.f; - } - } - - line += sizeT; - } -} - - -const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square -const S32 SCULPT_REZ_2 = 8; -const S32 SCULPT_REZ_3 = 16; -const S32 SCULPT_REZ_4 = 32; - -S32 sculpt_sides(F32 detail) -{ - - // detail is usually one of: 1, 1.5, 2.5, 4.0. - - if (detail <= 1.0) - { - return SCULPT_REZ_1; - } - if (detail <= 2.0) - { - return SCULPT_REZ_2; - } - if (detail <= 3.0) - { - return SCULPT_REZ_3; - } - else - { - return SCULPT_REZ_4; - } -} - - - -// determine the number of vertices in both s and t direction for this sculpt -void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) -{ - // this code has the following properties: - // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map - // while still using all available verts - // 2) the mesh cannot have more verts than is allowed by LOD - // 3) the mesh cannot have more verts than is allowed by the map - - S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); - S32 max_vertices_map = width * height / 4; - - S32 vertices; - if (max_vertices_map > 0) - vertices = llmin(max_vertices_lod, max_vertices_map); - else - vertices = max_vertices_lod; - - - F32 ratio; - if ((width == 0) || (height == 0)) - ratio = 1.f; - else - ratio = (F32) width / (F32) height; - - - s = (S32)(F32) sqrt(((F32)vertices / ratio)); - - s = llmax(s, 4); // no degenerate sizes, please - t = vertices / s; - - t = llmax(t, 4); // no degenerate sizes, please - s = vertices / t; -} - -// sculpt replaces generate() for sculpted surfaces -void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - U8 sculpt_type = mParams.getSculptType(); - - BOOL data_is_empty = FALSE; - - if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) - { - sculpt_level = -1; - data_is_empty = TRUE; - } - - S32 requested_sizeS = 0; - S32 requested_sizeT = 0; - - sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); - - mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); - mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); - - S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got - S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got - - // weird crash bug - DEV-11158 - trying to collect more data: - if ((sizeS == 0) || (sizeT == 0)) - { - llwarns << "sculpt bad mesh size " << sizeS << " " << sizeT << llendl; - } - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeS * sizeT); - sNumMeshPoints += mMesh.size(); - - //generate vertex positions - if (!data_is_empty) - { - sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); - - // don't test lowest LOD to support legacy content DEV-33670 - if (mDetail > SCULPT_MIN_AREA_DETAIL) - { - if (sculptGetSurfaceArea() < SCULPT_MIN_AREA) - { - data_is_empty = TRUE; - } - } - } - - if (data_is_empty) - { - sculptGeneratePlaceholder(); - } - - - - for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) - { - mFaceMask |= mProfilep->mFaces[i].mFaceID; - } - - mSculptLevel = sculpt_level; - - // Delete any existing faces so that they get regenerated - mVolumeFaces.clear(); - - createVolumeFaces(); -} - - - - -BOOL LLVolume::isCap(S32 face) -{ - return mProfilep->mFaces[face].mCap; -} - -BOOL LLVolume::isFlat(S32 face) -{ - return mProfilep->mFaces[face].mFlat; -} - - -bool LLVolumeParams::isSculpt() const -{ - return mSculptID.notNull(); -} - -bool LLVolumeParams::isMeshSculpt() const -{ - return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); -} - -bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const -{ - return ( (getPathParams() == params.getPathParams()) && - (getProfileParams() == params.getProfileParams()) && - (mSculptID == params.mSculptID) && - (mSculptType == params.mSculptType) ); -} - -bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const -{ - return ( (getPathParams() != params.getPathParams()) || - (getProfileParams() != params.getProfileParams()) || - (mSculptID != params.mSculptID) || - (mSculptType != params.mSculptType) ); -} - -bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const -{ - if( getPathParams() != params.getPathParams() ) - { - return getPathParams() < params.getPathParams(); - } - - if (getProfileParams() != params.getProfileParams()) - { - return getProfileParams() < params.getProfileParams(); - } - - if (mSculptID != params.mSculptID) - { - return mSculptID < params.mSculptID; - } - - return mSculptType < params.mSculptType; - - -} - -void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - mProfileParams.copyParams(params.mProfileParams); - mPathParams.copyParams(params.mPathParams); - mSculptID = params.getSculptID(); - mSculptType = params.getSculptType(); -} - -// Less restricitve approx 0 for volumes -const F32 APPROXIMATELY_ZERO = 0.001f; -bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO) -{ - return (f >= -tolerance) && (f <= tolerance); -} - -// return true if in range (or nearly so) -static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO) -{ - F32 min_delta = v - min; - if (min_delta < 0.f) - { - v = min; - if (!approx_zero(min_delta, tolerance)) - return false; - } - F32 max_delta = max - v; - if (max_delta < 0.f) - { - v = max; - if (!approx_zero(max_delta, tolerance)) - return false; - } - return true; -} - -bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e) -{ - bool valid = true; - - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); - - F32 end = e; - if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); - - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); - - // Now set them. - mProfileParams.setBegin(begin); - mProfileParams.setEnd(end); - - return valid; -} - -bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e) -{ - bool valid = true; - - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); - - F32 end = e; - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); - - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); - - // Now set them. - mPathParams.setBegin(begin); - mPathParams.setEnd(end); - - return valid; -} - -bool LLVolumeParams::setHollow(const F32 h) -{ - // Validate the hollow based on path and profile. - U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; - - F32 max_hollow = HOLLOW_MAX; - - // Only square holes have trouble. - if (LL_PCODE_HOLE_SQUARE == hole_type) - { - switch(profile) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - case LL_PCODE_PROFILE_EQUALTRI: - max_hollow = HOLLOW_MAX_SQUARE; - } - } - - F32 hollow = h; - bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); - mProfileParams.setHollow(hollow); - - return valid; -} - -bool LLVolumeParams::setTwistBegin(const F32 b) -{ - F32 twist_begin = b; - bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistBegin(twist_begin); - return valid; -} - -bool LLVolumeParams::setTwistEnd(const F32 e) -{ - F32 twist_end = e; - bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistEnd(twist_end); - return valid; -} - -bool LLVolumeParams::setRatio(const F32 x, const F32 y) -{ - F32 min_x = RATIO_MIN; - F32 max_x = RATIO_MAX; - F32 min_y = RATIO_MIN; - F32 max_y = RATIO_MAX; - // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PATH_CIRCLE == path_type && - LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) - { - // Holes are more restricted... - min_x = HOLE_X_MIN; - max_x = HOLE_X_MAX; - min_y = HOLE_Y_MIN; - max_y = HOLE_Y_MAX; - } - - F32 ratio_x = x; - bool valid = limit_range(ratio_x, min_x, max_x); - F32 ratio_y = y; - valid &= limit_range(ratio_y, min_y, max_y); - - mPathParams.setScale(ratio_x, ratio_y); - - return valid; -} - -bool LLVolumeParams::setShear(const F32 x, const F32 y) -{ - F32 shear_x = x; - bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); - F32 shear_y = y; - valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); - mPathParams.setShear(shear_x, shear_y); - return valid; -} - -bool LLVolumeParams::setTaperX(const F32 v) -{ - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperX(taper); - return valid; -} - -bool LLVolumeParams::setTaperY(const F32 v) -{ - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperY(taper); - return valid; -} - -bool LLVolumeParams::setRevolutions(const F32 r) -{ - F32 revolutions = r; - bool valid = limit_range(revolutions, REV_MIN, REV_MAX); - mPathParams.setRevolutions(revolutions); - return valid; -} - -bool LLVolumeParams::setRadiusOffset(const F32 offset) -{ - bool valid = true; - - // If this is a sphere, just set it to 0 and get out. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || - LL_PCODE_PATH_CIRCLE != path_type ) - { - mPathParams.setRadiusOffset(0.f); - return true; - } - - // Limit radius offset, based on taper and hole size y. - F32 radius_offset = offset; - F32 taper_y = getTaperY(); - F32 radius_mag = fabs(radius_offset); - F32 hole_y_mag = fabs(getRatioY()); - F32 taper_y_mag = fabs(taper_y); - // Check to see if the taper effects us. - if ( (radius_offset > 0.f && taper_y < 0.f) || - (radius_offset < 0.f && taper_y > 0.f) ) - { - // The taper does not help increase the radius offset range. - taper_y_mag = 0.f; - } - F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); - - // Enforce the maximum magnitude. - F32 delta = max_radius_mag - radius_mag; - if (delta < 0.f) - { - // Check radius offset sign. - if (radius_offset < 0.f) - { - radius_offset = -max_radius_mag; - } - else - { - radius_offset = max_radius_mag; - } - valid = approx_zero(delta, .1f); - } - - mPathParams.setRadiusOffset(radius_offset); - return valid; -} - -bool LLVolumeParams::setSkew(const F32 skew_value) -{ - bool valid = true; - - // Check the skew value against the revolutions. - F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); - F32 skew_mag = fabs(skew); - F32 revolutions = getRevolutions(); - F32 scale_x = getRatioX(); - F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); - // Discontinuity; A revolution of 1 allows skews below 0.5. - if ( fabs(revolutions - 1.0f) < 0.001) - min_skew_mag = 0.0f; - - // Clip skew. - F32 delta = skew_mag - min_skew_mag; - if (delta < 0.f) - { - // Check skew sign. - if (skew < 0.0f) - { - skew = -min_skew_mag; - } - else - { - skew = min_skew_mag; - } - valid = approx_zero(delta, .01f); - } - - mPathParams.setSkew(skew); - return valid; -} - -bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type) -{ - mSculptID = sculpt_id; - mSculptType = sculpt_type; - return true; -} - -bool LLVolumeParams::setType(U8 profile, U8 path) -{ - bool result = true; - // First, check profile and path for validity. - U8 profile_type = profile & LL_PCODE_PROFILE_MASK; - U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; - U8 path_type = path >> 4; - - if (profile_type > LL_PCODE_PROFILE_MAX) - { - // Bad profile. Make it square. - profile = LL_PCODE_PROFILE_SQUARE; - result = false; - llwarns << "LLVolumeParams::setType changing bad profile type (" << profile_type - << ") to be LL_PCODE_PROFILE_SQUARE" << llendl; - } - else if (hole_type > LL_PCODE_HOLE_MAX) - { - // Bad hole. Make it the same. - profile = profile_type; - result = false; - llwarns << "LLVolumeParams::setType changing bad hole type (" << hole_type - << ") to be LL_PCODE_HOLE_SAME" << llendl; - } - - if (path_type < LL_PCODE_PATH_MIN || - path_type > LL_PCODE_PATH_MAX) - { - // Bad path. Make it linear. - result = false; - llwarns << "LLVolumeParams::setType changing bad path (" << path - << ") to be LL_PCODE_PATH_LINE" << llendl; - path = LL_PCODE_PATH_LINE; - } - - mProfileParams.setCurveType(profile); - mPathParams.setCurveType(path); - return result; -} - -// static -bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, - U8 path_curve, F32 path_begin, F32 path_end, - F32 scx, F32 scy, F32 shx, F32 shy, - F32 twistend, F32 twistbegin, F32 radiusoffset, - F32 tx, F32 ty, F32 revolutions, F32 skew) -{ - LLVolumeParams test_params; - if (!test_params.setType (prof_curve, path_curve)) - { - return false; - } - if (!test_params.setBeginAndEndS (prof_begin, prof_end)) - { - return false; - } - if (!test_params.setBeginAndEndT (path_begin, path_end)) - { - return false; - } - if (!test_params.setHollow (hollow)) - { - return false; - } - if (!test_params.setTwistBegin (twistbegin)) - { - return false; - } - if (!test_params.setTwistEnd (twistend)) - { - return false; - } - if (!test_params.setRatio (scx, scy)) - { - return false; - } - if (!test_params.setShear (shx, shy)) - { - return false; - } - if (!test_params.setTaper (tx, ty)) - { - return false; - } - if (!test_params.setRevolutions (revolutions)) - { - return false; - } - if (!test_params.setRadiusOffset (radiusoffset)) - { - return false; - } - if (!test_params.setSkew (skew)) - { - return false; - } - return true; -} - -S32 *LLVolume::getTriangleIndices(U32 &num_indices) const -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - S32 expected_num_triangle_indices = getNumTriangleIndices(); - if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES) - { - // we don't allow LLVolumes with this many vertices - llwarns << "Couldn't allocate triangle indices" << llendl; - num_indices = 0; - return NULL; - } - - S32* index = new S32[expected_num_triangle_indices]; - S32 count = 0; - - // Let's do this totally diffently, as we don't care about faces... - // Counter-clockwise triangles are forward facing... - - BOOL open = getProfile().isOpen(); - BOOL hollow = (mParams.getProfileParams().getHollow() > 0); - BOOL path_open = getPath().isOpen(); - S32 size_s, size_s_out, size_t; - S32 s, t, i; - size_s = getProfile().getTotal(); - size_s_out = getProfile().getTotalOut(); - size_t = getPath().mPath.size(); - - // NOTE -- if the construction of the triangles below ever changes - // then getNumTriangleIndices() method may also have to be updated. - - if (open) /* Flawfinder: ignore */ - { - if (hollow) - { - // Open hollow -- much like the closed solid, except we - // we need to stitch up the gap between s=0 and s=size_s-1 - - for (t = 0; t < size_t - 1; t++) - { - // The outer face, first cut, and inner face - for (s = 0; s < size_s - 1; s++) - { - i = s + t*size_s; - index[count++] = i; // x,y - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s; // x,y+1 - - index[count++] = i + size_s; // x,y+1 - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s + 1; // x+1,y+1 - } - - // The other cut face - index[count++] = s + t*size_s; // x,y - index[count++] = 0 + t*size_s; // x+1,y - index[count++] = s + (t+1)*size_s; // x,y+1 - - index[count++] = s + (t+1)*size_s; // x,y+1 - index[count++] = 0 + t*size_s; // x+1,y - index[count++] = 0 + (t+1)*size_s; // x+1,y+1 - } - - // Do the top and bottom caps, if necessary - if (path_open) - { - // Top cap - S32 pt1 = 0; - S32 pt2 = size_s-1; - S32 i = (size_t - 1)*size_s; - - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = getProfile().mProfile[pt1]; - LLVector3 p2 = getProfile().mProfile[pt2]; - LLVector3 pa = getProfile().mProfile[pt1+1]; - LLVector3 pb = getProfile().mProfile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - index[count++] = pt1 + i; - index[count++] = pt1 + 1 + i; - index[count++] = pt2 + i; - pt1++; - } - else - { - index[count++] = pt1 + i; - index[count++] = pt2 - 1 + i; - index[count++] = pt2 + i; - pt2--; - } - } - - // Bottom cap - pt1 = 0; - pt2 = size_s-1; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = getProfile().mProfile[pt1]; - LLVector3 p2 = getProfile().mProfile[pt2]; - LLVector3 pa = getProfile().mProfile[pt1+1]; - LLVector3 pb = getProfile().mProfile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - index[count++] = pt1; - index[count++] = pt2; - index[count++] = pt1 + 1; - pt1++; - } - else - { - index[count++] = pt1; - index[count++] = pt2; - index[count++] = pt2 - 1; - pt2--; - } - } - } - } - else - { - // Open solid - - for (t = 0; t < size_t - 1; t++) - { - // Outer face + 1 cut face - for (s = 0; s < size_s - 1; s++) - { - i = s + t*size_s; - - index[count++] = i; // x,y - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s; // x,y+1 - - index[count++] = i + size_s; // x,y+1 - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s + 1; // x+1,y+1 - } - - // The other cut face - index[count++] = (size_s - 1) + (t*size_s); // x,y - index[count++] = 0 + t*size_s; // x+1,y - index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1 - - index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1 - index[count++] = 0 + (t*size_s); // x+1,y - index[count++] = 0 + (t+1)*size_s; // x+1,y+1 - } - - // Do the top and bottom caps, if necessary - if (path_open) - { - for (s = 0; s < size_s - 2; s++) - { - index[count++] = s+1; - index[count++] = s; - index[count++] = size_s - 1; - } - - // We've got a top cap - S32 offset = (size_t - 1)*size_s; - for (s = 0; s < size_s - 2; s++) - { - // Inverted ordering from bottom cap. - index[count++] = offset + size_s - 1; - index[count++] = offset + s; - index[count++] = offset + s + 1; - } - } - } - } - else if (hollow) - { - // Closed hollow - // Outer face - - for (t = 0; t < size_t - 1; t++) - { - for (s = 0; s < size_s_out - 1; s++) - { - i = s + t*size_s; - - index[count++] = i; // x,y - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s; // x,y+1 - - index[count++] = i + size_s; // x,y+1 - index[count++] = i + 1; // x+1,y - index[count++] = i + 1 + size_s; // x+1,y+1 - } - } - - // Inner face - // Invert facing from outer face - for (t = 0; t < size_t - 1; t++) - { - for (s = size_s_out; s < size_s - 1; s++) - { - i = s + t*size_s; - - index[count++] = i; // x,y - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s; // x,y+1 - - index[count++] = i + size_s; // x,y+1 - index[count++] = i + 1; // x+1,y - index[count++] = i + 1 + size_s; // x+1,y+1 - } - } - - // Do the top and bottom caps, if necessary - if (path_open) - { - // Top cap - S32 pt1 = 0; - S32 pt2 = size_s-1; - S32 i = (size_t - 1)*size_s; - - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = getProfile().mProfile[pt1]; - LLVector3 p2 = getProfile().mProfile[pt2]; - LLVector3 pa = getProfile().mProfile[pt1+1]; - LLVector3 pb = getProfile().mProfile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - index[count++] = pt1 + i; - index[count++] = pt1 + 1 + i; - index[count++] = pt2 + i; - pt1++; - } - else - { - index[count++] = pt1 + i; - index[count++] = pt2 - 1 + i; - index[count++] = pt2 + i; - pt2--; - } - } - - // Bottom cap - pt1 = 0; - pt2 = size_s-1; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = getProfile().mProfile[pt1]; - LLVector3 p2 = getProfile().mProfile[pt2]; - LLVector3 pa = getProfile().mProfile[pt1+1]; - LLVector3 pb = getProfile().mProfile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - index[count++] = pt1; - index[count++] = pt2; - index[count++] = pt1 + 1; - pt1++; - } - else - { - index[count++] = pt1; - index[count++] = pt2; - index[count++] = pt2 - 1; - pt2--; - } - } - } - } - else - { - // Closed solid. Easy case. - for (t = 0; t < size_t - 1; t++) - { - for (s = 0; s < size_s - 1; s++) - { - // Should wrap properly, but for now... - i = s + t*size_s; - - index[count++] = i; // x,y - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s; // x,y+1 - - index[count++] = i + size_s; // x,y+1 - index[count++] = i + 1; // x+1,y - index[count++] = i + size_s + 1; // x+1,y+1 - } - } - - // Do the top and bottom caps, if necessary - if (path_open) - { - // bottom cap - for (s = 1; s < size_s - 2; s++) - { - index[count++] = s+1; - index[count++] = s; - index[count++] = 0; - } - - // top cap - S32 offset = (size_t - 1)*size_s; - for (s = 1; s < size_s - 2; s++) - { - // Inverted ordering from bottom cap. - index[count++] = offset; - index[count++] = offset + s; - index[count++] = offset + s + 1; - } - } - } - -#ifdef LL_DEBUG - // assert that we computed the correct number of indices - if (count != expected_num_triangle_indices ) - { - llerrs << "bad index count prediciton:" - << " expected=" << expected_num_triangle_indices - << " actual=" << count << llendl; - } -#endif - -#if 0 - // verify that each index does not point beyond the size of the mesh - S32 num_vertices = mMesh.size(); - for (i = 0; i < count; i+=3) - { - llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl; - llassert(index[i] < num_vertices); - llassert(index[i+1] < num_vertices); - llassert(index[i+2] < num_vertices); - } -#endif - - num_indices = count; - return index; -} - -S32 LLVolume::getNumTriangleIndices() const -{ - BOOL profile_open = getProfile().isOpen(); - BOOL hollow = (mParams.getProfileParams().getHollow() > 0); - BOOL path_open = getPath().isOpen(); - - S32 size_s, size_s_out, size_t; - size_s = getProfile().getTotal(); - size_s_out = getProfile().getTotalOut(); - size_t = getPath().mPath.size(); - - S32 count = 0; - if (profile_open) /* Flawfinder: ignore */ - { - if (hollow) - { - // Open hollow -- much like the closed solid, except we - // we need to stitch up the gap between s=0 and s=size_s-1 - count = (size_t - 1) * (((size_s -1) * 6) + 6); - } - else - { - count = (size_t - 1) * (((size_s -1) * 6) + 6); - } - } - else if (hollow) - { - // Closed hollow - // Outer face - count = (size_t - 1) * (size_s_out - 1) * 6; - - // Inner face - count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6; - } - else - { - // Closed solid. Easy case. - count = (size_t - 1) * (size_s - 1) * 6; - } - - if (path_open) - { - S32 cap_triangle_count = size_s - 3; - if ( profile_open - || hollow ) - { - cap_triangle_count = size_s - 2; - } - if ( cap_triangle_count > 0 ) - { - // top and bottom caps - count += cap_triangle_count * 2 * 3; - } - } - return count; -} - - -S32 LLVolume::getNumTriangles() const -{ - U32 triangle_count = 0; - - for (S32 i = 0; i < getNumVolumeFaces(); ++i) - { - triangle_count += getVolumeFace(i).mNumIndices/3; - } - - return triangle_count; -} - - -//----------------------------------------------------------------------------- -// generateSilhouetteVertices() -//----------------------------------------------------------------------------- -void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, - std::vector<LLVector3> &normals, - const LLVector3& obj_cam_vec_in, - const LLMatrix4& mat_in, - const LLMatrix3& norm_mat_in, - S32 face_mask) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - LLMatrix4a mat; - mat.loadu(mat_in); - - LLMatrix4a norm_mat; - norm_mat.loadu(norm_mat_in); - - LLVector4a obj_cam_vec; - obj_cam_vec.load3(obj_cam_vec_in.mV); - - vertices.clear(); - normals.clear(); - - if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - return; - } - - S32 cur_index = 0; - //for each face - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - LLVolumeFace& face = *iter; - - if (!(face_mask & (0x1 << cur_index++)) || - face.mNumIndices == 0 || face.mEdge.empty()) - { - continue; - } - - if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { - - } - else { - - //============================================== - //DEBUG draw edge map instead of silhouette edge - //============================================== - -#if DEBUG_SILHOUETTE_EDGE_MAP - - //for each triangle - U32 count = face.mNumIndices; - for (U32 j = 0; j < count/3; j++) { - //get vertices - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - //get current face center - LLVector3 cCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //for each edge - for (S32 k = 0; k < 3; k++) { - S32 nIndex = face.mEdge[j*3+k]; - if (nIndex <= -1) { - continue; - } - - if (nIndex >= (S32) count/3) { - continue; - } - //get neighbor vertices - v1 = face.mIndices[nIndex*3+0]; - v2 = face.mIndices[nIndex*3+1]; - v3 = face.mIndices[nIndex*3+2]; - - //get neighbor face center - LLVector3 nCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //draw line - vertices.push_back(cCenter); - vertices.push_back(nCenter); - normals.push_back(LLVector3(1,1,1)); - normals.push_back(LLVector3(1,1,1)); - segments.push_back(vertices.size()); - } - } - - continue; - - //============================================== - //DEBUG - //============================================== - - //============================================== - //DEBUG draw normals instead of silhouette edge - //============================================== -#elif DEBUG_SILHOUETTE_NORMALS - - //for each vertex - for (U32 j = 0; j < face.mNumVertices; j++) { - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); -#if DEBUG_SILHOUETTE_BINORMALS - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mBinormal*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); -#endif - } - - continue; -#else - //============================================== - //DEBUG - //============================================== - - static const U8 AWAY = 0x01, - TOWARDS = 0x02; - - //for each triangle - std::vector<U8> fFacing; - vector_append(fFacing, face.mNumIndices/3); - - LLVector4a* v = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - //approximate normal - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - LLVector4a c1,c2; - c1.setSub(v[v1], v[v2]); - c2.setSub(v[v2], v[v3]); - - LLVector4a norm; - - norm.setCross3(c1, c2); - - if (norm.dot3(norm) < 0.00000001f) - { - fFacing[j] = AWAY | TOWARDS; - } - else - { - //get view vector - LLVector4a view; - view.setSub(obj_cam_vec, v[v1]); - bool away = view.dot3(norm) > 0.0f; - if (away) - { - fFacing[j] = AWAY; - } - else - { - fFacing[j] = TOWARDS; - } - } - } - - //for each triangle - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - if (fFacing[j] == (AWAY | TOWARDS)) - { //this is a degenerate triangle - //take neighbor facing (degenerate faces get facing of one of their neighbors) - // *FIX IF NEEDED: this does not deal with neighboring degenerate faces - for (S32 k = 0; k < 3; k++) - { - S32 index = face.mEdge[j*3+k]; - if (index != -1) - { - fFacing[j] = fFacing[index]; - break; - } - } - continue; //skip degenerate face - } - - //for each edge - for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j*3+k]; - if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { - //our neighbor is degenerate, make him face our direction - fFacing[face.mEdge[j*3+k]] = fFacing[j]; - continue; - } - - if (index == -1 || //edge has no neighbor, MUST be a silhouette edge - (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge - - S32 v1 = face.mIndices[j*3+k]; - S32 v2 = face.mIndices[j*3+((k+1)%3)]; - - LLVector4a t; - mat.affineTransform(v[v1], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v1], t); - - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - - mat.affineTransform(v[v2], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v2], t); - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - } - } - } -#endif - } - } -} - -S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, - S32 face, - LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) -{ - LLVector4a starta, enda; - starta.load3(start.mV); - enda.load3(end.mV); - - return lineSegmentIntersect(starta, enda, face, intersection, tex_coord, normal, bi_normal); - -} - - -S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face, - LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) -{ - S32 hit_face = -1; - - S32 start_face; - S32 end_face; - - if (face == -1) // ALL_SIDES - { - start_face = 0; - end_face = getNumVolumeFaces() - 1; - } - else - { - start_face = face; - end_face = face; - } - - LLVector4a dir; - dir.setSub(end, start); - - F32 closest_t = 2.f; // must be larger than 1 - - end_face = llmin(end_face, getNumVolumeFaces()-1); - - for (S32 i = start_face; i <= end_face; i++) - { - LLVolumeFace &face = mVolumeFaces[i]; - - LLVector4a box_center; - box_center.setAdd(face.mExtents[0], face.mExtents[1]); - box_center.mul(0.5f); - - LLVector4a box_size; - box_size.setSub(face.mExtents[1], face.mExtents[0]); - - if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) - { - if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them - { - genBinormals(i); - } - - if (!face.mOctree) - { - face.createOctree(); - } - - //LLVector4a* p = (LLVector4a*) face.mPositions; - - LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal); - intersect.traverse(face.mOctree); - if (intersect.mHitFace) - { - hit_face = i; - } - } - } - - - return hit_face; -} - -class LLVertexIndexPair -{ -public: - LLVertexIndexPair(const LLVector3 &vertex, const S32 index); - - LLVector3 mVertex; - S32 mIndex; -}; - -LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index) -{ - mVertex = vertex; - mIndex = index; -} - -const F32 VERTEX_SLOP = 0.00001f; -const F32 VERTEX_SLOP_SQRD = VERTEX_SLOP * VERTEX_SLOP; - -struct lessVertex -{ - bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) - { - const F32 slop = VERTEX_SLOP; - - if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) - { - return TRUE; - } - else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) - { - return FALSE; - } - - if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) - { - return TRUE; - } - else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) - { - return FALSE; - } - - if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) - { - return TRUE; - } - else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) - { - return FALSE; - } - - return FALSE; - } -}; - -struct lessTriangle -{ - bool operator()(const S32 *a, const S32 *b) - { - if (*a < *b) - { - return TRUE; - } - else if (*a > *b) - { - return FALSE; - } - - if (*(a+1) < *(b+1)) - { - return TRUE; - } - else if (*(a+1) > *(b+1)) - { - return FALSE; - } - - if (*(a+2) < *(b+2)) - { - return TRUE; - } - else if (*(a+2) > *(b+2)) - { - return FALSE; - } - - return FALSE; - } -}; - -BOOL equalTriangle(const S32 *a, const S32 *b) -{ - if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) - { - return TRUE; - } - return FALSE; -} - -BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, - const std::vector<Point>& input_vertices, - const S32 num_input_triangles, - S32 *input_triangles, - S32 &num_output_vertices, - LLVector3 **output_vertices, - S32 &num_output_triangles, - S32 **output_triangles) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - /* Testing: avoid any cleanup - static BOOL skip_cleanup = TRUE; - if ( skip_cleanup ) - { - num_output_vertices = num_input_vertices; - num_output_triangles = num_input_triangles; - - *output_vertices = new LLVector3[num_input_vertices]; - for (S32 index = 0; index < num_input_vertices; index++) - { - (*output_vertices)[index] = input_vertices[index].mPos; - } - - *output_triangles = new S32[num_input_triangles*3]; - memcpy(*output_triangles, input_triangles, 3*num_input_triangles*sizeof(S32)); // Flawfinder: ignore - return TRUE; - } - */ - - // Here's how we do this: - // Create a structure which contains the original vertex index and the - // LLVector3 data. - // "Sort" the data by the vectors - // Create an array the size of the old vertex list, with a mapping of - // old indices to new indices. - // Go through triangles, shift so the lowest index is first - // Sort triangles by first index - // Remove duplicate triangles - // Allocate and pack new triangle data. - - //LLTimer cleanupTimer; - //llinfos << "In vertices: " << num_input_vertices << llendl; - //llinfos << "In triangles: " << num_input_triangles << llendl; - - S32 i; - typedef std::multiset<LLVertexIndexPair*, lessVertex> vertex_set_t; - vertex_set_t vertex_list; - - LLVertexIndexPair *pairp = NULL; - for (i = 0; i < num_input_vertices; i++) - { - LLVertexIndexPair *new_pairp = new LLVertexIndexPair(input_vertices[i].mPos, i); - vertex_list.insert(new_pairp); - } - - // Generate the vertex mapping and the list of vertices without - // duplicates. This will crash if there are no vertices. - llassert(num_input_vertices > 0); // check for no vertices! - S32 *vertex_mapping = new S32[num_input_vertices]; - LLVector3 *new_vertices = new LLVector3[num_input_vertices]; - LLVertexIndexPair *prev_pairp = NULL; - - S32 new_num_vertices; - - new_num_vertices = 0; - for (vertex_set_t::iterator iter = vertex_list.begin(), - end = vertex_list.end(); - iter != end; iter++) - { - pairp = *iter; - if (!prev_pairp || ((pairp->mVertex - prev_pairp->mVertex).magVecSquared() >= VERTEX_SLOP_SQRD)) - { - new_vertices[new_num_vertices] = pairp->mVertex; - //llinfos << "Added vertex " << new_num_vertices << " : " << pairp->mVertex << llendl; - new_num_vertices++; - // Update the previous - prev_pairp = pairp; - } - else - { - //llinfos << "Removed duplicate vertex " << pairp->mVertex << ", distance magVecSquared() is " << (pairp->mVertex - prev_pairp->mVertex).magVecSquared() << llendl; - } - vertex_mapping[pairp->mIndex] = new_num_vertices - 1; - } - - // Iterate through triangles and remove degenerates, re-ordering vertices - // along the way. - S32 *new_triangles = new S32[num_input_triangles * 3]; - S32 new_num_triangles = 0; - - for (i = 0; i < num_input_triangles; i++) - { - S32 v1 = i*3; - S32 v2 = v1 + 1; - S32 v3 = v1 + 2; - - //llinfos << "Checking triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; - input_triangles[v1] = vertex_mapping[input_triangles[v1]]; - input_triangles[v2] = vertex_mapping[input_triangles[v2]]; - input_triangles[v3] = vertex_mapping[input_triangles[v3]]; - - if ((input_triangles[v1] == input_triangles[v2]) - || (input_triangles[v1] == input_triangles[v3]) - || (input_triangles[v2] == input_triangles[v3])) - { - //llinfos << "Removing degenerate triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; - // Degenerate triangle, skip - continue; - } - - if (input_triangles[v1] < input_triangles[v2]) - { - if (input_triangles[v1] < input_triangles[v3]) - { - // (0 < 1) && (0 < 2) - new_triangles[new_num_triangles*3] = input_triangles[v1]; - new_triangles[new_num_triangles*3+1] = input_triangles[v2]; - new_triangles[new_num_triangles*3+2] = input_triangles[v3]; - } - else - { - // (0 < 1) && (2 < 0) - new_triangles[new_num_triangles*3] = input_triangles[v3]; - new_triangles[new_num_triangles*3+1] = input_triangles[v1]; - new_triangles[new_num_triangles*3+2] = input_triangles[v2]; - } - } - else if (input_triangles[v2] < input_triangles[v3]) - { - // (1 < 0) && (1 < 2) - new_triangles[new_num_triangles*3] = input_triangles[v2]; - new_triangles[new_num_triangles*3+1] = input_triangles[v3]; - new_triangles[new_num_triangles*3+2] = input_triangles[v1]; - } - else - { - // (1 < 0) && (2 < 1) - new_triangles[new_num_triangles*3] = input_triangles[v3]; - new_triangles[new_num_triangles*3+1] = input_triangles[v1]; - new_triangles[new_num_triangles*3+2] = input_triangles[v2]; - } - new_num_triangles++; - } - - if (new_num_triangles == 0) - { - llwarns << "Created volume object with 0 faces." << llendl; - delete[] new_triangles; - delete[] vertex_mapping; - delete[] new_vertices; - return FALSE; - } - - typedef std::set<S32*, lessTriangle> triangle_set_t; - triangle_set_t triangle_list; - - for (i = 0; i < new_num_triangles; i++) - { - triangle_list.insert(&new_triangles[i*3]); - } - - // Sort through the triangle list, and delete duplicates - - S32 *prevp = NULL; - S32 *curp = NULL; - - S32 *sorted_tris = new S32[new_num_triangles*3]; - S32 cur_tri = 0; - for (triangle_set_t::iterator iter = triangle_list.begin(), - end = triangle_list.end(); - iter != end; iter++) - { - curp = *iter; - if (!prevp || !equalTriangle(prevp, curp)) - { - //llinfos << "Added triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl; - sorted_tris[cur_tri*3] = *curp; - sorted_tris[cur_tri*3+1] = *(curp+1); - sorted_tris[cur_tri*3+2] = *(curp+2); - cur_tri++; - prevp = curp; - } - else - { - //llinfos << "Skipped triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl; - } - } - - *output_vertices = new LLVector3[new_num_vertices]; - num_output_vertices = new_num_vertices; - for (i = 0; i < new_num_vertices; i++) - { - (*output_vertices)[i] = new_vertices[i]; - } - - *output_triangles = new S32[cur_tri*3]; - num_output_triangles = cur_tri; - memcpy(*output_triangles, sorted_tris, 3*cur_tri*sizeof(S32)); /* Flawfinder: ignore */ - - /* - llinfos << "Out vertices: " << num_output_vertices << llendl; - llinfos << "Out triangles: " << num_output_triangles << llendl; - for (i = 0; i < num_output_vertices; i++) - { - llinfos << i << ":" << (*output_vertices)[i] << llendl; - } - for (i = 0; i < num_output_triangles; i++) - { - llinfos << i << ":" << (*output_triangles)[i*3] << ":" << (*output_triangles)[i*3+1] << ":" << (*output_triangles)[i*3+2] << llendl; - } - */ - - //llinfos << "Out vertices: " << num_output_vertices << llendl; - //llinfos << "Out triangles: " << num_output_triangles << llendl; - delete[] vertex_mapping; - vertex_mapping = NULL; - delete[] new_vertices; - new_vertices = NULL; - delete[] new_triangles; - new_triangles = NULL; - delete[] sorted_tris; - sorted_tris = NULL; - triangle_list.clear(); - std::for_each(vertex_list.begin(), vertex_list.end(), DeletePointer()); - vertex_list.clear(); - - return TRUE; -} - - -BOOL LLVolumeParams::importFile(LLFILE *fp) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - //llinfos << "importing volume" << llendl; - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importFile(fp); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importFile(fp); - } - else - { - llwarns << "unknown keyword " << keyword << " in volume import" << llendl; - } - } - - return TRUE; -} - -BOOL LLVolumeParams::exportFile(LLFILE *fp) const -{ - fprintf(fp,"\tshape 0\n"); - fprintf(fp,"\t{\n"); - mPathParams.exportFile(fp); - mProfileParams.exportFile(fp); - fprintf(fp, "\t}\n"); - return TRUE; -} - - -BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - //llinfos << "importing volume" << llendl; - const S32 BUFSIZE = 16384; - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf(buffer, " %255s", keyword); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importLegacyStream(input_stream); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importLegacyStream(input_stream); - } - else - { - llwarns << "unknown keyword " << keyword << " in volume import" << llendl; - } - } - - return TRUE; -} - -BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - output_stream <<"\tshape 0\n"; - output_stream <<"\t{\n"; - mPathParams.exportLegacyStream(output_stream); - mProfileParams.exportLegacyStream(output_stream); - output_stream << "\t}\n"; - return TRUE; -} - -LLSD LLVolumeParams::sculptAsLLSD() const -{ - LLSD sd = LLSD(); - sd["id"] = getSculptID(); - sd["type"] = getSculptType(); - - return sd; -} - -bool LLVolumeParams::sculptFromLLSD(LLSD& sd) -{ - setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); - return true; -} - -LLSD LLVolumeParams::asLLSD() const -{ - LLSD sd = LLSD(); - sd["path"] = mPathParams; - sd["profile"] = mProfileParams; - sd["sculpt"] = sculptAsLLSD(); - - return sd; -} - -bool LLVolumeParams::fromLLSD(LLSD& sd) -{ - mPathParams.fromLLSD(sd["path"]); - mProfileParams.fromLLSD(sd["profile"]); - sculptFromLLSD(sd["sculpt"]); - - return true; -} - -void LLVolumeParams::reduceS(F32 begin, F32 end) -{ - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mProfileParams.getBegin(); - F32 b = mProfileParams.getEnd(); - mProfileParams.setBegin(a + begin * (b - a)); - mProfileParams.setEnd(a + end * (b - a)); -} - -void LLVolumeParams::reduceT(F32 begin, F32 end) -{ - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mPathParams.getBegin(); - F32 b = mPathParams.getEnd(); - mPathParams.setBegin(a + begin * (b - a)); - mPathParams.setEnd(a + end * (b - a)); -} - -const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity -const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity - -// returns TRUE if the shape can be approximated with a convex shape -// for collison purposes -BOOL LLVolumeParams::isConvex() const -{ - if (!getSculptID().isNull()) - { - // can't determine, be safe and say no: - return FALSE; - } - - F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); - F32 hollow = mProfileParams.getHollow(); - - U8 path_type = mPathParams.getCurveType(); - if ( path_length > MIN_CONCAVE_PATH_WEDGE - && ( mPathParams.getTwist() != mPathParams.getTwistBegin() - || (hollow > 0.f - && LL_PCODE_PATH_LINE != path_type) ) ) - { - // twist along a "not too short" path is concave - return FALSE; - } - - F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); - BOOL same_hole = hollow == 0.f - || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; - - F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // it is a sphere and spheres get twice the minimum profile wedge - min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; - } - - BOOL convex_profile = ( ( profile_length == 1.f - || profile_length <= 0.5f ) - && hollow == 0.f ) // trivially convex - || ( profile_length <= min_profile_wedge - && same_hole ); // effectvely convex (even when hollow) - - if (!convex_profile) - { - // profile is concave - return FALSE; - } - - if ( LL_PCODE_PATH_LINE == path_type ) - { - // straight paths with convex profile - return TRUE; - } - - BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); - if (concave_path) - { - return FALSE; - } - - // we're left with spheres, toroids and tubes - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // at this stage all spheres must be convex - return TRUE; - } - - // it's a toroid or tube - if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) - { - // effectively convex - return TRUE; - } - - return FALSE; -} - -// debug -void LLVolumeParams::setCube() -{ - mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); - mProfileParams.setBegin(0.f); - mProfileParams.setEnd(1.f); - mProfileParams.setHollow(0.f); - - mPathParams.setBegin(0.f); - mPathParams.setEnd(1.f); - mPathParams.setScale(1.f, 1.f); - mPathParams.setShear(0.f, 0.f); - mPathParams.setCurveType(LL_PCODE_PATH_LINE); - mPathParams.setTwistBegin(0.f); - mPathParams.setTwistEnd(0.f); - mPathParams.setRadiusOffset(0.f); - mPathParams.setTaper(0.f, 0.f); - mPathParams.setRevolutions(0.f); - mPathParams.setSkew(0.f); -} - -LLFaceID LLVolume::generateFaceMask() -{ - LLFaceID new_mask = 0x0000; - - switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - new_mask |= LL_FACE_OUTER_SIDE_0; - break; - case LL_PCODE_PROFILE_SQUARE: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_EQUALTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - default: - llerrs << "Unknown profile!" << llendl; - break; - } - - // handle hollow objects - if (mParams.getProfileParams().getHollow() > 0) - { - new_mask |= LL_FACE_INNER_SIDE; - } - - // handle open profile curves - if (mProfilep->isOpen()) - { - new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; - } - - // handle open path curves - if (mPathp->isOpen()) - { - new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; - } - - return new_mask; -} - -BOOL LLVolume::isFaceMaskValid(LLFaceID face_mask) -{ - LLFaceID test_mask = 0; - for(S32 i = 0; i < getNumFaces(); i++) - { - test_mask |= mProfilep->mFaces[i].mFaceID; - } - - return test_mask == face_mask; -} - -BOOL LLVolume::isConvex() const -{ - // mParams.isConvex() may return FALSE even though the final - // geometry is actually convex due to LOD approximations. - // TODO -- provide LLPath and LLProfile with isConvex() methods - // that correctly determine convexity. -- Leviathan - return mParams.isConvex(); -} - - -std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params) -{ - s << "{type=" << (U32) profile_params.mCurveType; - s << ", begin=" << profile_params.mBegin; - s << ", end=" << profile_params.mEnd; - s << ", hollow=" << profile_params.mHollow; - s << "}"; - return s; -} - - -std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params) -{ - s << "{type=" << (U32) path_params.mCurveType; - s << ", begin=" << path_params.mBegin; - s << ", end=" << path_params.mEnd; - s << ", twist=" << path_params.mTwistEnd; - s << ", scale=" << path_params.mScale; - s << ", shear=" << path_params.mShear; - s << ", twist_begin=" << path_params.mTwistBegin; - s << ", radius_offset=" << path_params.mRadiusOffset; - s << ", taper=" << path_params.mTaper; - s << ", revolutions=" << path_params.mRevolutions; - s << ", skew=" << path_params.mSkew; - s << "}"; - return s; -} - - -std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params) -{ - s << "{profileparams = " << volume_params.mProfileParams; - s << ", pathparams = " << volume_params.mPathParams; - s << "}"; - return s; -} - - -std::ostream& operator<<(std::ostream &s, const LLProfile &profile) -{ - s << " {open=" << (U32) profile.mOpen; - s << ", dirty=" << profile.mDirty; - s << ", totalout=" << profile.mTotalOut; - s << ", total=" << profile.mTotal; - s << "}"; - return s; -} - - -std::ostream& operator<<(std::ostream &s, const LLPath &path) -{ - s << "{open=" << (U32) path.mOpen; - s << ", dirty=" << path.mDirty; - s << ", step=" << path.mStep; - s << ", total=" << path.mTotal; - s << "}"; - return s; -} - -std::ostream& operator<<(std::ostream &s, const LLVolume &volume) -{ - s << "{params = " << volume.getParams(); - s << ", path = " << *volume.mPathp; - s << ", profile = " << *volume.mProfilep; - s << "}"; - return s; -} - - -std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) -{ - s << "{params = " << volumep->getParams(); - s << ", path = " << *(volumep->mPathp); - s << ", profile = " << *(volumep->mProfilep); - s << "}"; - return s; -} - -LLVolumeFace::LLVolumeFace() : - mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mBinormals(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), - mOctree(NULL) -{ - mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3); - mCenter = mExtents+2; -} - -LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) -: mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mBinormals(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), - mOctree(NULL) -{ - mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3); - mCenter = mExtents+2; - *this = src; -} - -LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) -{ - if (&src == this) - { //self assignment, do nothing - return *this; - } - - mID = src.mID; - mTypeMask = src.mTypeMask; - mBeginS = src.mBeginS; - mBeginT = src.mBeginT; - mNumS = src.mNumS; - mNumT = src.mNumT; - - mExtents[0] = src.mExtents[0]; - mExtents[1] = src.mExtents[1]; - *mCenter = *src.mCenter; - - mNumVertices = 0; - mNumIndices = 0; - - freeData(); - - LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a)); - - resizeVertices(src.mNumVertices); - resizeIndices(src.mNumIndices); - - if (mNumVertices) - { - S32 vert_size = mNumVertices*sizeof(LLVector4a); - S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); - - - if (src.mBinormals) - { - allocateBinormals(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) src.mBinormals, vert_size); - } - else - { - free(mBinormals); - mBinormals = NULL; - } - - if (src.mWeights) - { - allocateWeights(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); - } - else - { - free(mWeights); - mWeights = NULL; - } - } - - if (mNumIndices) - { - S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); - } - - //delete - return *this; -} - -LLVolumeFace::~LLVolumeFace() -{ - free(mExtents); - mExtents = NULL; - - freeData(); -} - -void LLVolumeFace::freeData() -{ - free(mPositions); - mPositions = NULL; - free( mNormals); - mNormals = NULL; - free(mTexCoords); - mTexCoords = NULL; - free(mIndices); - mIndices = NULL; - free(mBinormals); - mBinormals = NULL; - free(mWeights); - mWeights = NULL; - - delete mOctree; - mOctree = NULL; -} - -BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) -{ - //tree for this face is no longer valid - delete mOctree; - mOctree = NULL; - - BOOL ret = FALSE ; - if (mTypeMask & CAP_MASK) - { - ret = createCap(volume, partial_build); - } - else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) - { - ret = createSide(volume, partial_build); - } - else - { - llerrs << "Unknown/uninitialized face type!" << llendl; - } - - //update the range of the texture coordinates - if(ret) - { - mTexCoordExtents[0].setVec(1.f, 1.f) ; - mTexCoordExtents[1].setVec(0.f, 0.f) ; - - for(U32 i = 0 ; i < mNumVertices ; i++) - { - if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0]) - { - mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ; - } - if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0]) - { - mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ; - } - - if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1]) - { - mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ; - } - if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1]) - { - mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ; - } - } - mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ; - mTexCoordExtents[0].mV[1] = llmax(0.f, mTexCoordExtents[0].mV[1]) ; - mTexCoordExtents[1].mV[0] = llmin(1.f, mTexCoordExtents[1].mV[0]) ; - mTexCoordExtents[1].mV[1] = llmin(1.f, mTexCoordExtents[1].mV[1]) ; - } - - return ret ; -} - -void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) -{ - cv.setPosition(mPositions[index]); - cv.setNormal(mNormals[index]); - cv.mTexCoord = mTexCoords[index]; -} - -bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const -{ - return getPosition().equals3(rhs.getPosition()) && - mTexCoord == rhs.mTexCoord && - getNormal().equals3(rhs.getNormal()); -} - -bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const -{ - if (a.mV[0] != b.mV[0]) - { - return a.mV[0] < b.mV[0]; - } - - if (a.mV[1] != b.mV[1]) - { - return a.mV[1] < b.mV[1]; - } - - return a.mV[2] < b.mV[2]; -} - -void LLVolumeFace::optimize(F32 angle_cutoff) -{ - LLVolumeFace new_face; - - //map of points to vector of vertices at that point - VertexMapData::PointMap point_map; - - //remove redundant vertices - for (U32 i = 0; i < mNumIndices; ++i) - { - U16 index = mIndices[i]; - - LLVolumeFace::VertexData cv; - getVertexData(index, cv); - - BOOL found = FALSE; - VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); - if (point_iter != point_map.end()) - { //duplicate point might exist - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - LLVolumeFace::VertexData& tv = (point_iter->second)[j]; - if (tv.compareNormal(cv, angle_cutoff)) - { - found = TRUE; - new_face.pushIndex((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - new_face.pushVertex(cv); - U16 index = (U16) new_face.mNumVertices-1; - new_face.pushIndex(index); - - VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); - } - } - } - - swapData(new_face); -} - -class LLVCacheTriangleData; - -class LLVCacheVertexData -{ -public: - S32 mIdx; - S32 mCacheTag; - F32 mScore; - U32 mActiveTriangles; - std::vector<LLVCacheTriangleData*> mTriangles; - - LLVCacheVertexData() - { - mCacheTag = -1; - mScore = 0.f; - mActiveTriangles = 0; - mIdx = -1; - } -}; - -class LLVCacheTriangleData -{ -public: - bool mActive; - F32 mScore; - LLVCacheVertexData* mVertex[3]; - - LLVCacheTriangleData() - { - mActive = true; - mScore = 0.f; - mVertex[0] = mVertex[1] = mVertex[2] = NULL; - } - - void complete() - { - mActive = false; - for (S32 i = 0; i < 3; ++i) - { - if (mVertex[i]) - { - llassert_always(mVertex[i]->mActiveTriangles > 0); - mVertex[i]->mActiveTriangles--; - } - } - } - - bool operator<(const LLVCacheTriangleData& rhs) const - { //highest score first - return rhs.mScore < mScore; - } -}; - -const F32 FindVertexScore_CacheDecayPower = 1.5f; -const F32 FindVertexScore_LastTriScore = 0.75f; -const F32 FindVertexScore_ValenceBoostScale = 2.0f; -const F32 FindVertexScore_ValenceBoostPower = 0.5f; -const U32 MaxSizeVertexCache = 32; - -F32 find_vertex_score(LLVCacheVertexData& data) -{ - if (data.mActiveTriangles == 0) - { //no triangle references this vertex - return -1.f; - } - - F32 score = 0.f; - - S32 cache_idx = data.mCacheTag; - - if (cache_idx < 0) - { - //not in cache - } - else - { - if (cache_idx < 3) - { //vertex was in the last triangle - score = FindVertexScore_LastTriScore; - } - else - { //more points for being higher in the cache - F32 scaler = 1.f/(MaxSizeVertexCache-3); - score = 1.f-((cache_idx-3)*scaler); - score = powf(score, FindVertexScore_CacheDecayPower); - } - } - - //bonus points for having low valence - F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); - score += FindVertexScore_ValenceBoostScale * valence_boost; - - return score; -} - -class LLVCacheFIFO -{ -public: - LLVCacheVertexData* mCache[MaxSizeVertexCache]; - U32 mMisses; - - LLVCacheFIFO() - { - mMisses = 0; - for (U32 i = 0; i < MaxSizeVertexCache; ++i) - { - mCache[i] = NULL; - } - } - - void addVertex(LLVCacheVertexData* data) - { - if (data->mCacheTag == -1) - { - mMisses++; - - S32 end = MaxSizeVertexCache-1; - - if (mCache[end]) - { - mCache[end]->mCacheTag = -1; - } - - for (S32 i = end; i > 0; --i) - { - mCache[i] = mCache[i-1]; - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - data->mCacheTag = 0; - } - } -}; - -class LLVCacheLRU -{ -public: - LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; - - LLVCacheTriangleData* mBestTriangle; - - U32 mMisses; - - LLVCacheLRU() - { - for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) - { - mCache[i] = NULL; - } - - mBestTriangle = NULL; - mMisses = 0; - } - - void addVertex(LLVCacheVertexData* data) - { - S32 end = MaxSizeVertexCache+2; - if (data->mCacheTag != -1) - { //just moving a vertex to the front of the cache - end = data->mCacheTag; - } - else - { - mMisses++; - if (mCache[end]) - { //adding a new vertex, vertex at end of cache falls off - mCache[end]->mCacheTag = -1; - } - } - - for (S32 i = end; i > 0; --i) - { //adjust cache pointers and tags - mCache[i] = mCache[i-1]; - - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - mCache[0]->mCacheTag = 0; - } - - void addTriangle(LLVCacheTriangleData* data) - { - addVertex(data->mVertex[0]); - addVertex(data->mVertex[1]); - addVertex(data->mVertex[2]); - } - - void updateScores() - { - for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) - { //trailing 3 vertices aren't actually in the cache for scoring purposes - if (mCache[i]) - { - mCache[i]->mCacheTag = -1; - } - } - - for (U32 i = 0; i < MaxSizeVertexCache; ++i) - { //update scores of vertices in cache - if (mCache[i]) - { - mCache[i]->mScore = find_vertex_score(*(mCache[i])); - llassert_always(mCache[i]->mCacheTag == i); - } - } - - mBestTriangle = NULL; - //update triangle scores - for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) - { - if (mCache[i]) - { - for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j) - { - LLVCacheTriangleData* tri = mCache[i]->mTriangles[j]; - if (tri->mActive) - { - tri->mScore = tri->mVertex[0]->mScore; - tri->mScore += tri->mVertex[1]->mScore; - tri->mScore += tri->mVertex[2]->mScore; - - if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) - { - mBestTriangle = tri; - } - } - } - } - } - - //knock trailing 3 vertices off the cache - for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) - { - if (mCache[i]) - { - llassert_always(mCache[i]->mCacheTag == -1); - mCache[i] = NULL; - } - } - } -}; - - -void LLVolumeFace::cacheOptimize() -{ //optimize for vertex cache according to Forsyth method: - // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html - - LLVCacheLRU cache; - - //mapping of vertices to triangles and indices - std::vector<LLVCacheVertexData> vertex_data; - - //mapping of triangles do vertices - std::vector<LLVCacheTriangleData> triangle_data; - - triangle_data.resize(mNumIndices/3); - vertex_data.resize(mNumVertices); - - for (U32 i = 0; i < mNumIndices; i++) - { //populate vertex data and triangle data arrays - U16 idx = mIndices[i]; - U32 tri_idx = i/3; - - vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx])); - vertex_data[idx].mIdx = idx; - triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]); - } - - /*F32 pre_acmr = 1.f; - //measure cache misses from before rebuild - { - LLVCacheFIFO test_cache; - for (U32 i = 0; i < mNumIndices; ++i) - { - test_cache.addVertex(&vertex_data[mIndices[i]]); - } - - for (U32 i = 0; i < mNumVertices; i++) - { - vertex_data[i].mCacheTag = -1; - } - - pre_acmr = (F32) test_cache.mMisses/(mNumIndices/3); - }*/ - - for (U32 i = 0; i < mNumVertices; i++) - { //initialize score values (no cache -- might try a fifo cache here) - vertex_data[i].mScore = find_vertex_score(vertex_data[i]); - vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size(); - - for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j) - { - vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore; - } - } - - //sort triangle data by score - std::sort(triangle_data.begin(), triangle_data.end()); - - std::vector<U16> new_indices; - - LLVCacheTriangleData* tri; - - //prime pump by adding first triangle to cache; - tri = &(triangle_data[0]); - cache.addTriangle(tri); - new_indices.push_back(tri->mVertex[0]->mIdx); - new_indices.push_back(tri->mVertex[1]->mIdx); - new_indices.push_back(tri->mVertex[2]->mIdx); - tri->complete(); - - U32 breaks = 0; - for (U32 i = 1; i < mNumIndices/3; ++i) - { - cache.updateScores(); - tri = cache.mBestTriangle; - if (!tri) - { - breaks++; - for (U32 j = 0; j < triangle_data.size(); ++j) - { - if (triangle_data[j].mActive) - { - tri = &(triangle_data[j]); - break; - } - } - } - - cache.addTriangle(tri); - new_indices.push_back(tri->mVertex[0]->mIdx); - new_indices.push_back(tri->mVertex[1]->mIdx); - new_indices.push_back(tri->mVertex[2]->mIdx); - tri->complete(); - } - - for (U32 i = 0; i < mNumIndices; ++i) - { - mIndices[i] = new_indices[i]; - } - - /*F32 post_acmr = 1.f; - //measure cache misses from after rebuild - { - LLVCacheFIFO test_cache; - for (U32 i = 0; i < mNumVertices; i++) - { - vertex_data[i].mCacheTag = -1; - } - - for (U32 i = 0; i < mNumIndices; ++i) - { - test_cache.addVertex(&vertex_data[mIndices[i]]); - } - - post_acmr = (F32) test_cache.mMisses/(mNumIndices/3); - }*/ - - //optimize for pre-TnL cache - - //allocate space for new buffer - S32 num_verts = mNumVertices; - LLVector4a* pos = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - LLVector4a* norm = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - LLVector2* tc = (LLVector2*) malloc(size); - - LLVector4a* wght = NULL; - if (mWeights) - { - wght = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - } - - LLVector4a* binorm = NULL; - if (mBinormals) - { - binorm = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - } - - //allocate mapping of old indices to new indices - std::vector<S32> new_idx; - new_idx.resize(mNumVertices, -1); - - S32 cur_idx = 0; - for (U32 i = 0; i < mNumIndices; ++i) - { - U16 idx = mIndices[i]; - if (new_idx[idx] == -1) - { //this vertex hasn't been added yet - new_idx[idx] = cur_idx; - - //copy vertex data - pos[cur_idx] = mPositions[idx]; - norm[cur_idx] = mNormals[idx]; - tc[cur_idx] = mTexCoords[idx]; - if (mWeights) - { - wght[cur_idx] = mWeights[idx]; - } - if (mBinormals) - { - binorm[cur_idx] = mBinormals[idx]; - } - - cur_idx++; - } - } - - for (U32 i = 0; i < mNumIndices; ++i) - { - mIndices[i] = new_idx[mIndices[i]]; - } - - free(mPositions); - free(mNormals); - free(mTexCoords); - free(mWeights); - free(mBinormals); - - mPositions = pos; - mNormals = norm; - mTexCoords = tc; - mWeights = wght; - mBinormals = binorm; - - //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); - //llinfos << result << llendl; - -} - -void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) -{ - if (mOctree) - { - return; - } - - mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL); - new LLVolumeOctreeListener(mOctree); - - for (U32 i = 0; i < mNumIndices; i+= 3) - { //for each triangle - LLPointer<LLVolumeTriangle> tri = new LLVolumeTriangle(); - - const LLVector4a& v0 = mPositions[mIndices[i]]; - const LLVector4a& v1 = mPositions[mIndices[i+1]]; - const LLVector4a& v2 = mPositions[mIndices[i+2]]; - - //store pointers to vertex data - tri->mV[0] = &v0; - tri->mV[1] = &v1; - tri->mV[2] = &v2; - - //store indices - tri->mIndex[0] = mIndices[i]; - tri->mIndex[1] = mIndices[i+1]; - tri->mIndex[2] = mIndices[i+2]; - - //get minimum point - LLVector4a min = v0; - min.setMin(min, v1); - min.setMin(min, v2); - - //get maximum point - LLVector4a max = v0; - max.setMax(max, v1); - max.setMax(max, v2); - - //compute center - LLVector4a center; - center.setAdd(min, max); - center.mul(0.5f); - - tri->mPositionGroup = center; - - //compute "radius" - LLVector4a size; - size.setSub(max,min); - - tri->mRadius = size.getLength3().getF32() * scaler; - - //insert - mOctree->insert(tri); - } - - //remove unneeded octree layers - while (!mOctree->balance()) { } - - //calculate AABB for each node - LLVolumeOctreeRebound rebound(this); - rebound.traverse(mOctree); - - if (gDebugGL) - { - LLVolumeOctreeValidate validate; - validate.traverse(mOctree); - } -} - - -void LLVolumeFace::swapData(LLVolumeFace& rhs) -{ - llswap(rhs.mPositions, mPositions); - llswap(rhs.mNormals, mNormals); - llswap(rhs.mBinormals, mBinormals); - llswap(rhs.mTexCoords, mTexCoords); - llswap(rhs.mIndices,mIndices); - llswap(rhs.mNumVertices, mNumVertices); - llswap(rhs.mNumIndices, mNumIndices); -} - -void LerpPlanarVertex(LLVolumeFace::VertexData& v0, - LLVolumeFace::VertexData& v1, - LLVolumeFace::VertexData& v2, - LLVolumeFace::VertexData& vout, - F32 coef01, - F32 coef02) -{ - - LLVector4a lhs; - lhs.setSub(v1.getPosition(), v0.getPosition()); - lhs.mul(coef01); - LLVector4a rhs; - rhs.setSub(v2.getPosition(), v0.getPosition()); - rhs.mul(coef02); - - rhs.add(lhs); - rhs.add(v0.getPosition()); - - vout.setPosition(rhs); - - vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); - vout.setNormal(v0.getNormal()); -} - -BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - const std::vector<LLVolume::Point>& mesh = volume->getMesh(); - const std::vector<LLVector3>& profile = volume->getProfile().mProfile; - S32 max_s = volume->getProfile().getTotal(); - 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]; - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - { - VertexData corners[4]; - VertexData baseVert; - for(S32 t = 0; t < 4; t++) - { - corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); - corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; - corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; - } - - { - LLVector4a lhs; - lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); - LLVector4a rhs; - rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); - baseVert.getNormal().setCross3(lhs, rhs); - baseVert.getNormal().normalize3fast(); - } - - if(!(mTypeMask & TOP_MASK)) - { - baseVert.getNormal().mul(-1.0f); - } - else - { - //Swap the UVs on the U(X) axis for top face - LLVector2 swap; - swap = corners[0].mTexCoord; - corners[0].mTexCoord=corners[3].mTexCoord; - corners[3].mTexCoord=swap; - swap = corners[1].mTexCoord; - corners[1].mTexCoord=corners[2].mTexCoord; - corners[2].mTexCoord=swap; - } - - LLVector4a binormal; - - calc_binormal_from_triangle( binormal, - corners[0].getPosition(), corners[0].mTexCoord, - corners[1].getPosition(), corners[1].mTexCoord, - corners[2].getPosition(), corners[2].mTexCoord); - - binormal.normalize3fast(); - - S32 size = (grid_size+1)*(grid_size+1); - resizeVertices(size); - allocateBinormals(size); - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector4a* binorm = (LLVector4a*) mBinormals; - LLVector2* tc = (LLVector2*) mTexCoords; - - for(int gx = 0;gx<grid_size+1;gx++) - { - for(int gy = 0;gy<grid_size+1;gy++) - { - VertexData newVert; - LerpPlanarVertex( - corners[0], - corners[1], - corners[3], - newVert, - (F32)gx/(F32)grid_size, - (F32)gy/(F32)grid_size); - - *pos++ = newVert.getPosition(); - *norm++ = baseVert.getNormal(); - *tc++ = newVert.mTexCoord; - *binorm++ = binormal; - - if (gx == 0 && gy == 0) - { - min = newVert.getPosition(); - max = min; - } - else - { - min.setMin(min, newVert.getPosition()); - max.setMax(max, newVert.getPosition()); - } - } - } - - mCenter->setAdd(min, max); - mCenter->mul(0.5f); - } - - if (!partial_build) - { - resizeIndices(grid_size*grid_size*6); - - U16* out = mIndices; - - S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; - for(S32 gx = 0;gx<grid_size;gx++) - { - - for(S32 gy = 0;gy<grid_size;gy++) - { - if (mTypeMask & TOP_MASK) - { - for(S32 i=5;i>=0;i--) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - } - else - { - for(S32 i=0;i<6;i++) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - } - } - } - } - - return TRUE; -} - - -BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - if (!(mTypeMask & HOLLOW_MASK) && - !(mTypeMask & OPEN_MASK) && - ((volume->getParams().getPathParams().getBegin()==0.0f)&& - (volume->getParams().getPathParams().getEnd()==1.0f))&& - (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && - volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) - ){ - return createUnCutCubeCap(volume, partial_build); - } - - S32 num_vertices = 0, num_indices = 0; - - const std::vector<LLVolume::Point>& mesh = volume->getMesh(); - const std::vector<LLVector3>& profile = volume->getProfile().mProfile; - - // All types of caps have the same number of vertices and indices - num_vertices = profile.size(); - num_indices = (profile.size() - 2)*3; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - resizeVertices(num_vertices+1); - allocateBinormals(num_vertices+1); - - if (!partial_build) - { - resizeIndices(num_indices+3); - } - } - else - { - resizeVertices(num_vertices); - allocateBinormals(num_vertices); - - if (!partial_build) - { - resizeIndices(num_indices); - } - } - - S32 max_s = volume->getProfile().getTotal(); - S32 max_t = volume->getPath().mPath.size(); - - mCenter->clear(); - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - // Figure out the normal, assume all caps are flat faces. - // Cross product to get normals. - - LLVector2 cuv; - LLVector2 min_uv, max_uv; - - LLVector4a& min = mExtents[0]; - LLVector4a& max = mExtents[1]; - - LLVector2* tc = (LLVector2*) mTexCoords; - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector4a* binorm = (LLVector4a*) mBinormals; - - // Copy the vertices into the array - for (S32 i = 0; i < num_vertices; i++) - { - if (mTypeMask & TOP_MASK) - { - tc[i].mV[0] = profile[i].mV[0]+0.5f; - tc[i].mV[1] = profile[i].mV[1]+0.5f; - } - else - { - // Mirror for underside. - tc[i].mV[0] = profile[i].mV[0]+0.5f; - tc[i].mV[1] = 0.5f - profile[i].mV[1]; - } - - pos[i].load3(mesh[i + offset].mPos.mV); - - if (i == 0) - { - max = pos[i]; - min = max; - min_uv = max_uv = tc[i]; - } - else - { - update_min_max(min,max,pos[i]); - update_min_max(min_uv, max_uv, tc[i]); - } - } - - mCenter->setAdd(min, max); - mCenter->mul(0.5f); - - cuv = (min_uv + max_uv)*0.5f; - - LLVector4a binormal; - calc_binormal_from_triangle(binormal, - *mCenter, cuv, - pos[0], tc[0], - pos[1], tc[1]); - binormal.normalize3fast(); - - LLVector4a normal; - LLVector4a d0, d1; - - - d0.setSub(*mCenter, pos[0]); - d1.setSub(*mCenter, pos[1]); - - if (mTypeMask & TOP_MASK) - { - normal.setCross3(d0, d1); - } - else - { - normal.setCross3(d1, d0); - } - - normal.normalize3fast(); - - VertexData vd; - vd.setPosition(*mCenter); - vd.mTexCoord = cuv; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - pos[num_vertices] = *mCenter; - tc[num_vertices] = cuv; - num_vertices++; - } - - for (S32 i = 0; i < num_vertices; i++) - { - binorm[i].load4a(binormal.getF32ptr()); - norm[i].load4a(normal.getF32ptr()); - } - - if (partial_build) - { - return TRUE; - } - - if (mTypeMask & HOLLOW_MASK) - { - if (mTypeMask & TOP_MASK) - { - // HOLLOW TOP - // Does it matter if it's open or closed? - djs - - S32 pt1 = 0, pt2 = num_vertices - 1; - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = profile[pt1]; - LLVector3 p2 = profile[pt2]; - LLVector3 pa = profile[pt1+1]; - LLVector3 pb = profile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt1 + 1; - mIndices[i++] = pt2; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2 - 1; - mIndices[i++] = pt2; - pt2--; - } - } - } - else - { - // HOLLOW BOTTOM - // Does it matter if it's open or closed? - djs - - llassert(mTypeMask & BOTTOM_MASK); - S32 pt1 = 0, pt2 = num_vertices - 1; - - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - LLVector3 p1 = profile[pt1]; - LLVector3 p2 = profile[pt2]; - LLVector3 pa = profile[pt1+1]; - LLVector3 pb = profile[pt2-1]; - - p1.mV[VZ] = 0.f; - p2.mV[VZ] = 0.f; - pa.mV[VZ] = 0.f; - pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + - (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + - (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - - area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + - (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - - area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + - (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + - (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + - (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector3 d1 = p1 - pa; - LLVector3 d2 = p2 - pb; - - if (d1.magVecSquared() < d2.magVecSquared()) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - // Flipped backfacing from top - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt1 + 1; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt2 - 1; - pt2--; - } - } - } - } - else - { - // Not hollow, generate the triangle fan. - U16 v1 = 2; - U16 v2 = 1; - - if (mTypeMask & TOP_MASK) - { - v1 = 1; - v2 = 2; - } - - for (S32 i = 0; i < (num_vertices - 2); i++) - { - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+v1] = i; - mIndices[3*i+v2] = i + 1; - } - - - } - - return TRUE; -} - -void LLVolumeFace::createBinormals() -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - if (!mBinormals) - { - allocateBinormals(mNumVertices); - - //generate binormals - LLVector4a* pos = mPositions; - LLVector2* tc = (LLVector2*) mTexCoords; - LLVector4a* binorm = (LLVector4a*) mBinormals; - - LLVector4a* end = mBinormals+mNumVertices; - while (binorm < end) - { - (*binorm++).clear(); - } - - binorm = mBinormals; - - for (U32 i = 0; i < mNumIndices/3; i++) - { //for each triangle - const U16& i0 = mIndices[i*3+0]; - const U16& i1 = mIndices[i*3+1]; - const U16& i2 = mIndices[i*3+2]; - - //calculate binormal - LLVector4a binormal; - calc_binormal_from_triangle(binormal, - pos[i0], tc[i0], - pos[i1], tc[i1], - pos[i2], tc[i2]); - - - //add triangle normal to vertices - binorm[i0].add(binormal); - binorm[i1].add(binormal); - binorm[i2].add(binormal); - - //even out quad contributions - if (i % 2 == 0) - { - binorm[i2].add(binormal); - } - else - { - binorm[i1].add(binormal); - } - } - - //normalize binormals - for (U32 i = 0; i < mNumVertices; i++) - { - binorm[i].normalize3fast(); - //bump map/planar projection code requires normals to be normalized - mNormals[i].normalize3fast(); - } - } -} - -void LLVolumeFace::resizeVertices(S32 num_verts) -{ - free(mPositions); - free(mNormals); - free(mBinormals); - free(mTexCoords); - - mBinormals = NULL; - - if (num_verts) - { - mPositions = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); - assert_aligned(mNormals, 16); - - //pad texture coordinate block end to allow for QWORD reads - S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - mTexCoords = (LLVector2*) malloc(size); - assert_aligned(mTexCoords, 16); - } - else - { - mPositions = NULL; - mNormals = NULL; - mTexCoords = NULL; - } - - mNumVertices = num_verts; -} - -void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) -{ - pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); -} - -void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc) -{ - S32 new_verts = mNumVertices+1; - S32 new_size = new_verts*16; -// S32 old_size = mNumVertices*16; - - //positions - mPositions = (LLVector4a*) realloc(mPositions, new_size); - - //normals - mNormals = (LLVector4a*) realloc(mNormals, new_size); - - //tex coords - new_size = ((new_verts*8)+0xF) & ~0xF; - mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); - - - //just clear binormals - free(mBinormals); - mBinormals = NULL; - - mPositions[mNumVertices] = pos; - mNormals[mNumVertices] = norm; - mTexCoords[mNumVertices] = tc; - - mNumVertices++; -} - -void LLVolumeFace::allocateBinormals(S32 num_verts) -{ - free(mBinormals); - mBinormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); -} - -void LLVolumeFace::allocateWeights(S32 num_verts) -{ - free(mWeights); - mWeights = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); -} - -void LLVolumeFace::resizeIndices(S32 num_indices) -{ - free(mIndices); - - if (num_indices) - { - //pad index block end to allow for QWORD reads - S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; - - mIndices = (U16*) malloc(size); - } - else - { - mIndices = NULL; - } - - mNumIndices = num_indices; -} - -void LLVolumeFace::pushIndex(const U16& idx) -{ - S32 new_count = mNumIndices + 1; - S32 new_size = ((new_count*2)+0xF) & ~0xF; - - S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; - if (new_size != old_size) - { - mIndices = (U16*) realloc(mIndices, new_size); - } - - mIndices[mNumIndices++] = idx; -} - -void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx) -{ - resizeVertices(v.size()); - resizeIndices(idx.size()); - - for (U32 i = 0; i < v.size(); ++i) - { - mPositions[i] = v[i].getPosition(); - mNormals[i] = v[i].getNormal(); - mTexCoords[i] = v[i].mTexCoord; - } - - for (U32 i = 0; i < idx.size(); ++i) - { - mIndices[i] = idx[i]; - } -} - -void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in) -{ - U16 offset = mNumVertices; - - S32 new_count = face.mNumVertices + mNumVertices; - - if (new_count > 65536) - { - llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; - } - - if (face.mNumVertices == 0) - { - llerrs << "Cannot append empty face." << llendl; - } - - //allocate new buffer space - mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); - assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); - assert_aligned(mNormals, 16); - mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); - assert_aligned(mTexCoords, 16); - - mNumVertices = new_count; - - //get destination address of appended face - LLVector4a* dst_pos = mPositions+offset; - LLVector2* dst_tc = mTexCoords+offset; - LLVector4a* dst_norm = mNormals+offset; - - //get source addresses of appended face - const LLVector4a* src_pos = face.mPositions; - const LLVector2* src_tc = face.mTexCoords; - const LLVector4a* src_norm = face.mNormals; - - //load aligned matrices - LLMatrix4a mat, norm_mat; - mat.loadu(mat_in); - norm_mat.loadu(norm_mat_in); - - for (U32 i = 0; i < face.mNumVertices; ++i) - { - //transform appended face position and store - mat.affineTransform(src_pos[i], dst_pos[i]); - - //transform appended face normal and store - norm_mat.rotate(src_norm[i], dst_norm[i]); - dst_norm[i].normalize3fast(); - - //copy appended face texture coordinate - dst_tc[i] = src_tc[i]; - - if (offset == 0 && i == 0) - { //initialize bounding box - mExtents[0] = mExtents[1] = dst_pos[i]; - } - else - { - //stretch bounding box - update_min_max(mExtents[0], mExtents[1], dst_pos[i]); - } - } - - - new_count = mNumIndices + face.mNumIndices; - - //allocate new index buffer - mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); - - //get destination address into new index buffer - U16* dst_idx = mIndices+mNumIndices; - mNumIndices = new_count; - - for (U32 i = 0; i < face.mNumIndices; ++i) - { //copy indices, offsetting by old vertex count - dst_idx[i] = face.mIndices[i]+offset; - } -} - -BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) -{ - LLMemType m1(LLMemType::MTYPE_VOLUME); - - BOOL flat = mTypeMask & FLAT_MASK; - - U8 sculpt_type = volume->getParams().getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - S32 num_vertices, num_indices; - - const std::vector<LLVolume::Point>& mesh = volume->getMesh(); - const std::vector<LLVector3>& profile = volume->getProfile().mProfile; - const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath; - - S32 max_s = volume->getProfile().getTotal(); - - S32 s, t, i; - F32 ss, tt; - - num_vertices = mNumS*mNumT; - num_indices = (mNumS-1)*(mNumT-1)*6; - - if (!partial_build) - { - resizeVertices(num_vertices); - resizeIndices(num_indices); - - if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) - { - mEdge.resize(num_indices); - } - } - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector2* tc = (LLVector2*) mTexCoords; - S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); - S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; - - S32 cur_vertex = 0; - // Copy the vertices into the array - for (t = mBeginT; t < mBeginT + mNumT; t++) - { - tt = path_data[t].mTexT; - for (s = 0; s < num_s; s++) - { - if (mTypeMask & END_MASK) - { - if (s) - { - ss = 1.f; - } - else - { - ss = 0.f; - } - } - else - { - // Get s value for tex-coord. - if (!flat) - { - ss = profile[mBeginS + s].mV[2]; - } - else - { - ss = profile[mBeginS + s].mV[2] - begin_stex; - } - } - - if (sculpt_reverse_horizontal) - { - ss = 1.f - ss; - } - - // Check to see if this triangle wraps around the array. - if (mBeginS + s >= max_s) - { - // We're wrapping - i = mBeginS + s + max_s*(t-1); - } - else - { - i = mBeginS + s + max_s*t; - } - - pos[cur_vertex].load3(mesh[i].mPos.mV); - tc[cur_vertex] = LLVector2(ss,tt); - - norm[cur_vertex].clear(); - cur_vertex++; - - if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0) - { - - pos[cur_vertex].load3(mesh[i].mPos.mV); - tc[cur_vertex] = LLVector2(ss,tt); - - norm[cur_vertex].clear(); - - cur_vertex++; - } - } - - if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) - { - if (mTypeMask & OPEN_MASK) - { - s = num_s-1; - } - else - { - s = 0; - } - - i = mBeginS + s + max_s*t; - ss = profile[mBeginS + s].mV[2] - begin_stex; - pos[cur_vertex].load3(mesh[i].mPos.mV); - tc[cur_vertex] = LLVector2(ss,tt); - norm[cur_vertex].clear(); - - cur_vertex++; - } - } - - - //get bounding box for this side - LLVector4a& face_min = mExtents[0]; - LLVector4a& face_max = mExtents[1]; - mCenter->clear(); - - face_min = face_max = pos[0]; - - for (U32 i = 1; i < mNumVertices; ++i) - { - update_min_max(face_min, face_max, pos[i]); - } - - mCenter->setAdd(face_min, face_max); - mCenter->mul(0.5f); - - S32 cur_index = 0; - S32 cur_edge = 0; - BOOL flat_face = mTypeMask & FLAT_MASK; - - if (!partial_build) - { - // Now we generate the indices. - for (t = 0; t < (mNumT-1); t++) - { - for (s = 0; s < (mNumS-1); s++) - { - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - mIndices[cur_index++] = s + mNumS*(t+1); //top left - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*t; //bottom right - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face - if (t < mNumT-2) { //top right/top left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; - } - else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on T - mEdge[cur_edge++] = s*2+1; - } - if (s > 0) { //top left/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; - } - else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; - } - - if (t > 0) { //bottom left/bottom right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; - } - else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on T - mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; - } - if (s < mNumS-2) { //bottom right/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; - } - else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t; - } - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face - } - } - } - - //clear normals - for (U32 i = 0; i < mNumVertices; i++) - { - mNormals[i].clear(); - } - - //generate normals - for (U32 i = 0; i < mNumIndices/3; i++) //for each triangle - { - const U16* idx = &(mIndices[i*3]); - - - LLVector4a* v[] = - { pos+idx[0], pos+idx[1], pos+idx[2] }; - - LLVector4a* n[] = - { norm+idx[0], norm+idx[1], norm+idx[2] }; - - //calculate triangle normal - LLVector4a a, b, c; - - a.setSub(*v[0], *v[1]); - b.setSub(*v[0], *v[2]); - c.setCross3(a,b); - - n[0]->add(c); - n[1]->add(c); - n[2]->add(c); - - //even out quad contributions - n[i%2+1]->add(c); - } - - // adjust normals based on wrapping and stitching - - LLVector4a top; - top.setSub(pos[0], pos[mNumS*(mNumT-2)]); - BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); - - top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); - BOOL s_top_converges = (top.dot3(top) < 0.000001f); - - if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes - { - if (volume->getPath().isOpen() == FALSE) - { //wrap normals on T - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges)) - { //wrap normals on S - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && - ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) - { - if (s_bottom_converges) - { //all lower S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i].set(1,0,0); - } - } - - if (s_top_converges) - { //all upper S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i+mNumS-1].set(-1,0,0); - } - } - } - } - else // logic for sculpt volumes - { - BOOL average_poles = FALSE; - BOOL wrap_s = FALSE; - BOOL wrap_t = FALSE; - - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - average_poles = TRUE; - - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - wrap_s = TRUE; - - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - wrap_t = TRUE; - - - if (average_poles) - { - // average normals for north pole - - LLVector4a average; - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i] = average; - } - - // average normals for south pole - - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i + mNumS * (mNumT - 1)]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i + mNumS * (mNumT - 1)] = average; - } - - } - - - if (wrap_s) - { - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (wrap_t) - { - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - } - - return TRUE; -} - -// Finds binormal based on three vertices with texture coordinates. -// Fills in dummy values if the triangle has degenerate texture coordinates. -void calc_binormal_from_triangle(LLVector4a& binormal, - - const LLVector4a& pos0, - const LLVector2& tex0, - const LLVector4a& pos1, - const LLVector2& tex1, - const LLVector4a& pos2, - const LLVector2& tex2) -{ - LLVector4a rx0( pos0[VX], tex0.mV[VX], tex0.mV[VY] ); - LLVector4a rx1( pos1[VX], tex1.mV[VX], tex1.mV[VY] ); - LLVector4a rx2( pos2[VX], tex2.mV[VX], tex2.mV[VY] ); - - LLVector4a ry0( pos0[VY], tex0.mV[VX], tex0.mV[VY] ); - LLVector4a ry1( pos1[VY], tex1.mV[VX], tex1.mV[VY] ); - LLVector4a ry2( pos2[VY], tex2.mV[VX], tex2.mV[VY] ); - - LLVector4a rz0( pos0[VZ], tex0.mV[VX], tex0.mV[VY] ); - LLVector4a rz1( pos1[VZ], tex1.mV[VX], tex1.mV[VY] ); - LLVector4a rz2( pos2[VZ], tex2.mV[VX], tex2.mV[VY] ); - - LLVector4a lhs, rhs; - - LLVector4a r0; - lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2); - r0.setCross3(lhs, rhs); - - LLVector4a r1; - lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2); - r1.setCross3(lhs, rhs); - - LLVector4a r2; - lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2); - r2.setCross3(lhs, rhs); - - if( r0[VX] && r1[VX] && r2[VX] ) - { - binormal.set( - -r0[VZ] / r0[VX], - -r1[VZ] / r1[VX], - -r2[VZ] / r2[VX]); - // binormal.normVec(); - } - else - { - binormal.set( 0, 1 , 0 ); - } -} +/** + + * @file llvolume.cpp + * + * $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 "llmemory.h" +#include "llmath.h" + +#include <set> +#if !LL_WINDOWS +#include <stdint.h> +#endif + +#include "llerror.h" +#include "llmemtype.h" + +#include "llvolumemgr.h" +#include "v2math.h" +#include "v3math.h" +#include "v4math.h" +#include "m4math.h" +#include "m3math.h" +#include "llmatrix3a.h" +#include "lloctree.h" +#include "lldarray.h" +#include "llvolume.h" +#include "llvolumeoctree.h" +#include "llstl.h" +#include "llsdserialize.h" +#include "llvector4a.h" +#include "llmatrix4a.h" + +#define DEBUG_SILHOUETTE_BINORMALS 0 +#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette +#define DEBUG_SILHOUETTE_EDGE_MAP 0 // DaveP: Use this to display edge map using the silhouette + +const F32 CUT_MIN = 0.f; +const F32 CUT_MAX = 1.f; +const F32 MIN_CUT_DELTA = 0.02f; + +const F32 HOLLOW_MIN = 0.f; +const F32 HOLLOW_MAX = 0.95f; +const F32 HOLLOW_MAX_SQUARE = 0.7f; + +const F32 TWIST_MIN = -1.f; +const F32 TWIST_MAX = 1.f; + +const F32 RATIO_MIN = 0.f; +const F32 RATIO_MAX = 2.f; // Tom Y: Inverted sense here: 0 = top taper, 2 = bottom taper + +const F32 HOLE_X_MIN= 0.05f; +const F32 HOLE_X_MAX= 1.0f; + +const F32 HOLE_Y_MIN= 0.05f; +const F32 HOLE_Y_MAX= 0.5f; + +const F32 SHEAR_MIN = -0.5f; +const F32 SHEAR_MAX = 0.5f; + +const F32 REV_MIN = 1.f; +const F32 REV_MAX = 4.f; + +const F32 TAPER_MIN = -1.f; +const F32 TAPER_MAX = 1.f; + +const F32 SKEW_MIN = -0.95f; +const F32 SKEW_MAX = 0.95f; + +const F32 SCULPT_MIN_AREA = 0.002f; +const S32 SCULPT_MIN_AREA_DETAIL = 1; + +extern BOOL gDebugGL; + +void assert_aligned(void* ptr, uintptr_t alignment) +{ +#if 0 + uintptr_t t = (uintptr_t) ptr; + if (t%alignment != 0) + { + llerrs << "WTF?" << llendl; + } +#endif +} + +BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) +{ + LLVector3 test = (pt2-pt1)%(pt3-pt2); + + //answer + if(test * norm < 0) + { + return FALSE; + } + else + { + return TRUE; + } +} + +BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) +{ + return LLLineSegmentBoxIntersect(start.mV, end.mV, center.mV, size.mV); +} + +BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size) +{ + F32 fAWdU[3]; + F32 dir[3]; + F32 diff[3]; + + for (U32 i = 0; i < 3; i++) + { + dir[i] = 0.5f * (end[i] - start[i]); + diff[i] = (0.5f * (end[i] + start[i])) - center[i]; + fAWdU[i] = fabsf(dir[i]); + if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; + } + + float f; + f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; + f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; + f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; + + return true; +} + + + +// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. +// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, +// and returns the intersection point along dir in intersection_t. + +// Moller-Trumbore algorithm +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ + + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); + + LLVector4a edge2; + edge2.setSub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + LLVector4a det; + det.setAllDot3(edge1, pvec); + + if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) + { + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); + + /* calculate U parameter and test bounds */ + LLVector4a u; + u.setAllDot3(tvec,pvec); + + if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && + (u.lessEqual(det).getGatheredBits() & 0x7)) + { + /* prepare to test V parameter */ + LLVector4a qvec; + qvec.setCross3(tvec, edge1); + + /* calculate V parameter and test bounds */ + LLVector4a v; + v.setAllDot3(dir, qvec); + + + //if (!(v < 0.f || u + v > det)) + + LLVector4a sum_uv; + sum_uv.setAdd(u, v); + + S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; + S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; + + if (v_gequal && sum_lequal) + { + /* calculate t, scale parameters, ray intersects triangle */ + LLVector4a t; + t.setAllDot3(edge2,qvec); + + t.div(det); + u.div(det); + v.div(det); + + intersection_a = u[0]; + intersection_b = v[0]; + intersection_t = t[0]; + return TRUE; + } + } + } + + return FALSE; +} + +BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ + F32 u, v, t; + + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); + + + LLVector4a edge2; + edge2.setSub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + F32 det = edge1.dot3(pvec).getF32(); + + + if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) + { + return FALSE; + } + + F32 inv_det = 1.f / det; + + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); + + /* calculate U parameter and test bounds */ + u = (tvec.dot3(pvec).getF32()) * inv_det; + if (u < 0.f || u > 1.f) + { + return FALSE; + } + + /* prepare to test V parameter */ + tvec.sub(edge1); + + /* calculate V parameter and test bounds */ + v = (dir.dot3(tvec).getF32()) * inv_det; + + if (v < 0.f || u + v > 1.f) + { + return FALSE; + } + + /* calculate t, ray intersects triangle */ + t = (edge2.dot3(tvec).getF32()) * inv_det; + + intersection_a = u; + intersection_b = v; + intersection_t = t; + + + return TRUE; +} + +//helper for non-aligned vectors +BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided) +{ + LLVector4a vert0a, vert1a, vert2a, origa, dira; + vert0a.load3(vert0.mV); + vert1a.load3(vert1.mV); + vert2a.load3(vert2.mV); + origa.load3(orig.mV); + dira.load3(dir.mV); + + if (two_sided) + { + return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } + else + { + return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } +} + +class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle> +{ +public: + const LLVolumeFace* mFace; + + LLVolumeOctreeRebound(const LLVolumeFace* face) + { + mFace = face; + } + + virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) + { //this is a depth first traversal, so it's safe to assum all children have complete + //bounding data + + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; + + if (!branch->getData().empty()) + { //node has data, find AABB that binds data set + const LLVolumeTriangle* tri = *(branch->getData().begin()); + + //initialize min/max to first available vertex + min = *(tri->mV[0]); + max = *(tri->mV[0]); + + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = + branch->getData().begin(); iter != branch->getData().end(); ++iter) + { //for each triangle in node + + //stretch by triangles in node + tri = *iter; + + min.setMin(min, *tri->mV[0]); + min.setMin(min, *tri->mV[1]); + min.setMin(min, *tri->mV[2]); + + max.setMax(max, *tri->mV[0]); + max.setMax(max, *tri->mV[1]); + max.setMax(max, *tri->mV[2]); + } + } + else if (!branch->getChildren().empty()) + { //no data, but child nodes exist + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); + + //initialize min/max to extents of first child + min = child->mExtents[0]; + max = child->mExtents[1]; + } + else + { + llerrs << "WTF? Empty leaf" << llendl; + } + + for (S32 i = 0; i < branch->getChildCount(); ++i) + { //stretch by child extents + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + min.setMin(min, child->mExtents[0]); + max.setMax(max, child->mExtents[1]); + } + + node->mBounds[0].setAdd(min, max); + node->mBounds[0].mul(0.5f); + + node->mBounds[1].setSub(max,min); + node->mBounds[1].mul(0.5f); + } +}; + +//------------------------------------------------------------------- +// statics +//------------------------------------------------------------------- + + +//---------------------------------------------------- + +LLProfile::Face* LLProfile::addCap(S16 faceID) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + Face *face = vector_append(mFaces, 1); + + face->mIndex = 0; + face->mCount = mTotal; + face->mScaleU= 1.0f; + face->mCap = TRUE; + face->mFaceID = faceID; + return face; +} + +LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BOOL flat) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + Face *face = vector_append(mFaces, 1); + + face->mIndex = i; + face->mCount = count; + face->mScaleU= scaleU; + + face->mFlat = flat; + face->mCap = FALSE; + face->mFaceID = faceID; + return face; +} + +// What is the bevel parameter used for? - DJS 04/05/02 +// Bevel parameter is currently unused but presumedly would support +// filleted and chamfered corners +void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + F32 scale = 0.5f; + F32 t, t_step, t_first, t_fraction, ang, ang_step; + LLVector3 pt1,pt2; + + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + + t_step = 1.0f / sides; + ang_step = 2.0f*F_PI*t_step*ang_scale; + + // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. + + S32 total_sides = llround(sides / ang_scale); // Total number of sides all around + + if (total_sides < 8) + { + scale = tableScale[total_sides]; + } + + t_first = floor(begin * sides) / (F32)sides; + + // pt1 is the first point on the fractional face. + // Starting t and ang values for the first face + t = t_first; + ang = 2.0f*F_PI*(t*ang_scale + offset); + pt1.setVec(cos(ang)*scale,sin(ang)*scale, t); + + // Increment to the next point. + // pt2 is the end point on the fractional face + t += t_step; + ang += ang_step; + pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); + + t_fraction = (begin - t_first)*sides; + + // Only use if it's not almost exactly on an edge. + if (t_fraction < 0.9999f) + { + LLVector3 new_pt = lerp(pt1, pt2, t_fraction); + mProfile.push_back(new_pt); + } + + // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 + while (t < end) + { + // Iterate through all the integer steps of t. + pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); + + if (mProfile.size() > 0) { + LLVector3 p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); + } + } + mProfile.push_back(pt1); + + t += t_step; + ang += ang_step; + } + + t_fraction = (end - (t - t_step))*sides; + + // pt1 is the first point on the fractional face + // pt2 is the end point on the fractional face + pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); + + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + LLVector3 new_pt = lerp(pt1, pt2, t_fraction); + + if (mProfile.size() > 0) { + LLVector3 p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); + } + } + mProfile.push_back(new_pt); + } + + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if ((end - begin)*ang_scale > 0.5f) + { + mConcave = TRUE; + } + else + { + mConcave = FALSE; + } + mOpen = TRUE; + if (params.getHollow() <= 0) + { + // put center point if not hollow. + mProfile.push_back(LLVector3(0,0,0)); + } + } + else + { + // The profile isn't open. + mOpen = FALSE; + mConcave = FALSE; + } + + mTotal = mProfile.size(); +} + +void LLProfile::genNormals(const LLProfileParams& params) +{ + S32 count = mProfile.size(); + + S32 outer_count; + if (mTotalOut) + { + outer_count = mTotalOut; + } + else + { + outer_count = mTotal / 2; + } + + mEdgeNormals.resize(count * 2); + mEdgeCenters.resize(count * 2); + mNormals.resize(count); + + LLVector2 pt0,pt1; + + BOOL hollow = (params.getHollow() > 0); + + S32 i0, i1, i2, i3, i4; + + // Parametrically generate normal + for (i2 = 0; i2 < count; i2++) + { + mNormals[i2].mV[0] = mProfile[i2].mV[0]; + mNormals[i2].mV[1] = mProfile[i2].mV[1]; + if (hollow && (i2 >= outer_count)) + { + mNormals[i2] *= -1.f; + } + if (mNormals[i2].magVec() < 0.001) + { + // Special case for point at center, get adjacent points. + i1 = (i2 - 1) >= 0 ? i2 - 1 : count - 1; + i0 = (i1 - 1) >= 0 ? i1 - 1 : count - 1; + i3 = (i2 + 1) < count ? i2 + 1 : 0; + i4 = (i3 + 1) < count ? i3 + 1 : 0; + + pt0.setVec(mProfile[i1].mV[VX] + mProfile[i1].mV[VX] - mProfile[i0].mV[VX], + mProfile[i1].mV[VY] + mProfile[i1].mV[VY] - mProfile[i0].mV[VY]); + pt1.setVec(mProfile[i3].mV[VX] + mProfile[i3].mV[VX] - mProfile[i4].mV[VX], + mProfile[i3].mV[VY] + mProfile[i3].mV[VY] - mProfile[i4].mV[VY]); + + mNormals[i2] = pt0 + pt1; + mNormals[i2] *= 0.5f; + } + mNormals[i2].normVec(); + } + + S32 num_normal_sets = isConcave() ? 2 : 1; + for (S32 normal_set = 0; normal_set < num_normal_sets; normal_set++) + { + S32 point_num; + for (point_num = 0; point_num < mTotal; point_num++) + { + LLVector3 point_1 = mProfile[point_num]; + point_1.mV[VZ] = 0.f; + + LLVector3 point_2; + + if (isConcave() && normal_set == 0 && point_num == (mTotal - 1) / 2) + { + point_2 = mProfile[mTotal - 1]; + } + else if (isConcave() && normal_set == 1 && point_num == mTotal - 1) + { + point_2 = mProfile[(mTotal - 1) / 2]; + } + else + { + LLVector3 delta_pos; + S32 neighbor_point = (point_num + 1) % mTotal; + while(delta_pos.magVecSquared() < 0.01f * 0.01f) + { + point_2 = mProfile[neighbor_point]; + delta_pos = point_2 - point_1; + neighbor_point = (neighbor_point + 1) % mTotal; + if (neighbor_point == point_num) + { + break; + } + } + } + + point_2.mV[VZ] = 0.f; + LLVector3 face_normal = (point_2 - point_1) % LLVector3::z_axis; + face_normal.normVec(); + mEdgeNormals[normal_set * count + point_num] = face_normal; + mEdgeCenters[normal_set * count + point_num] = lerp(point_1, point_2, 0.5f); + } + } +} + + +// Hollow is percent of the original bounding box, not of this particular +// profile's geometry. Thus, a swept triangle needs lower hollow values than +// a swept square. +LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split) +{ + // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. + + // Total add has number of vertices on outside. + mTotalOut = mTotal; + + // Why is the "bevel" parameter -1? DJS 04/05/02 + genNGon(params, llfloor(sides),offset,-1, ang_scale, split); + + Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); + + std::vector<LLVector3> pt; + pt.resize(mTotal) ; + + for (S32 i=mTotalOut;i<mTotal;i++) + { + pt[i] = mProfile[i] * box_hollow; + } + + S32 j=mTotal-1; + for (S32 i=mTotalOut;i<mTotal;i++) + { + mProfile[i] = pt[j--]; + } + + for (S32 i=0;i<(S32)mFaces.size();i++) + { + if (mFaces[i].mCap) + { + mFaces[i].mCount *= 2; + } + } + + return face; +} + + + +BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if ((!mDirty) && (!is_sculpted)) + { + return FALSE; + } + mDirty = FALSE; + + if (detail < MIN_LOD) + { + llinfos << "Generating profile with LOD < MIN_LOD. CLAMPING" << llendl; + detail = MIN_LOD; + } + + mProfile.clear(); + mFaces.clear(); + + // Generate the face data + S32 i; + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + F32 hollow = params.getHollow(); + + // Quick validation to eliminate some server crashes. + if (begin > end - 0.01f) + { + llwarns << "LLProfile::generate() assertion failed (begin >= end)" << llendl; + return FALSE; + } + + S32 face_num = 0; + + switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_SQUARE: + { + genNGon(params, 4,-0.375, 0, 1, split); + if (path_open) + { + addCap (LL_FACE_PATH_BEGIN); + } + + for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); + } + + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 4 to generate proper tex coords. + mProfile[i].mV[2] *= 4.f; + } + + if (hollow) + { + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_TRIANGLE: + // This offset is not correct, but we can't change it now... DK 11/17/04 + addHole(params, TRUE, 3, -0.375f, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + // TODO: Compute actual detail levels for cubes + addHole(params, FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_SQUARE: + default: + addHole(params, TRUE, 4, -0.375f, hollow, 1.f, split); + break; + } + } + + if (path_open) { + mFaces[0].mCount = mTotal; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + case LL_PCODE_PROFILE_EQUALTRI: + { + genNGon(params, 3,0, 0, 1, split); + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 3 to generate proper tex coords. + mProfile[i].mV[2] *= 3.f; + } + + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } + + for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); + } + if (hollow) + { + // Swept triangles need smaller hollowness values, + // because the triangle doesn't fill the bounding box. + F32 triangle_hollow = hollow / 2.f; + + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_CIRCLE: + // TODO: Actually generate level of detail for triangles + addHole(params, FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); + break; + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 4, 0, triangle_hollow, 1.f, split); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_TRIANGLE: + default: + addHole(params, TRUE, 3, 0, triangle_hollow, 1.f, split); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + F32 circle_detail = MIN_DETAIL_FACES * detail; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides, + // so that corners line up. + circle_detail = llceil(circle_detail / 4.0f) * 4.0f; + } + } + + S32 sides = (S32)circle_detail; + + if (is_sculpted) + sides = sculpt_size; + + genNGon(params, sides); + + if (path_open) + { + addCap (LL_FACE_PATH_BEGIN); + } + + if (mOpen && !hollow) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 4, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, TRUE, 3, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, FALSE, circle_detail, 0, hollow, 1.f); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE_HALF: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + // Number of faces is cut in half because it's only a half-circle. + F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides (div 2), + // so that corners line up. + circle_detail = llceil(circle_detail / 2.0f) * 2.0f; + } + } + genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } + if (mOpen && !params.getHollow()) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 2, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, TRUE, 3, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, FALSE, circle_detail, 0.5f, hollow, 0.5f); + break; + } + } + + // Special case for openness of sphere + if ((params.getEnd() - params.getBegin()) < 1.f) + { + mOpen = TRUE; + } + else if (!hollow) + { + mOpen = FALSE; + mProfile.push_back(mProfile[0]); + mTotal++; + } + } + break; + default: + llerrs << "Unknown profile: getCurveType()=" << params.getCurveType() << llendl; + break; + }; + + if (path_open) + { + addCap(LL_FACE_PATH_END); // bottom + } + + if ( mOpen) // interior edge caps + { + addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, TRUE); + + if (hollow) + { + addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, TRUE); + } + else + { + addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE); + } + } + + //genNormals(params); + + return TRUE; +} + + + +BOOL LLProfileParams::importFile(LLFILE *fp) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + llwarns << "unknown keyword " << keyword << " in profile import" << llendl; + } + } + + return TRUE; +} + + +BOOL LLProfileParams::exportFile(LLFILE *fp) const +{ + fprintf(fp,"\t\tprofile 0\n"); + fprintf(fp,"\t\t{\n"); + fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp,"\t\t\tend\t%g\n", getEnd()); + fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); + fprintf(fp, "\t\t}\n"); + return TRUE; +} + + +BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, + valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + llwarns << "unknown keyword " << keyword << " in profile import" << llendl; + } + } + + return TRUE; +} + + +BOOL LLProfileParams::exportLegacyStream(std::ostream& output_stream) const +{ + output_stream <<"\t\tprofile 0\n"; + output_stream <<"\t\t{\n"; + output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; + output_stream <<"\t\t\tend\t" << getEnd() << "\n"; + output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; + output_stream << "\t\t}\n"; + return TRUE; +} + +LLSD LLProfileParams::asLLSD() const +{ + LLSD sd; + + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["hollow"] = getHollow(); + return sd; +} + +bool LLProfileParams::fromLLSD(LLSD& sd) +{ + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setHollow((F32)sd["hollow"].asReal()); + return true; +} + +void LLProfileParams::copyParams(const LLProfileParams ¶ms) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setHollow(params.getHollow()); +} + + +LLPath::~LLPath() +{ +} + +void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) +{ + // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. + const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + + F32 revolutions = params.getRevolutions(); + F32 skew = params.getSkew(); + F32 skew_mag = fabs(skew); + F32 hole_x = params.getScaleX() * (1.0f - skew_mag); + F32 hole_y = params.getScaleY(); + + // Calculate taper begin/end for x,y (Negative means taper the beginning) + F32 taper_x_begin = 1.0f; + F32 taper_x_end = 1.0f - params.getTaperX(); + F32 taper_y_begin = 1.0f; + F32 taper_y_end = 1.0f - params.getTaperY(); + + if ( taper_x_end > 1.0f ) + { + // Flip tapering. + taper_x_begin = 2.0f - taper_x_end; + taper_x_end = 1.0f; + } + if ( taper_y_end > 1.0f ) + { + // Flip tapering. + taper_y_begin = 2.0f - taper_y_end; + taper_y_end = 1.0f; + } + + // For spheres, the radius is usually zero. + F32 radius_start = 0.5f; + if (sides < 8) + { + radius_start = tableScale[sides]; + } + + // Scale the radius to take the hole size into account. + radius_start *= 1.0f - hole_y; + + // Now check the radius offset to calculate the start,end radius. (Negative means + // decrease the start radius instead). + F32 radius_end = radius_start; + F32 radius_offset = params.getRadiusOffset(); + if (radius_offset < 0.f) + { + radius_start *= 1.f + radius_offset; + } + else + { + radius_end *= 1.f - radius_offset; + } + + // Is the path NOT a closed loop? + mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || + (skew_mag > 0.001f) || + (fabs(taper_x_end - taper_x_begin) > 0.001f) || + (fabs(taper_y_end - taper_y_begin) > 0.001f) || + (fabs(radius_end - radius_start) > 0.001f) ); + + F32 ang, c, s; + LLQuaternion twist, qang; + PathPt *pt; + LLVector3 path_axis (1.f, 0.f, 0.f); + //LLVector3 twist_axis(0.f, 0.f, 1.f); + F32 twist_begin = params.getTwistBegin() * twist_scale; + F32 twist_end = params.getTwist() * twist_scale; + + // We run through this once before the main loop, to make sure + // the path begins at the correct cut. + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + pt = vector_append(mPath, 1); + ang = 2.0f*F_PI*revolutions * t; + s = sin(ang)*lerp(radius_start, radius_end, t); + c = cos(ang)*lerp(radius_start, radius_end, t); + + + pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); + pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + pt->mRot = twist * qang; + + t+=step; + + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; + + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + pt = vector_append(mPath, 1); + + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); + + pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + + pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); + pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + pt->mRot = twist * qang; + + t+=step; + } + + // Make one final pass for the end cut. + t = params.getEnd(); + pt = vector_append(mPath, 1); + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); + + pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); + pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + pt->mRot = twist * qang; + + mTotal = mPath.size(); +} + +const LLVector2 LLPathParams::getBeginScale() const +{ + LLVector2 begin_scale(1.f, 1.f); + if (getScaleX() > 1) + { + begin_scale.mV[0] = 2-getScaleX(); + } + if (getScaleY() > 1) + { + begin_scale.mV[1] = 2-getScaleY(); + } + return begin_scale; +} + +const LLVector2 LLPathParams::getEndScale() const +{ + LLVector2 end_scale(1.f, 1.f); + if (getScaleX() < 1) + { + end_scale.mV[0] = getScaleX(); + } + if (getScaleY() < 1) + { + end_scale.mV[1] = getScaleY(); + } + return end_scale; +} + +BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if ((!mDirty) && (!is_sculpted)) + { + return FALSE; + } + + if (detail < MIN_LOD) + { + llinfos << "Generating path with LOD < MIN! Clamping to 1" << llendl; + detail = MIN_LOD; + } + + mDirty = FALSE; + S32 np = 2; // hardcode for line + + mPath.clear(); + mOpen = TRUE; + + // Is this 0xf0 mask really necessary? DK 03/02/05 + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + if (np < split+2) + { + np = split+2; + } + + mStep = 1.0f / (np-1); + + mPath.resize(np); + + LLVector2 start_scale = params.getBeginScale(); + LLVector2 end_scale = params.getEndScale(); + + for (S32 i=0;i<np;i++) + { + F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); + mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t), + lerp(0,params.getShear().mV[1],t), + t - 0.5f); + mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); + mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t); + mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t); + mPath[i].mTexT = t; + } + } + break; + + case LL_PCODE_PATH_CIRCLE: + { + // Increase the detail as the revolutions and twist increase. + F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); + + S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); + + if (is_sculpted) + sides = sculpt_size; + + genNGon(params, sides); + } + break; + + case LL_PCODE_PATH_CIRCLE2: + { + if (params.getEnd() - params.getBegin() >= 0.99f && + params.getScaleX() >= .99f) + { + mOpen = FALSE; + } + + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); + + F32 t = 0.f; + F32 tStep = 1.0f / mPath.size(); + + F32 toggle = 0.5f; + for (S32 i=0;i<(S32)mPath.size();i++) + { + mPath[i].mPos.mV[0] = toggle; + if (toggle == 0.5f) + toggle = -0.5f; + else + toggle = 0.5f; + t += tStep; + } + } + + break; + + case LL_PCODE_PATH_TEST: + + np = 5; + mStep = 1.0f / (np-1); + + mPath.resize(np); + + for (S32 i=0;i<np;i++) + { + F32 t = (F32)i * mStep; + mPath[i].mPos.setVec(0, + lerp(0, -sin(F_PI*params.getTwist()*t)*0.5f,t), + lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t)); + mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t); + mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t); + mPath[i].mTexT = t; + mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0); + } + + break; + }; + + if (params.getTwist() != params.getTwistBegin()) mOpen = TRUE; + + //if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) { + // mOpen = TRUE; + //} + + return TRUE; +} + +BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + mOpen = TRUE; // Draw end caps + if (getPathLength() == 0) + { + // Path hasn't been generated yet. + // Some algorithms later assume at least TWO path points. + resizePath(2); + for (U32 i = 0; i < 2; i++) + { + mPath[i].mPos.setVec(0, 0, 0); + mPath[i].mRot.setQuat(0, 0, 0); + mPath[i].mScale.setVec(1, 1); + mPath[i].mTexT = 0; + } + } + + return TRUE; +} + + +BOOL LLPathParams::importFile(LLFILE *fp) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + llwarns << "unknown keyword " << " in path import" << llendl; + } + } + return TRUE; +} + + +BOOL LLPathParams::exportFile(LLFILE *fp) const +{ + fprintf(fp, "\t\tpath 0\n"); + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp, "\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp, "\t\t\tend\t%g\n", getEnd()); + fprintf(fp, "\t\t\tscale_x\t%g\n", getScaleX() ); + fprintf(fp, "\t\t\tscale_y\t%g\n", getScaleY() ); + fprintf(fp, "\t\t\tshear_x\t%g\n", getShearX() ); + fprintf(fp, "\t\t\tshear_y\t%g\n", getShearY() ); + fprintf(fp,"\t\t\ttwist\t%g\n", getTwist()); + + fprintf(fp,"\t\t\ttwist_begin\t%g\n", getTwistBegin()); + fprintf(fp,"\t\t\tradius_offset\t%g\n", getRadiusOffset()); + fprintf(fp,"\t\t\ttaper_x\t%g\n", getTaperX()); + fprintf(fp,"\t\t\ttaper_y\t%g\n", getTaperY()); + fprintf(fp,"\t\t\trevolutions\t%g\n", getRevolutions()); + fprintf(fp,"\t\t\tskew\t%g\n", getSkew()); + + fprintf(fp, "\t\t}\n"); + return TRUE; +} + + +BOOL LLPathParams::importLegacyStream(std::istream& input_stream) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + llwarns << "unknown keyword " << " in path import" << llendl; + } + } + return TRUE; +} + + +BOOL LLPathParams::exportLegacyStream(std::ostream& output_stream) const +{ + output_stream << "\t\tpath 0\n"; + output_stream << "\t\t{\n"; + output_stream << "\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream << "\t\t\tbegin\t" << getBegin() << "\n"; + output_stream << "\t\t\tend\t" << getEnd() << "\n"; + output_stream << "\t\t\tscale_x\t" << getScaleX() << "\n"; + output_stream << "\t\t\tscale_y\t" << getScaleY() << "\n"; + output_stream << "\t\t\tshear_x\t" << getShearX() << "\n"; + output_stream << "\t\t\tshear_y\t" << getShearY() << "\n"; + output_stream <<"\t\t\ttwist\t" << getTwist() << "\n"; + + output_stream <<"\t\t\ttwist_begin\t" << getTwistBegin() << "\n"; + output_stream <<"\t\t\tradius_offset\t" << getRadiusOffset() << "\n"; + output_stream <<"\t\t\ttaper_x\t" << getTaperX() << "\n"; + output_stream <<"\t\t\ttaper_y\t" << getTaperY() << "\n"; + output_stream <<"\t\t\trevolutions\t" << getRevolutions() << "\n"; + output_stream <<"\t\t\tskew\t" << getSkew() << "\n"; + + output_stream << "\t\t}\n"; + return TRUE; +} + +LLSD LLPathParams::asLLSD() const +{ + LLSD sd = LLSD(); + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["scale_x"] = getScaleX(); + sd["scale_y"] = getScaleY(); + sd["shear_x"] = getShearX(); + sd["shear_y"] = getShearY(); + sd["twist"] = getTwist(); + sd["twist_begin"] = getTwistBegin(); + sd["radius_offset"] = getRadiusOffset(); + sd["taper_x"] = getTaperX(); + sd["taper_y"] = getTaperY(); + sd["revolutions"] = getRevolutions(); + sd["skew"] = getSkew(); + + return sd; +} + +bool LLPathParams::fromLLSD(LLSD& sd) +{ + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setScaleX((F32)sd["scale_x"].asReal()); + setScaleY((F32)sd["scale_y"].asReal()); + setShearX((F32)sd["shear_x"].asReal()); + setShearY((F32)sd["shear_y"].asReal()); + setTwist((F32)sd["twist"].asReal()); + setTwistBegin((F32)sd["twist_begin"].asReal()); + setRadiusOffset((F32)sd["radius_offset"].asReal()); + setTaperX((F32)sd["taper_x"].asReal()); + setTaperY((F32)sd["taper_y"].asReal()); + setRevolutions((F32)sd["revolutions"].asReal()); + setSkew((F32)sd["skew"].asReal()); + return true; +} + +void LLPathParams::copyParams(const LLPathParams ¶ms) +{ + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setScale(params.getScaleX(), params.getScaleY() ); + setShear(params.getShearX(), params.getShearY() ); + setTwist(params.getTwist()); + setTwistBegin(params.getTwistBegin()); + setRadiusOffset(params.getRadiusOffset()); + setTaper( params.getTaperX(), params.getTaperY() ); + setRevolutions(params.getRevolutions()); + setSkew(params.getSkew()); +} + +S32 profile_delete_lock = 1 ; +LLProfile::~LLProfile() +{ + if(profile_delete_lock) + { + llerrs << "LLProfile should not be deleted here!" << llendl ; + } +} + + +S32 LLVolume::sNumMeshPoints = 0; + +LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) + : mParams(params) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + mUnique = is_unique; + mFaceMask = 0x0; + mDetail = detail; + mSculptLevel = -2; + mIsTetrahedron = FALSE; + mLODScaleBias.setVec(1,1,1); + mHullPoints = NULL; + mHullIndices = NULL; + mNumHullPoints = 0; + mNumHullIndices = 0; + + // set defaults + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) + { + mPathp = new LLDynamicPath(); + } + else + { + mPathp = new LLPath(); + } + mProfilep = new LLProfile(); + + mGenerateSingleFace = generate_single_face; + + generate(); + + if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) + { + createVolumeFaces(); + } +} + +void LLVolume::resizePath(S32 length) +{ + mPathp->resizePath(length); + mVolumeFaces.clear(); +} + +void LLVolume::regen() +{ + generate(); + createVolumeFaces(); +} + +void LLVolume::genBinormals(S32 face) +{ + mVolumeFaces[face].createBinormals(); +} + +LLVolume::~LLVolume() +{ + sNumMeshPoints -= mMesh.size(); + delete mPathp; + + profile_delete_lock = 0 ; + delete mProfilep; + profile_delete_lock = 1 ; + + mPathp = NULL; + mProfilep = NULL; + mVolumeFaces.clear(); + + free(mHullPoints); + mHullPoints = NULL; + free(mHullIndices); + mHullIndices = NULL; +} + +BOOL LLVolume::generate() +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + llassert_always(mProfilep); + + //Added 10.03.05 Dave Parks + // Split is a parameter to LLProfile::generate that tesselates edges on the profile + // to prevent lighting and texture interpolation errors on triangles that are + // stretched due to twisting or scaling on the path. + S32 split = (S32) ((mDetail)*0.66f); + + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && + (mParams.getPathParams().getScale().mV[0] != 1.0f || + mParams.getPathParams().getScale().mV[1] != 1.0f) && + (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) + { + split = 0; + } + + mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); + + F32 profile_detail = mDetail; + F32 path_detail = mDetail; + + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } + + //******************************************************************** + //debug info, to be removed + if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) + { + llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ; + llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; + llinfos << mParams << llendl ; + llinfos << "more info to check if mProfilep is deleted or not." << llendl ; + llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; + + llerrs << "LLVolume corrupted!" << llendl ; + } + //******************************************************************** + + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); + BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); + + if (regenPath || regenProf ) + { + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + //******************************************************************** + //debug info, to be removed + if((U32)(sizeS * sizeT) > (1u << 20)) + { + llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ; + llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ; + llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; + llinfos << mParams << llendl ; + llinfos << "more info to check if mProfilep is deleted or not." << llendl ; + llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; + + llerrs << "LLVolume corrupted!" << llendl ; + } + //******************************************************************** + + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeT * sizeS); + sNumMeshPoints += mMesh.size(); + + //generate vertex positions + + // Run along the path. + for (S32 s = 0; s < sizeS; ++s) + { + LLVector2 scale = mPathp->mPath[s].mScale; + LLQuaternion rot = mPathp->mPath[s].mRot; + + // Run along the profile. + for (S32 t = 0; t < sizeT; ++t) + { + S32 m = s*sizeT + t; + Point& pt = mMesh[m]; + + pt.mPos.mV[0] = mProfilep->mProfile[t].mV[0] * scale.mV[0]; + pt.mPos.mV[1] = mProfilep->mProfile[t].mV[1] * scale.mV[1]; + pt.mPos.mV[2] = 0.0f; + pt.mPos = pt.mPos * rot; + pt.mPos += mPathp->mPath[s].mPos; + } + } + + for (std::vector<LLProfile::Face>::iterator iter = mProfilep->mFaces.begin(); + iter != mProfilep->mFaces.end(); ++iter) + { + LLFaceID id = iter->mFaceID; + mFaceMask |= id; + } + + return TRUE; + } + return FALSE; +} + +void LLVolumeFace::VertexData::init() +{ + if (!mData) + { + mData = (LLVector4a*) malloc(sizeof(LLVector4a)*2); + } +} + +LLVolumeFace::VertexData::VertexData() +{ + mData = NULL; + init(); +} + +LLVolumeFace::VertexData::VertexData(const VertexData& rhs) +{ + mData = NULL; + *this = rhs; +} + +const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) +{ + if (this != &rhs) + { + init(); + LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); + mTexCoord = rhs.mTexCoord; + } + return *this; +} + +LLVolumeFace::VertexData::~VertexData() +{ + free(mData); + mData = NULL; +} + +LLVector4a& LLVolumeFace::VertexData::getPosition() +{ + return mData[POSITION]; +} + +LLVector4a& LLVolumeFace::VertexData::getNormal() +{ + return mData[NORMAL]; +} + +const LLVector4a& LLVolumeFace::VertexData::getPosition() const +{ + return mData[POSITION]; +} + +const LLVector4a& LLVolumeFace::VertexData::getNormal() const +{ + return mData[NORMAL]; +} + + +void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) +{ + mData[POSITION] = pos; +} + +void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) +{ + mData[NORMAL] = norm; +} + +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +{ + const F32* lp = this->getPosition().getF32ptr(); + const F32* rp = rhs.getPosition().getF32ptr(); + + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } + + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } + + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } + + lp = getNormal().getF32ptr(); + rp = rhs.getNormal().getF32ptr(); + + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } + + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } + + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } + + if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) + { + return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; + } + + return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; +} + +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +{ + return mData[POSITION].equals3(rhs.getPosition()) && + mData[NORMAL].equals3(rhs.getNormal()) && + mTexCoord == rhs.mTexCoord; +} + +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +{ + bool retval = false; + if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) + { + if (angle_cutoff > 1.f) + { + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL])); + } + else + { + F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); + retval = cur_angle > angle_cutoff; + } + } + + return retval; +} + +bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +{ + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + if (!unzip_llsd(mdl, is, size)) + { + llwarns << "not a valid mesh asset!" << llendl; + return false; + } + + { + U32 face_count = mdl.size(); + + if (face_count == 0) + { + llerrs << "WTF?" << llendl; + } + + mVolumeFaces.resize(face_count); + + for (U32 i = 0; i < face_count; ++i) + { + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; + + LLVolumeFace& face = mVolumeFaces[i]; + + //copy out indices + face.resizeIndices(idx.size()/2); + + if (idx.empty() || face.mNumIndices < 3) + { //why is there an empty index list? + llerrs <<"WTF?" << llendl; + continue; + } + + U16* indices = (U16*) &(idx[0]); + for (U32 j = 0; j < idx.size()/2; ++j) + { + face.mIndices[j] = indices[j]; + } + + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.resizeVertices(num_verts); + + if (mdl[i].has("Weights")) + { + face.allocateWeights(num_verts); + + LLSD::Binary weights = mdl[i]["Weights"]; + + U32 idx = 0; + + U32 cur_vertex = 0; + while (idx < weights.size() && cur_vertex < num_verts) + { + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; + + U32 cur_influence = 0; + LLVector4 wght(0,0,0,0); + + while (joint != END_INFLUENCES && idx < weights.size()) + { + U16 influence = weights[idx++]; + influence |= ((U16) weights[idx++] << 8); + + F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); + wght.mV[cur_influence++] = (F32) joint + w; + + if (cur_influence >= 4) + { + joint = END_INFLUENCES; + } + else + { + joint = weights[idx++]; + } + } + + face.mWeights[cur_vertex].loadua(wght.mV); + + cur_vertex++; + } + + if (cur_vertex != num_verts || idx != weights.size()) + { + llwarns << "Vertex weight count does not match vertex count!" << llendl; + } + + } + + LLVector3 minp; + LLVector3 maxp; + LLVector2 min_tc; + LLVector2 max_tc; + + minp.setValue(mdl[i]["PositionDomain"]["Min"]); + maxp.setValue(mdl[i]["PositionDomain"]["Max"]); + LLVector4a min_pos, max_pos; + min_pos.load3(minp.mV); + max_pos.load3(maxp.mV); + + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + + LLVector4a pos_range; + pos_range.setSub(max_pos, min_pos); + LLVector2 tc_range = max_tc - min_tc; + + LLVector4a* pos_out = face.mPositions; + LLVector4a* norm_out = face.mNormals; + LLVector2* tc_out = face.mTexCoords; + + for (U32 j = 0; j < num_verts; ++j) + { + U16* v = (U16*) &(pos[j*3*2]); + + pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); + pos_out->div(65535.f); + pos_out->mul(pos_range); + pos_out->add(min_pos); + + pos_out++; + + U16* n = (U16*) &(norm[j*3*2]); + + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + + U16* t = (U16*) &(tc[j*2*2]); + + tc_out->mV[0] = (F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0]; + tc_out->mV[1] = (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]; + + tc_out++; + } + + + // modifier flags? + bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + + + // translate to actions: + bool do_reflect_x = false; + bool do_reverse_triangles = false; + bool do_invert_normals = false; + + if (do_mirror) + { + do_reflect_x = true; + do_reverse_triangles = !do_reverse_triangles; + } + + if (do_invert) + { + do_invert_normals = true; + do_reverse_triangles = !do_reverse_triangles; + } + + // now do the work + + if (do_reflect_x) + { + LLVector4a* p = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + p[i].mul(-1.0f); + n[i].mul(-1.0f); + } + } + + if (do_invert_normals) + { + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + n[i].mul(-1.0f); + } + } + + if (do_reverse_triangles) + { + for (U32 j = 0; j < face.mNumIndices; j += 3) + { + // swap the 2nd and 3rd index + S32 swap = face.mIndices[j+1]; + face.mIndices[j+1] = face.mIndices[j+2]; + face.mIndices[j+2] = swap; + } + } + + //calculate bounding box + LLVector4a& min = face.mExtents[0]; + LLVector4a& max = face.mExtents[1]; + + min.clear(); + max.clear(); + min = max = face.mPositions[0]; + + for (S32 i = 1; i < face.mNumVertices; ++i) + { + min.setMin(min, face.mPositions[i]); + max.setMax(max, face.mPositions[i]); + } + } + } + + mSculptLevel = 0; // success! + + cacheOptimize(); + + return true; +} + +void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) +{ + LLVector4a v0; + v0.setSub(cv[1].getPosition(), cv[0].getNormal()); + LLVector4a v1; + v1.setSub(cv[2].getNormal(), cv[0].getPosition()); + + cv[0].getNormal().setCross3(v0,v1); + cv[0].getNormal().normalize3fast(); + cv[1].setNormal(cv[0].getNormal()); + cv[2].setNormal(cv[1].getNormal()); +} + +BOOL LLVolume::isTetrahedron() +{ + return mIsTetrahedron; +} + +void LLVolume::makeTetrahedron() +{ + mVolumeFaces.clear(); + + LLVolumeFace face; + + F32 x = 0.25f; + LLVector4a p[] = + { //unit tetrahedron corners + LLVector4a(x,x,x), + LLVector4a(-x,-x,x), + LLVector4a(-x,x,-x), + LLVector4a(x,-x,-x) + }; + + face.mExtents[0].splat(-x); + face.mExtents[1].splat(x); + + LLVolumeFace::VertexData cv[3]; + + //set texture coordinates + cv[0].mTexCoord = LLVector2(0,0); + cv[1].mTexCoord = LLVector2(1,0); + cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3); + + + //side 1 + cv[0].setPosition(p[1]); + cv[1].setPosition(p[0]); + cv[2].setPosition(p[2]); + + tetrahedron_set_normal(cv); + + face.resizeVertices(12); + face.resizeIndices(12); + + LLVector4a* v = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + LLVector2* tc = (LLVector2*) face.mTexCoords; + + v[0] = cv[0].getPosition(); + v[1] = cv[1].getPosition(); + v[2] = cv[2].getPosition(); + v += 3; + + n[0] = cv[0].getNormal(); + n[1] = cv[1].getNormal(); + n[2] = cv[2].getNormal(); + n += 3; + + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + + + //side 2 + cv[0].setPosition(p[3]); + cv[1].setPosition(p[0]); + cv[2].setPosition(p[1]); + + tetrahedron_set_normal(cv); + + v[0] = cv[0].getPosition(); + v[1] = cv[1].getPosition(); + v[2] = cv[2].getPosition(); + v += 3; + + n[0] = cv[0].getNormal(); + n[1] = cv[1].getNormal(); + n[2] = cv[2].getNormal(); + n += 3; + + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + + //side 3 + cv[0].setPosition(p[3]); + cv[1].setPosition(p[1]); + cv[2].setPosition(p[2]); + + tetrahedron_set_normal(cv); + + v[0] = cv[0].getPosition(); + v[1] = cv[1].getPosition(); + v[2] = cv[2].getPosition(); + v += 3; + + n[0] = cv[0].getNormal(); + n[1] = cv[1].getNormal(); + n[2] = cv[2].getNormal(); + n += 3; + + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + + //side 4 + cv[0].setPosition(p[2]); + cv[1].setPosition(p[0]); + cv[2].setPosition(p[3]); + + tetrahedron_set_normal(cv); + + v[0] = cv[0].getPosition(); + v[1] = cv[1].getPosition(); + v[2] = cv[2].getPosition(); + v += 3; + + n[0] = cv[0].getNormal(); + n[1] = cv[1].getNormal(); + n[2] = cv[2].getNormal(); + n += 3; + + tc[0] = cv[0].mTexCoord; + tc[1] = cv[1].mTexCoord; + tc[2] = cv[2].mTexCoord; + tc += 3; + + //set index buffer + for (U16 i = 0; i < 12; i++) + { + face.mIndices[i] = i; + } + + mVolumeFaces.push_back(face); + mSculptLevel = 0; + mIsTetrahedron = TRUE; +} + +void LLVolume::copyVolumeFaces(const LLVolume* volume) +{ + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; + mIsTetrahedron = FALSE; +} + +void LLVolume::cacheOptimize() +{ + for (S32 i = 0; i < mVolumeFaces.size(); ++i) + { + mVolumeFaces[i].cacheOptimize(); + } +} + + +S32 LLVolume::getNumFaces() const +{ + U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); + + if (sculpt_type == LL_SCULPT_TYPE_MESH) + { + return LL_SCULPT_MESH_MAX_FACES; + } + + return (S32)mProfilep->mFaces.size(); +} + + +void LLVolume::createVolumeFaces() +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if (mGenerateSingleFace) + { + // do nothing + } + else + { + S32 num_faces = getNumFaces(); + BOOL partial_build = TRUE; + if (num_faces != mVolumeFaces.size()) + { + partial_build = FALSE; + mVolumeFaces.resize(num_faces); + } + // Initialize volume faces with parameter data + for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) + { + LLVolumeFace& vf = mVolumeFaces[i]; + LLProfile::Face& face = mProfilep->mFaces[i]; + vf.mBeginS = face.mIndex; + vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + + vf.mBeginT = 0; + vf.mNumT= getPath().mPath.size(); + vf.mID = i; + + // Set the type mask bits correctly + if (mParams.getProfileParams().getHollow() > 0) + { + vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; + } + if (mProfilep->isOpen()) + { + vf.mTypeMask |= LLVolumeFace::OPEN_MASK; + } + if (face.mCap) + { + vf.mTypeMask |= LLVolumeFace::CAP_MASK; + if (face.mFaceID == LL_FACE_PATH_BEGIN) + { + vf.mTypeMask |= LLVolumeFace::TOP_MASK; + } + else + { + llassert(face.mFaceID == LL_FACE_PATH_END); + vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; + } + } + else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; + } + else + { + vf.mTypeMask |= LLVolumeFace::SIDE_MASK; + if (face.mFlat) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK; + } + if (face.mFaceID & LL_FACE_INNER_SIDE) + { + vf.mTypeMask |= LLVolumeFace::INNER_MASK; + if (face.mFlat && vf.mNumS > 2) + { //flat inner faces have to copy vert normals + vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + } + } + else + { + vf.mTypeMask |= LLVolumeFace::OUTER_MASK; + } + } + } + + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + (*iter).create(this, partial_build); + } + } +} + + +inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b) +{ + // maps RGB values to vector values [0..255] -> [-0.5..0.5] + LLVector3 value; + value.mV[VX] = r / 255.f - 0.5f; + value.mV[VY] = g / 255.f - 0.5f; + value.mV[VZ] = b / 255.f - 0.5f; + + return value; +} + +inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) +{ + U32 index = (x + y * sculpt_width) * sculpt_components; + return index; +} + + +inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) +{ + U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); + U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); + + return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); +} + + +inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data) +{ + LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); + + return v; +} + +inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +{ + U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); + + return sculpt_index_to_vector(index, sculpt_data); +} + +inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +{ + U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + + return sculpt_index_to_vector(index, sculpt_data); +} + + +F32 LLVolume::sculptGetSurfaceArea() +{ + // test to see if image has enough variation to create non-degenerate geometry + + F32 area = 0; + + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + for (S32 s = 0; s < sizeS-1; s++) + { + for (S32 t = 0; t < sizeT-1; t++) + { + // get four corners of quad + LLVector3 p1 = mMesh[(s )*sizeT + (t )].mPos; + LLVector3 p2 = mMesh[(s+1)*sizeT + (t )].mPos; + LLVector3 p3 = mMesh[(s )*sizeT + (t+1)].mPos; + LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos; + + // compute the area of the quad by taking the length of the cross product of the two triangles + LLVector3 cross1 = (p1 - p2) % (p1 - p3); + LLVector3 cross2 = (p4 - p2) % (p4 - p3); + area += (cross1.magVec() + cross2.magVec()) / 2.0; + } + } + + return area; +} + +// create placeholder shape +void LLVolume::sculptGeneratePlaceholder() +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; + + // for now, this is a sphere. + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + Point& pt = mMesh[i]; + + + F32 u = (F32)s/(sizeS-1); + F32 v = (F32)t/(sizeT-1); + + const F32 RADIUS = (F32) 0.3; + + pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); + pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); + pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS); + + } + line += sizeT; + } +} + +// create the vertices from the map +void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) +{ + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR + + + LLMemType m1(LLMemType::MTYPE_VOLUME); + + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; + for (S32 s = 0; s < sizeS; s++) + { + // Run along the profile. + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + Point& pt = mMesh[i]; + + S32 reversed_t = t; + + if (reverse_horizontal) + { + reversed_t = sizeT - t - 1; + } + + U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); + U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); + + + if (y == 0) // top row stitching + { + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } + + if (y == sculpt_height) // bottom row stitching + { + // wrap? + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + { + y = 0; + } + else + { + y = sculpt_height - 1; + } + + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } + + if (x == sculpt_width) // side stitching + { + // wrap? + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + { + x = 0; + } + + else + { + x = sculpt_width - 1; + } + } + + pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); + + if (sculpt_mirror) + { + pt.mPos.mV[VX] *= -1.f; + } + } + + line += sizeT; + } +} + + +const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square +const S32 SCULPT_REZ_2 = 8; +const S32 SCULPT_REZ_3 = 16; +const S32 SCULPT_REZ_4 = 32; + +S32 sculpt_sides(F32 detail) +{ + + // detail is usually one of: 1, 1.5, 2.5, 4.0. + + if (detail <= 1.0) + { + return SCULPT_REZ_1; + } + if (detail <= 2.0) + { + return SCULPT_REZ_2; + } + if (detail <= 3.0) + { + return SCULPT_REZ_3; + } + else + { + return SCULPT_REZ_4; + } +} + + + +// determine the number of vertices in both s and t direction for this sculpt +void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) +{ + // this code has the following properties: + // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map + // while still using all available verts + // 2) the mesh cannot have more verts than is allowed by LOD + // 3) the mesh cannot have more verts than is allowed by the map + + S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); + S32 max_vertices_map = width * height / 4; + + S32 vertices; + if (max_vertices_map > 0) + vertices = llmin(max_vertices_lod, max_vertices_map); + else + vertices = max_vertices_lod; + + + F32 ratio; + if ((width == 0) || (height == 0)) + ratio = 1.f; + else + ratio = (F32) width / (F32) height; + + + s = (S32)(F32) sqrt(((F32)vertices / ratio)); + + s = llmax(s, 4); // no degenerate sizes, please + t = vertices / s; + + t = llmax(t, 4); // no degenerate sizes, please + s = vertices / t; +} + +// sculpt replaces generate() for sculpted surfaces +void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + U8 sculpt_type = mParams.getSculptType(); + + BOOL data_is_empty = FALSE; + + if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) + { + sculpt_level = -1; + data_is_empty = TRUE; + } + + S32 requested_sizeS = 0; + S32 requested_sizeT = 0; + + sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); + + mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); + mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); + + S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got + S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got + + // weird crash bug - DEV-11158 - trying to collect more data: + if ((sizeS == 0) || (sizeT == 0)) + { + llwarns << "sculpt bad mesh size " << sizeS << " " << sizeT << llendl; + } + + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeS * sizeT); + sNumMeshPoints += mMesh.size(); + + //generate vertex positions + if (!data_is_empty) + { + sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); + + // don't test lowest LOD to support legacy content DEV-33670 + if (mDetail > SCULPT_MIN_AREA_DETAIL) + { + if (sculptGetSurfaceArea() < SCULPT_MIN_AREA) + { + data_is_empty = TRUE; + } + } + } + + if (data_is_empty) + { + sculptGeneratePlaceholder(); + } + + + + for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) + { + mFaceMask |= mProfilep->mFaces[i].mFaceID; + } + + mSculptLevel = sculpt_level; + + // Delete any existing faces so that they get regenerated + mVolumeFaces.clear(); + + createVolumeFaces(); +} + + + + +BOOL LLVolume::isCap(S32 face) +{ + return mProfilep->mFaces[face].mCap; +} + +BOOL LLVolume::isFlat(S32 face) +{ + return mProfilep->mFaces[face].mFlat; +} + + +bool LLVolumeParams::isSculpt() const +{ + return mSculptID.notNull(); +} + +bool LLVolumeParams::isMeshSculpt() const +{ + return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); +} + +bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const +{ + return ( (getPathParams() == params.getPathParams()) && + (getProfileParams() == params.getProfileParams()) && + (mSculptID == params.mSculptID) && + (mSculptType == params.mSculptType) ); +} + +bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const +{ + return ( (getPathParams() != params.getPathParams()) || + (getProfileParams() != params.getProfileParams()) || + (mSculptID != params.mSculptID) || + (mSculptType != params.mSculptType) ); +} + +bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const +{ + if( getPathParams() != params.getPathParams() ) + { + return getPathParams() < params.getPathParams(); + } + + if (getProfileParams() != params.getProfileParams()) + { + return getProfileParams() < params.getProfileParams(); + } + + if (mSculptID != params.mSculptID) + { + return mSculptID < params.mSculptID; + } + + return mSculptType < params.mSculptType; + + +} + +void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + mProfileParams.copyParams(params.mProfileParams); + mPathParams.copyParams(params.mPathParams); + mSculptID = params.getSculptID(); + mSculptType = params.getSculptType(); +} + +// Less restricitve approx 0 for volumes +const F32 APPROXIMATELY_ZERO = 0.001f; +bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO) +{ + return (f >= -tolerance) && (f <= tolerance); +} + +// return true if in range (or nearly so) +static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO) +{ + F32 min_delta = v - min; + if (min_delta < 0.f) + { + v = min; + if (!approx_zero(min_delta, tolerance)) + return false; + } + F32 max_delta = max - v; + if (max_delta < 0.f) + { + v = max; + if (!approx_zero(max_delta, tolerance)) + return false; + } + return true; +} + +bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e) +{ + bool valid = true; + + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + + F32 end = e; + if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + + // Now set them. + mProfileParams.setBegin(begin); + mProfileParams.setEnd(end); + + return valid; +} + +bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e) +{ + bool valid = true; + + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + + F32 end = e; + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + + // Now set them. + mPathParams.setBegin(begin); + mPathParams.setEnd(end); + + return valid; +} + +bool LLVolumeParams::setHollow(const F32 h) +{ + // Validate the hollow based on path and profile. + U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; + + F32 max_hollow = HOLLOW_MAX; + + // Only square holes have trouble. + if (LL_PCODE_HOLE_SQUARE == hole_type) + { + switch(profile) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + case LL_PCODE_PROFILE_EQUALTRI: + max_hollow = HOLLOW_MAX_SQUARE; + } + } + + F32 hollow = h; + bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); + mProfileParams.setHollow(hollow); + + return valid; +} + +bool LLVolumeParams::setTwistBegin(const F32 b) +{ + F32 twist_begin = b; + bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistBegin(twist_begin); + return valid; +} + +bool LLVolumeParams::setTwistEnd(const F32 e) +{ + F32 twist_end = e; + bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistEnd(twist_end); + return valid; +} + +bool LLVolumeParams::setRatio(const F32 x, const F32 y) +{ + F32 min_x = RATIO_MIN; + F32 max_x = RATIO_MAX; + F32 min_y = RATIO_MIN; + F32 max_y = RATIO_MAX; + // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PATH_CIRCLE == path_type && + LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) + { + // Holes are more restricted... + min_x = HOLE_X_MIN; + max_x = HOLE_X_MAX; + min_y = HOLE_Y_MIN; + max_y = HOLE_Y_MAX; + } + + F32 ratio_x = x; + bool valid = limit_range(ratio_x, min_x, max_x); + F32 ratio_y = y; + valid &= limit_range(ratio_y, min_y, max_y); + + mPathParams.setScale(ratio_x, ratio_y); + + return valid; +} + +bool LLVolumeParams::setShear(const F32 x, const F32 y) +{ + F32 shear_x = x; + bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); + F32 shear_y = y; + valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); + mPathParams.setShear(shear_x, shear_y); + return valid; +} + +bool LLVolumeParams::setTaperX(const F32 v) +{ + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperX(taper); + return valid; +} + +bool LLVolumeParams::setTaperY(const F32 v) +{ + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperY(taper); + return valid; +} + +bool LLVolumeParams::setRevolutions(const F32 r) +{ + F32 revolutions = r; + bool valid = limit_range(revolutions, REV_MIN, REV_MAX); + mPathParams.setRevolutions(revolutions); + return valid; +} + +bool LLVolumeParams::setRadiusOffset(const F32 offset) +{ + bool valid = true; + + // If this is a sphere, just set it to 0 and get out. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || + LL_PCODE_PATH_CIRCLE != path_type ) + { + mPathParams.setRadiusOffset(0.f); + return true; + } + + // Limit radius offset, based on taper and hole size y. + F32 radius_offset = offset; + F32 taper_y = getTaperY(); + F32 radius_mag = fabs(radius_offset); + F32 hole_y_mag = fabs(getRatioY()); + F32 taper_y_mag = fabs(taper_y); + // Check to see if the taper effects us. + if ( (radius_offset > 0.f && taper_y < 0.f) || + (radius_offset < 0.f && taper_y > 0.f) ) + { + // The taper does not help increase the radius offset range. + taper_y_mag = 0.f; + } + F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); + + // Enforce the maximum magnitude. + F32 delta = max_radius_mag - radius_mag; + if (delta < 0.f) + { + // Check radius offset sign. + if (radius_offset < 0.f) + { + radius_offset = -max_radius_mag; + } + else + { + radius_offset = max_radius_mag; + } + valid = approx_zero(delta, .1f); + } + + mPathParams.setRadiusOffset(radius_offset); + return valid; +} + +bool LLVolumeParams::setSkew(const F32 skew_value) +{ + bool valid = true; + + // Check the skew value against the revolutions. + F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); + F32 skew_mag = fabs(skew); + F32 revolutions = getRevolutions(); + F32 scale_x = getRatioX(); + F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); + // Discontinuity; A revolution of 1 allows skews below 0.5. + if ( fabs(revolutions - 1.0f) < 0.001) + min_skew_mag = 0.0f; + + // Clip skew. + F32 delta = skew_mag - min_skew_mag; + if (delta < 0.f) + { + // Check skew sign. + if (skew < 0.0f) + { + skew = -min_skew_mag; + } + else + { + skew = min_skew_mag; + } + valid = approx_zero(delta, .01f); + } + + mPathParams.setSkew(skew); + return valid; +} + +bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type) +{ + mSculptID = sculpt_id; + mSculptType = sculpt_type; + return true; +} + +bool LLVolumeParams::setType(U8 profile, U8 path) +{ + bool result = true; + // First, check profile and path for validity. + U8 profile_type = profile & LL_PCODE_PROFILE_MASK; + U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; + U8 path_type = path >> 4; + + if (profile_type > LL_PCODE_PROFILE_MAX) + { + // Bad profile. Make it square. + profile = LL_PCODE_PROFILE_SQUARE; + result = false; + llwarns << "LLVolumeParams::setType changing bad profile type (" << profile_type + << ") to be LL_PCODE_PROFILE_SQUARE" << llendl; + } + else if (hole_type > LL_PCODE_HOLE_MAX) + { + // Bad hole. Make it the same. + profile = profile_type; + result = false; + llwarns << "LLVolumeParams::setType changing bad hole type (" << hole_type + << ") to be LL_PCODE_HOLE_SAME" << llendl; + } + + if (path_type < LL_PCODE_PATH_MIN || + path_type > LL_PCODE_PATH_MAX) + { + // Bad path. Make it linear. + result = false; + llwarns << "LLVolumeParams::setType changing bad path (" << path + << ") to be LL_PCODE_PATH_LINE" << llendl; + path = LL_PCODE_PATH_LINE; + } + + mProfileParams.setCurveType(profile); + mPathParams.setCurveType(path); + return result; +} + +// static +bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, + U8 path_curve, F32 path_begin, F32 path_end, + F32 scx, F32 scy, F32 shx, F32 shy, + F32 twistend, F32 twistbegin, F32 radiusoffset, + F32 tx, F32 ty, F32 revolutions, F32 skew) +{ + LLVolumeParams test_params; + if (!test_params.setType (prof_curve, path_curve)) + { + return false; + } + if (!test_params.setBeginAndEndS (prof_begin, prof_end)) + { + return false; + } + if (!test_params.setBeginAndEndT (path_begin, path_end)) + { + return false; + } + if (!test_params.setHollow (hollow)) + { + return false; + } + if (!test_params.setTwistBegin (twistbegin)) + { + return false; + } + if (!test_params.setTwistEnd (twistend)) + { + return false; + } + if (!test_params.setRatio (scx, scy)) + { + return false; + } + if (!test_params.setShear (shx, shy)) + { + return false; + } + if (!test_params.setTaper (tx, ty)) + { + return false; + } + if (!test_params.setRevolutions (revolutions)) + { + return false; + } + if (!test_params.setRadiusOffset (radiusoffset)) + { + return false; + } + if (!test_params.setSkew (skew)) + { + return false; + } + return true; +} + +S32 *LLVolume::getTriangleIndices(U32 &num_indices) const +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + S32 expected_num_triangle_indices = getNumTriangleIndices(); + if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES) + { + // we don't allow LLVolumes with this many vertices + llwarns << "Couldn't allocate triangle indices" << llendl; + num_indices = 0; + return NULL; + } + + S32* index = new S32[expected_num_triangle_indices]; + S32 count = 0; + + // Let's do this totally diffently, as we don't care about faces... + // Counter-clockwise triangles are forward facing... + + BOOL open = getProfile().isOpen(); + BOOL hollow = (mParams.getProfileParams().getHollow() > 0); + BOOL path_open = getPath().isOpen(); + S32 size_s, size_s_out, size_t; + S32 s, t, i; + size_s = getProfile().getTotal(); + size_s_out = getProfile().getTotalOut(); + size_t = getPath().mPath.size(); + + // NOTE -- if the construction of the triangles below ever changes + // then getNumTriangleIndices() method may also have to be updated. + + if (open) /* Flawfinder: ignore */ + { + if (hollow) + { + // Open hollow -- much like the closed solid, except we + // we need to stitch up the gap between s=0 and s=size_s-1 + + for (t = 0; t < size_t - 1; t++) + { + // The outer face, first cut, and inner face + for (s = 0; s < size_s - 1; s++) + { + i = s + t*size_s; + index[count++] = i; // x,y + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s; // x,y+1 + + index[count++] = i + size_s; // x,y+1 + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s + 1; // x+1,y+1 + } + + // The other cut face + index[count++] = s + t*size_s; // x,y + index[count++] = 0 + t*size_s; // x+1,y + index[count++] = s + (t+1)*size_s; // x,y+1 + + index[count++] = s + (t+1)*size_s; // x,y+1 + index[count++] = 0 + t*size_s; // x+1,y + index[count++] = 0 + (t+1)*size_s; // x+1,y+1 + } + + // Do the top and bottom caps, if necessary + if (path_open) + { + // Top cap + S32 pt1 = 0; + S32 pt2 = size_s-1; + S32 i = (size_t - 1)*size_s; + + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = getProfile().mProfile[pt1]; + LLVector3 p2 = getProfile().mProfile[pt2]; + LLVector3 pa = getProfile().mProfile[pt1+1]; + LLVector3 pb = getProfile().mProfile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + index[count++] = pt1 + i; + index[count++] = pt1 + 1 + i; + index[count++] = pt2 + i; + pt1++; + } + else + { + index[count++] = pt1 + i; + index[count++] = pt2 - 1 + i; + index[count++] = pt2 + i; + pt2--; + } + } + + // Bottom cap + pt1 = 0; + pt2 = size_s-1; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = getProfile().mProfile[pt1]; + LLVector3 p2 = getProfile().mProfile[pt2]; + LLVector3 pa = getProfile().mProfile[pt1+1]; + LLVector3 pb = getProfile().mProfile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + index[count++] = pt1; + index[count++] = pt2; + index[count++] = pt1 + 1; + pt1++; + } + else + { + index[count++] = pt1; + index[count++] = pt2; + index[count++] = pt2 - 1; + pt2--; + } + } + } + } + else + { + // Open solid + + for (t = 0; t < size_t - 1; t++) + { + // Outer face + 1 cut face + for (s = 0; s < size_s - 1; s++) + { + i = s + t*size_s; + + index[count++] = i; // x,y + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s; // x,y+1 + + index[count++] = i + size_s; // x,y+1 + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s + 1; // x+1,y+1 + } + + // The other cut face + index[count++] = (size_s - 1) + (t*size_s); // x,y + index[count++] = 0 + t*size_s; // x+1,y + index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1 + + index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1 + index[count++] = 0 + (t*size_s); // x+1,y + index[count++] = 0 + (t+1)*size_s; // x+1,y+1 + } + + // Do the top and bottom caps, if necessary + if (path_open) + { + for (s = 0; s < size_s - 2; s++) + { + index[count++] = s+1; + index[count++] = s; + index[count++] = size_s - 1; + } + + // We've got a top cap + S32 offset = (size_t - 1)*size_s; + for (s = 0; s < size_s - 2; s++) + { + // Inverted ordering from bottom cap. + index[count++] = offset + size_s - 1; + index[count++] = offset + s; + index[count++] = offset + s + 1; + } + } + } + } + else if (hollow) + { + // Closed hollow + // Outer face + + for (t = 0; t < size_t - 1; t++) + { + for (s = 0; s < size_s_out - 1; s++) + { + i = s + t*size_s; + + index[count++] = i; // x,y + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s; // x,y+1 + + index[count++] = i + size_s; // x,y+1 + index[count++] = i + 1; // x+1,y + index[count++] = i + 1 + size_s; // x+1,y+1 + } + } + + // Inner face + // Invert facing from outer face + for (t = 0; t < size_t - 1; t++) + { + for (s = size_s_out; s < size_s - 1; s++) + { + i = s + t*size_s; + + index[count++] = i; // x,y + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s; // x,y+1 + + index[count++] = i + size_s; // x,y+1 + index[count++] = i + 1; // x+1,y + index[count++] = i + 1 + size_s; // x+1,y+1 + } + } + + // Do the top and bottom caps, if necessary + if (path_open) + { + // Top cap + S32 pt1 = 0; + S32 pt2 = size_s-1; + S32 i = (size_t - 1)*size_s; + + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = getProfile().mProfile[pt1]; + LLVector3 p2 = getProfile().mProfile[pt2]; + LLVector3 pa = getProfile().mProfile[pt1+1]; + LLVector3 pb = getProfile().mProfile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + index[count++] = pt1 + i; + index[count++] = pt1 + 1 + i; + index[count++] = pt2 + i; + pt1++; + } + else + { + index[count++] = pt1 + i; + index[count++] = pt2 - 1 + i; + index[count++] = pt2 + i; + pt2--; + } + } + + // Bottom cap + pt1 = 0; + pt2 = size_s-1; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = getProfile().mProfile[pt1]; + LLVector3 p2 = getProfile().mProfile[pt2]; + LLVector3 pa = getProfile().mProfile[pt1+1]; + LLVector3 pb = getProfile().mProfile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + index[count++] = pt1; + index[count++] = pt2; + index[count++] = pt1 + 1; + pt1++; + } + else + { + index[count++] = pt1; + index[count++] = pt2; + index[count++] = pt2 - 1; + pt2--; + } + } + } + } + else + { + // Closed solid. Easy case. + for (t = 0; t < size_t - 1; t++) + { + for (s = 0; s < size_s - 1; s++) + { + // Should wrap properly, but for now... + i = s + t*size_s; + + index[count++] = i; // x,y + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s; // x,y+1 + + index[count++] = i + size_s; // x,y+1 + index[count++] = i + 1; // x+1,y + index[count++] = i + size_s + 1; // x+1,y+1 + } + } + + // Do the top and bottom caps, if necessary + if (path_open) + { + // bottom cap + for (s = 1; s < size_s - 2; s++) + { + index[count++] = s+1; + index[count++] = s; + index[count++] = 0; + } + + // top cap + S32 offset = (size_t - 1)*size_s; + for (s = 1; s < size_s - 2; s++) + { + // Inverted ordering from bottom cap. + index[count++] = offset; + index[count++] = offset + s; + index[count++] = offset + s + 1; + } + } + } + +#ifdef LL_DEBUG + // assert that we computed the correct number of indices + if (count != expected_num_triangle_indices ) + { + llerrs << "bad index count prediciton:" + << " expected=" << expected_num_triangle_indices + << " actual=" << count << llendl; + } +#endif + +#if 0 + // verify that each index does not point beyond the size of the mesh + S32 num_vertices = mMesh.size(); + for (i = 0; i < count; i+=3) + { + llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl; + llassert(index[i] < num_vertices); + llassert(index[i+1] < num_vertices); + llassert(index[i+2] < num_vertices); + } +#endif + + num_indices = count; + return index; +} + +S32 LLVolume::getNumTriangleIndices() const +{ + BOOL profile_open = getProfile().isOpen(); + BOOL hollow = (mParams.getProfileParams().getHollow() > 0); + BOOL path_open = getPath().isOpen(); + + S32 size_s, size_s_out, size_t; + size_s = getProfile().getTotal(); + size_s_out = getProfile().getTotalOut(); + size_t = getPath().mPath.size(); + + S32 count = 0; + if (profile_open) /* Flawfinder: ignore */ + { + if (hollow) + { + // Open hollow -- much like the closed solid, except we + // we need to stitch up the gap between s=0 and s=size_s-1 + count = (size_t - 1) * (((size_s -1) * 6) + 6); + } + else + { + count = (size_t - 1) * (((size_s -1) * 6) + 6); + } + } + else if (hollow) + { + // Closed hollow + // Outer face + count = (size_t - 1) * (size_s_out - 1) * 6; + + // Inner face + count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6; + } + else + { + // Closed solid. Easy case. + count = (size_t - 1) * (size_s - 1) * 6; + } + + if (path_open) + { + S32 cap_triangle_count = size_s - 3; + if ( profile_open + || hollow ) + { + cap_triangle_count = size_s - 2; + } + if ( cap_triangle_count > 0 ) + { + // top and bottom caps + count += cap_triangle_count * 2 * 3; + } + } + return count; +} + + +S32 LLVolume::getNumTriangles() const +{ + U32 triangle_count = 0; + + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + triangle_count += getVolumeFace(i).mNumIndices/3; + } + + return triangle_count; +} + + +//----------------------------------------------------------------------------- +// generateSilhouetteVertices() +//----------------------------------------------------------------------------- +void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, + std::vector<LLVector3> &normals, + const LLVector3& obj_cam_vec_in, + const LLMatrix4& mat_in, + const LLMatrix3& norm_mat_in, + S32 face_mask) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + LLMatrix4a mat; + mat.loadu(mat_in); + + LLMatrix4a norm_mat; + norm_mat.loadu(norm_mat_in); + + LLVector4a obj_cam_vec; + obj_cam_vec.load3(obj_cam_vec_in.mV); + + vertices.clear(); + normals.clear(); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + return; + } + + S32 cur_index = 0; + //for each face + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + LLVolumeFace& face = *iter; + + if (!(face_mask & (0x1 << cur_index++)) || + face.mNumIndices == 0 || face.mEdge.empty()) + { + continue; + } + + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { + + } + else { + + //============================================== + //DEBUG draw edge map instead of silhouette edge + //============================================== + +#if DEBUG_SILHOUETTE_EDGE_MAP + + //for each triangle + U32 count = face.mNumIndices; + for (U32 j = 0; j < count/3; j++) { + //get vertices + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + //get current face center + LLVector3 cCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //for each edge + for (S32 k = 0; k < 3; k++) { + S32 nIndex = face.mEdge[j*3+k]; + if (nIndex <= -1) { + continue; + } + + if (nIndex >= (S32) count/3) { + continue; + } + //get neighbor vertices + v1 = face.mIndices[nIndex*3+0]; + v2 = face.mIndices[nIndex*3+1]; + v3 = face.mIndices[nIndex*3+2]; + + //get neighbor face center + LLVector3 nCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //draw line + vertices.push_back(cCenter); + vertices.push_back(nCenter); + normals.push_back(LLVector3(1,1,1)); + normals.push_back(LLVector3(1,1,1)); + segments.push_back(vertices.size()); + } + } + + continue; + + //============================================== + //DEBUG + //============================================== + + //============================================== + //DEBUG draw normals instead of silhouette edge + //============================================== +#elif DEBUG_SILHOUETTE_NORMALS + + //for each vertex + for (U32 j = 0; j < face.mNumVertices; j++) { + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); +#if DEBUG_SILHOUETTE_BINORMALS + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mBinormal*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); +#endif + } + + continue; +#else + //============================================== + //DEBUG + //============================================== + + static const U8 AWAY = 0x01, + TOWARDS = 0x02; + + //for each triangle + std::vector<U8> fFacing; + vector_append(fFacing, face.mNumIndices/3); + + LLVector4a* v = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + //approximate normal + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + LLVector4a c1,c2; + c1.setSub(v[v1], v[v2]); + c2.setSub(v[v2], v[v3]); + + LLVector4a norm; + + norm.setCross3(c1, c2); + + if (norm.dot3(norm) < 0.00000001f) + { + fFacing[j] = AWAY | TOWARDS; + } + else + { + //get view vector + LLVector4a view; + view.setSub(obj_cam_vec, v[v1]); + bool away = view.dot3(norm) > 0.0f; + if (away) + { + fFacing[j] = AWAY; + } + else + { + fFacing[j] = TOWARDS; + } + } + } + + //for each triangle + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + if (fFacing[j] == (AWAY | TOWARDS)) + { //this is a degenerate triangle + //take neighbor facing (degenerate faces get facing of one of their neighbors) + // *FIX IF NEEDED: this does not deal with neighboring degenerate faces + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j*3+k]; + if (index != -1) + { + fFacing[j] = fFacing[index]; + break; + } + } + continue; //skip degenerate face + } + + //for each edge + for (S32 k = 0; k < 3; k++) { + S32 index = face.mEdge[j*3+k]; + if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { + //our neighbor is degenerate, make him face our direction + fFacing[face.mEdge[j*3+k]] = fFacing[j]; + continue; + } + + if (index == -1 || //edge has no neighbor, MUST be a silhouette edge + (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge + + S32 v1 = face.mIndices[j*3+k]; + S32 v2 = face.mIndices[j*3+((k+1)%3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } +#endif + } + } +} + +S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) +{ + LLVector4a starta, enda; + starta.load3(start.mV); + enda.load3(end.mV); + + return lineSegmentIntersect(starta, enda, face, intersection, tex_coord, normal, bi_normal); + +} + + +S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) +{ + S32 hit_face = -1; + + S32 start_face; + S32 end_face; + + if (face == -1) // ALL_SIDES + { + start_face = 0; + end_face = getNumVolumeFaces() - 1; + } + else + { + start_face = face; + end_face = face; + } + + LLVector4a dir; + dir.setSub(end, start); + + F32 closest_t = 2.f; // must be larger than 1 + + end_face = llmin(end_face, getNumVolumeFaces()-1); + + for (S32 i = start_face; i <= end_face; i++) + { + LLVolumeFace &face = mVolumeFaces[i]; + + LLVector4a box_center; + box_center.setAdd(face.mExtents[0], face.mExtents[1]); + box_center.mul(0.5f); + + LLVector4a box_size; + box_size.setSub(face.mExtents[1], face.mExtents[0]); + + if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) + { + if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them + { + genBinormals(i); + } + + if (!face.mOctree) + { + face.createOctree(); + } + + //LLVector4a* p = (LLVector4a*) face.mPositions; + + LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal); + intersect.traverse(face.mOctree); + if (intersect.mHitFace) + { + hit_face = i; + } + } + } + + + return hit_face; +} + +class LLVertexIndexPair +{ +public: + LLVertexIndexPair(const LLVector3 &vertex, const S32 index); + + LLVector3 mVertex; + S32 mIndex; +}; + +LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index) +{ + mVertex = vertex; + mIndex = index; +} + +const F32 VERTEX_SLOP = 0.00001f; +const F32 VERTEX_SLOP_SQRD = VERTEX_SLOP * VERTEX_SLOP; + +struct lessVertex +{ + bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) + { + const F32 slop = VERTEX_SLOP; + + if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) + { + return TRUE; + } + else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) + { + return FALSE; + } + + if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) + { + return TRUE; + } + else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) + { + return FALSE; + } + + if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) + { + return TRUE; + } + else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) + { + return FALSE; + } + + return FALSE; + } +}; + +struct lessTriangle +{ + bool operator()(const S32 *a, const S32 *b) + { + if (*a < *b) + { + return TRUE; + } + else if (*a > *b) + { + return FALSE; + } + + if (*(a+1) < *(b+1)) + { + return TRUE; + } + else if (*(a+1) > *(b+1)) + { + return FALSE; + } + + if (*(a+2) < *(b+2)) + { + return TRUE; + } + else if (*(a+2) > *(b+2)) + { + return FALSE; + } + + return FALSE; + } +}; + +BOOL equalTriangle(const S32 *a, const S32 *b) +{ + if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) + { + return TRUE; + } + return FALSE; +} + +BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, + const std::vector<Point>& input_vertices, + const S32 num_input_triangles, + S32 *input_triangles, + S32 &num_output_vertices, + LLVector3 **output_vertices, + S32 &num_output_triangles, + S32 **output_triangles) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + /* Testing: avoid any cleanup + static BOOL skip_cleanup = TRUE; + if ( skip_cleanup ) + { + num_output_vertices = num_input_vertices; + num_output_triangles = num_input_triangles; + + *output_vertices = new LLVector3[num_input_vertices]; + for (S32 index = 0; index < num_input_vertices; index++) + { + (*output_vertices)[index] = input_vertices[index].mPos; + } + + *output_triangles = new S32[num_input_triangles*3]; + memcpy(*output_triangles, input_triangles, 3*num_input_triangles*sizeof(S32)); // Flawfinder: ignore + return TRUE; + } + */ + + // Here's how we do this: + // Create a structure which contains the original vertex index and the + // LLVector3 data. + // "Sort" the data by the vectors + // Create an array the size of the old vertex list, with a mapping of + // old indices to new indices. + // Go through triangles, shift so the lowest index is first + // Sort triangles by first index + // Remove duplicate triangles + // Allocate and pack new triangle data. + + //LLTimer cleanupTimer; + //llinfos << "In vertices: " << num_input_vertices << llendl; + //llinfos << "In triangles: " << num_input_triangles << llendl; + + S32 i; + typedef std::multiset<LLVertexIndexPair*, lessVertex> vertex_set_t; + vertex_set_t vertex_list; + + LLVertexIndexPair *pairp = NULL; + for (i = 0; i < num_input_vertices; i++) + { + LLVertexIndexPair *new_pairp = new LLVertexIndexPair(input_vertices[i].mPos, i); + vertex_list.insert(new_pairp); + } + + // Generate the vertex mapping and the list of vertices without + // duplicates. This will crash if there are no vertices. + llassert(num_input_vertices > 0); // check for no vertices! + S32 *vertex_mapping = new S32[num_input_vertices]; + LLVector3 *new_vertices = new LLVector3[num_input_vertices]; + LLVertexIndexPair *prev_pairp = NULL; + + S32 new_num_vertices; + + new_num_vertices = 0; + for (vertex_set_t::iterator iter = vertex_list.begin(), + end = vertex_list.end(); + iter != end; iter++) + { + pairp = *iter; + if (!prev_pairp || ((pairp->mVertex - prev_pairp->mVertex).magVecSquared() >= VERTEX_SLOP_SQRD)) + { + new_vertices[new_num_vertices] = pairp->mVertex; + //llinfos << "Added vertex " << new_num_vertices << " : " << pairp->mVertex << llendl; + new_num_vertices++; + // Update the previous + prev_pairp = pairp; + } + else + { + //llinfos << "Removed duplicate vertex " << pairp->mVertex << ", distance magVecSquared() is " << (pairp->mVertex - prev_pairp->mVertex).magVecSquared() << llendl; + } + vertex_mapping[pairp->mIndex] = new_num_vertices - 1; + } + + // Iterate through triangles and remove degenerates, re-ordering vertices + // along the way. + S32 *new_triangles = new S32[num_input_triangles * 3]; + S32 new_num_triangles = 0; + + for (i = 0; i < num_input_triangles; i++) + { + S32 v1 = i*3; + S32 v2 = v1 + 1; + S32 v3 = v1 + 2; + + //llinfos << "Checking triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; + input_triangles[v1] = vertex_mapping[input_triangles[v1]]; + input_triangles[v2] = vertex_mapping[input_triangles[v2]]; + input_triangles[v3] = vertex_mapping[input_triangles[v3]]; + + if ((input_triangles[v1] == input_triangles[v2]) + || (input_triangles[v1] == input_triangles[v3]) + || (input_triangles[v2] == input_triangles[v3])) + { + //llinfos << "Removing degenerate triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; + // Degenerate triangle, skip + continue; + } + + if (input_triangles[v1] < input_triangles[v2]) + { + if (input_triangles[v1] < input_triangles[v3]) + { + // (0 < 1) && (0 < 2) + new_triangles[new_num_triangles*3] = input_triangles[v1]; + new_triangles[new_num_triangles*3+1] = input_triangles[v2]; + new_triangles[new_num_triangles*3+2] = input_triangles[v3]; + } + else + { + // (0 < 1) && (2 < 0) + new_triangles[new_num_triangles*3] = input_triangles[v3]; + new_triangles[new_num_triangles*3+1] = input_triangles[v1]; + new_triangles[new_num_triangles*3+2] = input_triangles[v2]; + } + } + else if (input_triangles[v2] < input_triangles[v3]) + { + // (1 < 0) && (1 < 2) + new_triangles[new_num_triangles*3] = input_triangles[v2]; + new_triangles[new_num_triangles*3+1] = input_triangles[v3]; + new_triangles[new_num_triangles*3+2] = input_triangles[v1]; + } + else + { + // (1 < 0) && (2 < 1) + new_triangles[new_num_triangles*3] = input_triangles[v3]; + new_triangles[new_num_triangles*3+1] = input_triangles[v1]; + new_triangles[new_num_triangles*3+2] = input_triangles[v2]; + } + new_num_triangles++; + } + + if (new_num_triangles == 0) + { + llwarns << "Created volume object with 0 faces." << llendl; + delete[] new_triangles; + delete[] vertex_mapping; + delete[] new_vertices; + return FALSE; + } + + typedef std::set<S32*, lessTriangle> triangle_set_t; + triangle_set_t triangle_list; + + for (i = 0; i < new_num_triangles; i++) + { + triangle_list.insert(&new_triangles[i*3]); + } + + // Sort through the triangle list, and delete duplicates + + S32 *prevp = NULL; + S32 *curp = NULL; + + S32 *sorted_tris = new S32[new_num_triangles*3]; + S32 cur_tri = 0; + for (triangle_set_t::iterator iter = triangle_list.begin(), + end = triangle_list.end(); + iter != end; iter++) + { + curp = *iter; + if (!prevp || !equalTriangle(prevp, curp)) + { + //llinfos << "Added triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl; + sorted_tris[cur_tri*3] = *curp; + sorted_tris[cur_tri*3+1] = *(curp+1); + sorted_tris[cur_tri*3+2] = *(curp+2); + cur_tri++; + prevp = curp; + } + else + { + //llinfos << "Skipped triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl; + } + } + + *output_vertices = new LLVector3[new_num_vertices]; + num_output_vertices = new_num_vertices; + for (i = 0; i < new_num_vertices; i++) + { + (*output_vertices)[i] = new_vertices[i]; + } + + *output_triangles = new S32[cur_tri*3]; + num_output_triangles = cur_tri; + memcpy(*output_triangles, sorted_tris, 3*cur_tri*sizeof(S32)); /* Flawfinder: ignore */ + + /* + llinfos << "Out vertices: " << num_output_vertices << llendl; + llinfos << "Out triangles: " << num_output_triangles << llendl; + for (i = 0; i < num_output_vertices; i++) + { + llinfos << i << ":" << (*output_vertices)[i] << llendl; + } + for (i = 0; i < num_output_triangles; i++) + { + llinfos << i << ":" << (*output_triangles)[i*3] << ":" << (*output_triangles)[i*3+1] << ":" << (*output_triangles)[i*3+2] << llendl; + } + */ + + //llinfos << "Out vertices: " << num_output_vertices << llendl; + //llinfos << "Out triangles: " << num_output_triangles << llendl; + delete[] vertex_mapping; + vertex_mapping = NULL; + delete[] new_vertices; + new_vertices = NULL; + delete[] new_triangles; + new_triangles = NULL; + delete[] sorted_tris; + sorted_tris = NULL; + triangle_list.clear(); + std::for_each(vertex_list.begin(), vertex_list.end(), DeletePointer()); + vertex_list.clear(); + + return TRUE; +} + + +BOOL LLVolumeParams::importFile(LLFILE *fp) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + //llinfos << "importing volume" << llendl; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importFile(fp); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importFile(fp); + } + else + { + llwarns << "unknown keyword " << keyword << " in volume import" << llendl; + } + } + + return TRUE; +} + +BOOL LLVolumeParams::exportFile(LLFILE *fp) const +{ + fprintf(fp,"\tshape 0\n"); + fprintf(fp,"\t{\n"); + mPathParams.exportFile(fp); + mProfileParams.exportFile(fp); + fprintf(fp, "\t}\n"); + return TRUE; +} + + +BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + //llinfos << "importing volume" << llendl; + const S32 BUFSIZE = 16384; + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf(buffer, " %255s", keyword); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importLegacyStream(input_stream); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importLegacyStream(input_stream); + } + else + { + llwarns << "unknown keyword " << keyword << " in volume import" << llendl; + } + } + + return TRUE; +} + +BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + output_stream <<"\tshape 0\n"; + output_stream <<"\t{\n"; + mPathParams.exportLegacyStream(output_stream); + mProfileParams.exportLegacyStream(output_stream); + output_stream << "\t}\n"; + return TRUE; +} + +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; +} + +LLSD LLVolumeParams::asLLSD() const +{ + LLSD sd = LLSD(); + sd["path"] = mPathParams; + sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + + return sd; +} + +bool LLVolumeParams::fromLLSD(LLSD& sd) +{ + mPathParams.fromLLSD(sd["path"]); + mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + + return true; +} + +void LLVolumeParams::reduceS(F32 begin, F32 end) +{ + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mProfileParams.getBegin(); + F32 b = mProfileParams.getEnd(); + mProfileParams.setBegin(a + begin * (b - a)); + mProfileParams.setEnd(a + end * (b - a)); +} + +void LLVolumeParams::reduceT(F32 begin, F32 end) +{ + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mPathParams.getBegin(); + F32 b = mPathParams.getEnd(); + mPathParams.setBegin(a + begin * (b - a)); + mPathParams.setEnd(a + end * (b - a)); +} + +const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity +const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity + +// returns TRUE if the shape can be approximated with a convex shape +// for collison purposes +BOOL LLVolumeParams::isConvex() const +{ + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return FALSE; + } + + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); + F32 hollow = mProfileParams.getHollow(); + + U8 path_type = mPathParams.getCurveType(); + if ( path_length > MIN_CONCAVE_PATH_WEDGE + && ( mPathParams.getTwist() != mPathParams.getTwistBegin() + || (hollow > 0.f + && LL_PCODE_PATH_LINE != path_type) ) ) + { + // twist along a "not too short" path is concave + return FALSE; + } + + F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); + BOOL same_hole = hollow == 0.f + || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; + + F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // it is a sphere and spheres get twice the minimum profile wedge + min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; + } + + BOOL convex_profile = ( ( profile_length == 1.f + || profile_length <= 0.5f ) + && hollow == 0.f ) // trivially convex + || ( profile_length <= min_profile_wedge + && same_hole ); // effectvely convex (even when hollow) + + if (!convex_profile) + { + // profile is concave + return FALSE; + } + + if ( LL_PCODE_PATH_LINE == path_type ) + { + // straight paths with convex profile + return TRUE; + } + + BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); + if (concave_path) + { + return FALSE; + } + + // we're left with spheres, toroids and tubes + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // at this stage all spheres must be convex + return TRUE; + } + + // it's a toroid or tube + if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) + { + // effectively convex + return TRUE; + } + + return FALSE; +} + +// debug +void LLVolumeParams::setCube() +{ + mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); + mProfileParams.setBegin(0.f); + mProfileParams.setEnd(1.f); + mProfileParams.setHollow(0.f); + + mPathParams.setBegin(0.f); + mPathParams.setEnd(1.f); + mPathParams.setScale(1.f, 1.f); + mPathParams.setShear(0.f, 0.f); + mPathParams.setCurveType(LL_PCODE_PATH_LINE); + mPathParams.setTwistBegin(0.f); + mPathParams.setTwistEnd(0.f); + mPathParams.setRadiusOffset(0.f); + mPathParams.setTaper(0.f, 0.f); + mPathParams.setRevolutions(0.f); + mPathParams.setSkew(0.f); +} + +LLFaceID LLVolume::generateFaceMask() +{ + LLFaceID new_mask = 0x0000; + + switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + new_mask |= LL_FACE_OUTER_SIDE_0; + break; + case LL_PCODE_PROFILE_SQUARE: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_EQUALTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + default: + llerrs << "Unknown profile!" << llendl; + break; + } + + // handle hollow objects + if (mParams.getProfileParams().getHollow() > 0) + { + new_mask |= LL_FACE_INNER_SIDE; + } + + // handle open profile curves + if (mProfilep->isOpen()) + { + new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; + } + + // handle open path curves + if (mPathp->isOpen()) + { + new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; + } + + return new_mask; +} + +BOOL LLVolume::isFaceMaskValid(LLFaceID face_mask) +{ + LLFaceID test_mask = 0; + for(S32 i = 0; i < getNumFaces(); i++) + { + test_mask |= mProfilep->mFaces[i].mFaceID; + } + + return test_mask == face_mask; +} + +BOOL LLVolume::isConvex() const +{ + // mParams.isConvex() may return FALSE even though the final + // geometry is actually convex due to LOD approximations. + // TODO -- provide LLPath and LLProfile with isConvex() methods + // that correctly determine convexity. -- Leviathan + return mParams.isConvex(); +} + + +std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params) +{ + s << "{type=" << (U32) profile_params.mCurveType; + s << ", begin=" << profile_params.mBegin; + s << ", end=" << profile_params.mEnd; + s << ", hollow=" << profile_params.mHollow; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params) +{ + s << "{type=" << (U32) path_params.mCurveType; + s << ", begin=" << path_params.mBegin; + s << ", end=" << path_params.mEnd; + s << ", twist=" << path_params.mTwistEnd; + s << ", scale=" << path_params.mScale; + s << ", shear=" << path_params.mShear; + s << ", twist_begin=" << path_params.mTwistBegin; + s << ", radius_offset=" << path_params.mRadiusOffset; + s << ", taper=" << path_params.mTaper; + s << ", revolutions=" << path_params.mRevolutions; + s << ", skew=" << path_params.mSkew; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params) +{ + s << "{profileparams = " << volume_params.mProfileParams; + s << ", pathparams = " << volume_params.mPathParams; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLProfile &profile) +{ + s << " {open=" << (U32) profile.mOpen; + s << ", dirty=" << profile.mDirty; + s << ", totalout=" << profile.mTotalOut; + s << ", total=" << profile.mTotal; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLPath &path) +{ + s << "{open=" << (U32) path.mOpen; + s << ", dirty=" << path.mDirty; + s << ", step=" << path.mStep; + s << ", total=" << path.mTotal; + s << "}"; + return s; +} + +std::ostream& operator<<(std::ostream &s, const LLVolume &volume) +{ + s << "{params = " << volume.getParams(); + s << ", path = " << *volume.mPathp; + s << ", profile = " << *volume.mProfilep; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) +{ + s << "{params = " << volumep->getParams(); + s << ", path = " << *(volumep->mPathp); + s << ", profile = " << *(volumep->mProfilep); + s << "}"; + return s; +} + +LLVolumeFace::LLVolumeFace() : + mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), + mOctree(NULL) +{ + mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3); + mCenter = mExtents+2; +} + +LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) +: mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), + mOctree(NULL) +{ + mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3); + mCenter = mExtents+2; + *this = src; +} + +LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) +{ + if (&src == this) + { //self assignment, do nothing + return *this; + } + + mID = src.mID; + mTypeMask = src.mTypeMask; + mBeginS = src.mBeginS; + mBeginT = src.mBeginT; + mNumS = src.mNumS; + mNumT = src.mNumT; + + mExtents[0] = src.mExtents[0]; + mExtents[1] = src.mExtents[1]; + *mCenter = *src.mCenter; + + mNumVertices = 0; + mNumIndices = 0; + + freeData(); + + LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a)); + + resizeVertices(src.mNumVertices); + resizeIndices(src.mNumIndices); + + if (mNumVertices) + { + S32 vert_size = mNumVertices*sizeof(LLVector4a); + S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + + + if (src.mBinormals) + { + allocateBinormals(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) src.mBinormals, vert_size); + } + else + { + free(mBinormals); + mBinormals = NULL; + } + + if (src.mWeights) + { + allocateWeights(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); + } + else + { + free(mWeights); + mWeights = NULL; + } + } + + if (mNumIndices) + { + S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); + } + + //delete + return *this; +} + +LLVolumeFace::~LLVolumeFace() +{ + free(mExtents); + mExtents = NULL; + + freeData(); +} + +void LLVolumeFace::freeData() +{ + free(mPositions); + mPositions = NULL; + free( mNormals); + mNormals = NULL; + free(mTexCoords); + mTexCoords = NULL; + free(mIndices); + mIndices = NULL; + free(mBinormals); + mBinormals = NULL; + free(mWeights); + mWeights = NULL; + + delete mOctree; + mOctree = NULL; +} + +BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) +{ + //tree for this face is no longer valid + delete mOctree; + mOctree = NULL; + + BOOL ret = FALSE ; + if (mTypeMask & CAP_MASK) + { + ret = createCap(volume, partial_build); + } + else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) + { + ret = createSide(volume, partial_build); + } + else + { + llerrs << "Unknown/uninitialized face type!" << llendl; + } + + //update the range of the texture coordinates + if(ret) + { + mTexCoordExtents[0].setVec(1.f, 1.f) ; + mTexCoordExtents[1].setVec(0.f, 0.f) ; + + for(U32 i = 0 ; i < mNumVertices ; i++) + { + if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0]) + { + mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ; + } + if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0]) + { + mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ; + } + + if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1]) + { + mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ; + } + if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1]) + { + mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ; + } + } + mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ; + mTexCoordExtents[0].mV[1] = llmax(0.f, mTexCoordExtents[0].mV[1]) ; + mTexCoordExtents[1].mV[0] = llmin(1.f, mTexCoordExtents[1].mV[0]) ; + mTexCoordExtents[1].mV[1] = llmin(1.f, mTexCoordExtents[1].mV[1]) ; + } + + return ret ; +} + +void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) +{ + cv.setPosition(mPositions[index]); + cv.setNormal(mNormals[index]); + cv.mTexCoord = mTexCoords[index]; +} + +bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const +{ + return getPosition().equals3(rhs.getPosition()) && + mTexCoord == rhs.mTexCoord && + getNormal().equals3(rhs.getNormal()); +} + +bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const +{ + if (a.mV[0] != b.mV[0]) + { + return a.mV[0] < b.mV[0]; + } + + if (a.mV[1] != b.mV[1]) + { + return a.mV[1] < b.mV[1]; + } + + return a.mV[2] < b.mV[2]; +} + +void LLVolumeFace::optimize(F32 angle_cutoff) +{ + LLVolumeFace new_face; + + //map of points to vector of vertices at that point + VertexMapData::PointMap point_map; + + //remove redundant vertices + for (U32 i = 0; i < mNumIndices; ++i) + { + U16 index = mIndices[i]; + + LLVolumeFace::VertexData cv; + getVertexData(index, cv); + + BOOL found = FALSE; + VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + if (point_iter != point_map.end()) + { //duplicate point might exist + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + LLVolumeFace::VertexData& tv = (point_iter->second)[j]; + if (tv.compareNormal(cv, angle_cutoff)) + { + found = TRUE; + new_face.pushIndex((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + new_face.pushVertex(cv); + U16 index = (U16) new_face.mNumVertices-1; + new_face.pushIndex(index); + + VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + } + } + } + + swapData(new_face); +} + +class LLVCacheTriangleData; + +class LLVCacheVertexData +{ +public: + S32 mIdx; + S32 mCacheTag; + F32 mScore; + U32 mActiveTriangles; + std::vector<LLVCacheTriangleData*> mTriangles; + + LLVCacheVertexData() + { + mCacheTag = -1; + mScore = 0.f; + mActiveTriangles = 0; + mIdx = -1; + } +}; + +class LLVCacheTriangleData +{ +public: + bool mActive; + F32 mScore; + LLVCacheVertexData* mVertex[3]; + + LLVCacheTriangleData() + { + mActive = true; + mScore = 0.f; + mVertex[0] = mVertex[1] = mVertex[2] = NULL; + } + + void complete() + { + mActive = false; + for (S32 i = 0; i < 3; ++i) + { + if (mVertex[i]) + { + llassert_always(mVertex[i]->mActiveTriangles > 0); + mVertex[i]->mActiveTriangles--; + } + } + } + + bool operator<(const LLVCacheTriangleData& rhs) const + { //highest score first + return rhs.mScore < mScore; + } +}; + +const F32 FindVertexScore_CacheDecayPower = 1.5f; +const F32 FindVertexScore_LastTriScore = 0.75f; +const F32 FindVertexScore_ValenceBoostScale = 2.0f; +const F32 FindVertexScore_ValenceBoostPower = 0.5f; +const U32 MaxSizeVertexCache = 32; + +F32 find_vertex_score(LLVCacheVertexData& data) +{ + if (data.mActiveTriangles == 0) + { //no triangle references this vertex + return -1.f; + } + + F32 score = 0.f; + + S32 cache_idx = data.mCacheTag; + + if (cache_idx < 0) + { + //not in cache + } + else + { + if (cache_idx < 3) + { //vertex was in the last triangle + score = FindVertexScore_LastTriScore; + } + else + { //more points for being higher in the cache + F32 scaler = 1.f/(MaxSizeVertexCache-3); + score = 1.f-((cache_idx-3)*scaler); + score = powf(score, FindVertexScore_CacheDecayPower); + } + } + + //bonus points for having low valence + F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + score += FindVertexScore_ValenceBoostScale * valence_boost; + + return score; +} + +class LLVCacheFIFO +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache]; + U32 mMisses; + + LLVCacheFIFO() + { + mMisses = 0; + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { + mCache[i] = NULL; + } + } + + void addVertex(LLVCacheVertexData* data) + { + if (data->mCacheTag == -1) + { + mMisses++; + + S32 end = MaxSizeVertexCache-1; + + if (mCache[end]) + { + mCache[end]->mCacheTag = -1; + } + + for (S32 i = end; i > 0; --i) + { + mCache[i] = mCache[i-1]; + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + data->mCacheTag = 0; + } + } +}; + +class LLVCacheLRU +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; + + LLVCacheTriangleData* mBestTriangle; + + U32 mMisses; + + LLVCacheLRU() + { + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + mCache[i] = NULL; + } + + mBestTriangle = NULL; + mMisses = 0; + } + + void addVertex(LLVCacheVertexData* data) + { + S32 end = MaxSizeVertexCache+2; + if (data->mCacheTag != -1) + { //just moving a vertex to the front of the cache + end = data->mCacheTag; + } + else + { + mMisses++; + if (mCache[end]) + { //adding a new vertex, vertex at end of cache falls off + mCache[end]->mCacheTag = -1; + } + } + + for (S32 i = end; i > 0; --i) + { //adjust cache pointers and tags + mCache[i] = mCache[i-1]; + + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + mCache[0]->mCacheTag = 0; + } + + void addTriangle(LLVCacheTriangleData* data) + { + addVertex(data->mVertex[0]); + addVertex(data->mVertex[1]); + addVertex(data->mVertex[2]); + } + + void updateScores() + { + for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) + { //trailing 3 vertices aren't actually in the cache for scoring purposes + if (mCache[i]) + { + mCache[i]->mCacheTag = -1; + } + } + + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { //update scores of vertices in cache + if (mCache[i]) + { + mCache[i]->mScore = find_vertex_score(*(mCache[i])); + llassert_always(mCache[i]->mCacheTag == i); + } + } + + mBestTriangle = NULL; + //update triangle scores + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + if (mCache[i]) + { + for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j) + { + LLVCacheTriangleData* tri = mCache[i]->mTriangles[j]; + if (tri->mActive) + { + tri->mScore = tri->mVertex[0]->mScore; + tri->mScore += tri->mVertex[1]->mScore; + tri->mScore += tri->mVertex[2]->mScore; + + if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) + { + mBestTriangle = tri; + } + } + } + } + } + + //knock trailing 3 vertices off the cache + for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) + { + if (mCache[i]) + { + llassert_always(mCache[i]->mCacheTag == -1); + mCache[i] = NULL; + } + } + } +}; + + +void LLVolumeFace::cacheOptimize() +{ //optimize for vertex cache according to Forsyth method: + // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html + + LLVCacheLRU cache; + + //mapping of vertices to triangles and indices + std::vector<LLVCacheVertexData> vertex_data; + + //mapping of triangles do vertices + std::vector<LLVCacheTriangleData> triangle_data; + + triangle_data.resize(mNumIndices/3); + vertex_data.resize(mNumVertices); + + for (U32 i = 0; i < mNumIndices; i++) + { //populate vertex data and triangle data arrays + U16 idx = mIndices[i]; + U32 tri_idx = i/3; + + vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx])); + vertex_data[idx].mIdx = idx; + triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]); + } + + /*F32 pre_acmr = 1.f; + //measure cache misses from before rebuild + { + LLVCacheFIFO test_cache; + for (U32 i = 0; i < mNumIndices; ++i) + { + test_cache.addVertex(&vertex_data[mIndices[i]]); + } + + for (U32 i = 0; i < mNumVertices; i++) + { + vertex_data[i].mCacheTag = -1; + } + + pre_acmr = (F32) test_cache.mMisses/(mNumIndices/3); + }*/ + + for (U32 i = 0; i < mNumVertices; i++) + { //initialize score values (no cache -- might try a fifo cache here) + vertex_data[i].mScore = find_vertex_score(vertex_data[i]); + vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size(); + + for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j) + { + vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore; + } + } + + //sort triangle data by score + std::sort(triangle_data.begin(), triangle_data.end()); + + std::vector<U16> new_indices; + + LLVCacheTriangleData* tri; + + //prime pump by adding first triangle to cache; + tri = &(triangle_data[0]); + cache.addTriangle(tri); + new_indices.push_back(tri->mVertex[0]->mIdx); + new_indices.push_back(tri->mVertex[1]->mIdx); + new_indices.push_back(tri->mVertex[2]->mIdx); + tri->complete(); + + U32 breaks = 0; + for (U32 i = 1; i < mNumIndices/3; ++i) + { + cache.updateScores(); + tri = cache.mBestTriangle; + if (!tri) + { + breaks++; + for (U32 j = 0; j < triangle_data.size(); ++j) + { + if (triangle_data[j].mActive) + { + tri = &(triangle_data[j]); + break; + } + } + } + + cache.addTriangle(tri); + new_indices.push_back(tri->mVertex[0]->mIdx); + new_indices.push_back(tri->mVertex[1]->mIdx); + new_indices.push_back(tri->mVertex[2]->mIdx); + tri->complete(); + } + + for (U32 i = 0; i < mNumIndices; ++i) + { + mIndices[i] = new_indices[i]; + } + + /*F32 post_acmr = 1.f; + //measure cache misses from after rebuild + { + LLVCacheFIFO test_cache; + for (U32 i = 0; i < mNumVertices; i++) + { + vertex_data[i].mCacheTag = -1; + } + + for (U32 i = 0; i < mNumIndices; ++i) + { + test_cache.addVertex(&vertex_data[mIndices[i]]); + } + + post_acmr = (F32) test_cache.mMisses/(mNumIndices/3); + }*/ + + //optimize for pre-TnL cache + + //allocate space for new buffer + S32 num_verts = mNumVertices; + LLVector4a* pos = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + LLVector4a* norm = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + LLVector2* tc = (LLVector2*) malloc(size); + + LLVector4a* wght = NULL; + if (mWeights) + { + wght = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + } + + LLVector4a* binorm = NULL; + if (mBinormals) + { + binorm = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + } + + //allocate mapping of old indices to new indices + std::vector<S32> new_idx; + new_idx.resize(mNumVertices, -1); + + S32 cur_idx = 0; + for (U32 i = 0; i < mNumIndices; ++i) + { + U16 idx = mIndices[i]; + if (new_idx[idx] == -1) + { //this vertex hasn't been added yet + new_idx[idx] = cur_idx; + + //copy vertex data + pos[cur_idx] = mPositions[idx]; + norm[cur_idx] = mNormals[idx]; + tc[cur_idx] = mTexCoords[idx]; + if (mWeights) + { + wght[cur_idx] = mWeights[idx]; + } + if (mBinormals) + { + binorm[cur_idx] = mBinormals[idx]; + } + + cur_idx++; + } + } + + for (U32 i = 0; i < mNumIndices; ++i) + { + mIndices[i] = new_idx[mIndices[i]]; + } + + free(mPositions); + free(mNormals); + free(mTexCoords); + free(mWeights); + free(mBinormals); + + mPositions = pos; + mNormals = norm; + mTexCoords = tc; + mWeights = wght; + mBinormals = binorm; + + //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); + //llinfos << result << llendl; + +} + +void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) +{ + if (mOctree) + { + return; + } + + mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL); + new LLVolumeOctreeListener(mOctree); + + for (U32 i = 0; i < mNumIndices; i+= 3) + { //for each triangle + LLPointer<LLVolumeTriangle> tri = new LLVolumeTriangle(); + + const LLVector4a& v0 = mPositions[mIndices[i]]; + const LLVector4a& v1 = mPositions[mIndices[i+1]]; + const LLVector4a& v2 = mPositions[mIndices[i+2]]; + + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = mIndices[i]; + tri->mIndex[1] = mIndices[i+1]; + tri->mIndex[2] = mIndices[i+2]; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max,min); + + tri->mRadius = size.getLength3().getF32() * scaler; + + //insert + mOctree->insert(tri); + } + + //remove unneeded octree layers + while (!mOctree->balance()) { } + + //calculate AABB for each node + LLVolumeOctreeRebound rebound(this); + rebound.traverse(mOctree); + + if (gDebugGL) + { + LLVolumeOctreeValidate validate; + validate.traverse(mOctree); + } +} + + +void LLVolumeFace::swapData(LLVolumeFace& rhs) +{ + llswap(rhs.mPositions, mPositions); + llswap(rhs.mNormals, mNormals); + llswap(rhs.mBinormals, mBinormals); + llswap(rhs.mTexCoords, mTexCoords); + llswap(rhs.mIndices,mIndices); + llswap(rhs.mNumVertices, mNumVertices); + llswap(rhs.mNumIndices, mNumIndices); +} + +void LerpPlanarVertex(LLVolumeFace::VertexData& v0, + LLVolumeFace::VertexData& v1, + LLVolumeFace::VertexData& v2, + LLVolumeFace::VertexData& vout, + F32 coef01, + F32 coef02) +{ + + LLVector4a lhs; + lhs.setSub(v1.getPosition(), v0.getPosition()); + lhs.mul(coef01); + LLVector4a rhs; + rhs.setSub(v2.getPosition(), v0.getPosition()); + rhs.mul(coef02); + + rhs.add(lhs); + rhs.add(v0.getPosition()); + + vout.setPosition(rhs); + + vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); + vout.setNormal(v0.getNormal()); +} + +BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + const std::vector<LLVolume::Point>& mesh = volume->getMesh(); + const std::vector<LLVector3>& profile = volume->getProfile().mProfile; + S32 max_s = volume->getProfile().getTotal(); + 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]; + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + { + VertexData corners[4]; + VertexData baseVert; + for(S32 t = 0; t < 4; t++) + { + corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); + corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; + corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; + } + + { + LLVector4a lhs; + lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); + LLVector4a rhs; + rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); + baseVert.getNormal().setCross3(lhs, rhs); + baseVert.getNormal().normalize3fast(); + } + + if(!(mTypeMask & TOP_MASK)) + { + baseVert.getNormal().mul(-1.0f); + } + else + { + //Swap the UVs on the U(X) axis for top face + LLVector2 swap; + swap = corners[0].mTexCoord; + corners[0].mTexCoord=corners[3].mTexCoord; + corners[3].mTexCoord=swap; + swap = corners[1].mTexCoord; + corners[1].mTexCoord=corners[2].mTexCoord; + corners[2].mTexCoord=swap; + } + + LLVector4a binormal; + + calc_binormal_from_triangle( binormal, + corners[0].getPosition(), corners[0].mTexCoord, + corners[1].getPosition(), corners[1].mTexCoord, + corners[2].getPosition(), corners[2].mTexCoord); + + binormal.normalize3fast(); + + S32 size = (grid_size+1)*(grid_size+1); + resizeVertices(size); + allocateBinormals(size); + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector4a* binorm = (LLVector4a*) mBinormals; + LLVector2* tc = (LLVector2*) mTexCoords; + + for(int gx = 0;gx<grid_size+1;gx++) + { + for(int gy = 0;gy<grid_size+1;gy++) + { + VertexData newVert; + LerpPlanarVertex( + corners[0], + corners[1], + corners[3], + newVert, + (F32)gx/(F32)grid_size, + (F32)gy/(F32)grid_size); + + *pos++ = newVert.getPosition(); + *norm++ = baseVert.getNormal(); + *tc++ = newVert.mTexCoord; + *binorm++ = binormal; + + if (gx == 0 && gy == 0) + { + min = newVert.getPosition(); + max = min; + } + else + { + min.setMin(min, newVert.getPosition()); + max.setMax(max, newVert.getPosition()); + } + } + } + + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + } + + if (!partial_build) + { + resizeIndices(grid_size*grid_size*6); + + U16* out = mIndices; + + S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; + for(S32 gx = 0;gx<grid_size;gx++) + { + + for(S32 gy = 0;gy<grid_size;gy++) + { + if (mTypeMask & TOP_MASK) + { + for(S32 i=5;i>=0;i--) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + } + else + { + for(S32 i=0;i<6;i++) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + } + } + } + } + + return TRUE; +} + + +BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if (!(mTypeMask & HOLLOW_MASK) && + !(mTypeMask & OPEN_MASK) && + ((volume->getParams().getPathParams().getBegin()==0.0f)&& + (volume->getParams().getPathParams().getEnd()==1.0f))&& + (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && + volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) + ){ + return createUnCutCubeCap(volume, partial_build); + } + + S32 num_vertices = 0, num_indices = 0; + + const std::vector<LLVolume::Point>& mesh = volume->getMesh(); + const std::vector<LLVector3>& profile = volume->getProfile().mProfile; + + // All types of caps have the same number of vertices and indices + num_vertices = profile.size(); + num_indices = (profile.size() - 2)*3; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + resizeVertices(num_vertices+1); + allocateBinormals(num_vertices+1); + + if (!partial_build) + { + resizeIndices(num_indices+3); + } + } + else + { + resizeVertices(num_vertices); + allocateBinormals(num_vertices); + + if (!partial_build) + { + resizeIndices(num_indices); + } + } + + S32 max_s = volume->getProfile().getTotal(); + S32 max_t = volume->getPath().mPath.size(); + + mCenter->clear(); + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + // Figure out the normal, assume all caps are flat faces. + // Cross product to get normals. + + LLVector2 cuv; + LLVector2 min_uv, max_uv; + + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector4a* binorm = (LLVector4a*) mBinormals; + + // Copy the vertices into the array + for (S32 i = 0; i < num_vertices; i++) + { + if (mTypeMask & TOP_MASK) + { + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = profile[i].mV[1]+0.5f; + } + else + { + // Mirror for underside. + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = 0.5f - profile[i].mV[1]; + } + + pos[i].load3(mesh[i + offset].mPos.mV); + + if (i == 0) + { + max = pos[i]; + min = max; + min_uv = max_uv = tc[i]; + } + else + { + update_min_max(min,max,pos[i]); + update_min_max(min_uv, max_uv, tc[i]); + } + } + + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + + cuv = (min_uv + max_uv)*0.5f; + + LLVector4a binormal; + calc_binormal_from_triangle(binormal, + *mCenter, cuv, + pos[0], tc[0], + pos[1], tc[1]); + binormal.normalize3fast(); + + LLVector4a normal; + LLVector4a d0, d1; + + + d0.setSub(*mCenter, pos[0]); + d1.setSub(*mCenter, pos[1]); + + if (mTypeMask & TOP_MASK) + { + normal.setCross3(d0, d1); + } + else + { + normal.setCross3(d1, d0); + } + + normal.normalize3fast(); + + VertexData vd; + vd.setPosition(*mCenter); + vd.mTexCoord = cuv; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + pos[num_vertices] = *mCenter; + tc[num_vertices] = cuv; + num_vertices++; + } + + for (S32 i = 0; i < num_vertices; i++) + { + binorm[i].load4a(binormal.getF32ptr()); + norm[i].load4a(normal.getF32ptr()); + } + + if (partial_build) + { + return TRUE; + } + + if (mTypeMask & HOLLOW_MASK) + { + if (mTypeMask & TOP_MASK) + { + // HOLLOW TOP + // Does it matter if it's open or closed? - djs + + S32 pt1 = 0, pt2 = num_vertices - 1; + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = profile[pt1]; + LLVector3 p2 = profile[pt2]; + LLVector3 pa = profile[pt1+1]; + LLVector3 pb = profile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt1 + 1; + mIndices[i++] = pt2; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2 - 1; + mIndices[i++] = pt2; + pt2--; + } + } + } + else + { + // HOLLOW BOTTOM + // Does it matter if it's open or closed? - djs + + llassert(mTypeMask & BOTTOM_MASK); + S32 pt1 = 0, pt2 = num_vertices - 1; + + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + LLVector3 p1 = profile[pt1]; + LLVector3 p2 = profile[pt2]; + LLVector3 pa = profile[pt1+1]; + LLVector3 pb = profile[pt2-1]; + + p1.mV[VZ] = 0.f; + p2.mV[VZ] = 0.f; + pa.mV[VZ] = 0.f; + pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + + (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + + (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); + + area_1ba = (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + + (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); + + area_21b = (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + + (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + area_2ab = (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + + (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + + (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector3 d1 = p1 - pa; + LLVector3 d2 = p2 - pb; + + if (d1.magVecSquared() < d2.magVecSquared()) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + // Flipped backfacing from top + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt1 + 1; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt2 - 1; + pt2--; + } + } + } + } + else + { + // Not hollow, generate the triangle fan. + U16 v1 = 2; + U16 v2 = 1; + + if (mTypeMask & TOP_MASK) + { + v1 = 1; + v2 = 2; + } + + for (S32 i = 0; i < (num_vertices - 2); i++) + { + mIndices[3*i] = num_vertices - 1; + mIndices[3*i+v1] = i; + mIndices[3*i+v2] = i + 1; + } + + + } + + return TRUE; +} + +void LLVolumeFace::createBinormals() +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if (!mBinormals) + { + allocateBinormals(mNumVertices); + + //generate binormals + LLVector4a* pos = mPositions; + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* binorm = (LLVector4a*) mBinormals; + + LLVector4a* end = mBinormals+mNumVertices; + while (binorm < end) + { + (*binorm++).clear(); + } + + binorm = mBinormals; + + for (U32 i = 0; i < mNumIndices/3; i++) + { //for each triangle + const U16& i0 = mIndices[i*3+0]; + const U16& i1 = mIndices[i*3+1]; + const U16& i2 = mIndices[i*3+2]; + + //calculate binormal + LLVector4a binormal; + calc_binormal_from_triangle(binormal, + pos[i0], tc[i0], + pos[i1], tc[i1], + pos[i2], tc[i2]); + + + //add triangle normal to vertices + binorm[i0].add(binormal); + binorm[i1].add(binormal); + binorm[i2].add(binormal); + + //even out quad contributions + if (i % 2 == 0) + { + binorm[i2].add(binormal); + } + else + { + binorm[i1].add(binormal); + } + } + + //normalize binormals + for (U32 i = 0; i < mNumVertices; i++) + { + binorm[i].normalize3fast(); + //bump map/planar projection code requires normals to be normalized + mNormals[i].normalize3fast(); + } + } +} + +void LLVolumeFace::resizeVertices(S32 num_verts) +{ + free(mPositions); + free(mNormals); + free(mBinormals); + free(mTexCoords); + + mBinormals = NULL; + + if (num_verts) + { + mPositions = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); + assert_aligned(mNormals, 16); + + //pad texture coordinate block end to allow for QWORD reads + S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + mTexCoords = (LLVector2*) malloc(size); + assert_aligned(mTexCoords, 16); + } + else + { + mPositions = NULL; + mNormals = NULL; + mTexCoords = NULL; + } + + mNumVertices = num_verts; +} + +void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) +{ + pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); +} + +void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc) +{ + S32 new_verts = mNumVertices+1; + S32 new_size = new_verts*16; +// S32 old_size = mNumVertices*16; + + //positions + mPositions = (LLVector4a*) realloc(mPositions, new_size); + + //normals + mNormals = (LLVector4a*) realloc(mNormals, new_size); + + //tex coords + new_size = ((new_verts*8)+0xF) & ~0xF; + mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + + + //just clear binormals + free(mBinormals); + mBinormals = NULL; + + mPositions[mNumVertices] = pos; + mNormals[mNumVertices] = norm; + mTexCoords[mNumVertices] = tc; + + mNumVertices++; +} + +void LLVolumeFace::allocateBinormals(S32 num_verts) +{ + free(mBinormals); + mBinormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); +} + +void LLVolumeFace::allocateWeights(S32 num_verts) +{ + free(mWeights); + mWeights = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts); +} + +void LLVolumeFace::resizeIndices(S32 num_indices) +{ + free(mIndices); + + if (num_indices) + { + //pad index block end to allow for QWORD reads + S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; + + mIndices = (U16*) malloc(size); + } + else + { + mIndices = NULL; + } + + mNumIndices = num_indices; +} + +void LLVolumeFace::pushIndex(const U16& idx) +{ + S32 new_count = mNumIndices + 1; + S32 new_size = ((new_count*2)+0xF) & ~0xF; + + S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; + if (new_size != old_size) + { + mIndices = (U16*) realloc(mIndices, new_size); + } + + mIndices[mNumIndices++] = idx; +} + +void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx) +{ + resizeVertices(v.size()); + resizeIndices(idx.size()); + + for (U32 i = 0; i < v.size(); ++i) + { + mPositions[i] = v[i].getPosition(); + mNormals[i] = v[i].getNormal(); + mTexCoords[i] = v[i].mTexCoord; + } + + for (U32 i = 0; i < idx.size(); ++i) + { + mIndices[i] = idx[i]; + } +} + +void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in) +{ + U16 offset = mNumVertices; + + S32 new_count = face.mNumVertices + mNumVertices; + + if (new_count > 65536) + { + llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; + } + + if (face.mNumVertices == 0) + { + llerrs << "Cannot append empty face." << llendl; + } + + //allocate new buffer space + mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); + assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); + assert_aligned(mNormals, 16); + mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); + assert_aligned(mTexCoords, 16); + + mNumVertices = new_count; + + //get destination address of appended face + LLVector4a* dst_pos = mPositions+offset; + LLVector2* dst_tc = mTexCoords+offset; + LLVector4a* dst_norm = mNormals+offset; + + //get source addresses of appended face + const LLVector4a* src_pos = face.mPositions; + const LLVector2* src_tc = face.mTexCoords; + const LLVector4a* src_norm = face.mNormals; + + //load aligned matrices + LLMatrix4a mat, norm_mat; + mat.loadu(mat_in); + norm_mat.loadu(norm_mat_in); + + for (U32 i = 0; i < face.mNumVertices; ++i) + { + //transform appended face position and store + mat.affineTransform(src_pos[i], dst_pos[i]); + + //transform appended face normal and store + norm_mat.rotate(src_norm[i], dst_norm[i]); + dst_norm[i].normalize3fast(); + + //copy appended face texture coordinate + dst_tc[i] = src_tc[i]; + + if (offset == 0 && i == 0) + { //initialize bounding box + mExtents[0] = mExtents[1] = dst_pos[i]; + } + else + { + //stretch bounding box + update_min_max(mExtents[0], mExtents[1], dst_pos[i]); + } + } + + + new_count = mNumIndices + face.mNumIndices; + + //allocate new index buffer + mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + + //get destination address into new index buffer + U16* dst_idx = mIndices+mNumIndices; + mNumIndices = new_count; + + for (U32 i = 0; i < face.mNumIndices; ++i) + { //copy indices, offsetting by old vertex count + dst_idx[i] = face.mIndices[i]+offset; + } +} + +BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) +{ + LLMemType m1(LLMemType::MTYPE_VOLUME); + + BOOL flat = mTypeMask & FLAT_MASK; + + U8 sculpt_type = volume->getParams().getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR + + S32 num_vertices, num_indices; + + const std::vector<LLVolume::Point>& mesh = volume->getMesh(); + const std::vector<LLVector3>& profile = volume->getProfile().mProfile; + const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath; + + S32 max_s = volume->getProfile().getTotal(); + + S32 s, t, i; + F32 ss, tt; + + num_vertices = mNumS*mNumT; + num_indices = (mNumS-1)*(mNumT-1)*6; + + if (!partial_build) + { + resizeVertices(num_vertices); + resizeIndices(num_indices); + + if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + mEdge.resize(num_indices); + } + } + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector2* tc = (LLVector2*) mTexCoords; + S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); + S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; + + S32 cur_vertex = 0; + // Copy the vertices into the array + for (t = mBeginT; t < mBeginT + mNumT; t++) + { + tt = path_data[t].mTexT; + for (s = 0; s < num_s; s++) + { + if (mTypeMask & END_MASK) + { + if (s) + { + ss = 1.f; + } + else + { + ss = 0.f; + } + } + else + { + // Get s value for tex-coord. + if (!flat) + { + ss = profile[mBeginS + s].mV[2]; + } + else + { + ss = profile[mBeginS + s].mV[2] - begin_stex; + } + } + + if (sculpt_reverse_horizontal) + { + ss = 1.f - ss; + } + + // Check to see if this triangle wraps around the array. + if (mBeginS + s >= max_s) + { + // We're wrapping + i = mBeginS + s + max_s*(t-1); + } + else + { + i = mBeginS + s + max_s*t; + } + + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); + + norm[cur_vertex].clear(); + cur_vertex++; + + if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0) + { + + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); + + norm[cur_vertex].clear(); + + cur_vertex++; + } + } + + if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) + { + if (mTypeMask & OPEN_MASK) + { + s = num_s-1; + } + else + { + s = 0; + } + + i = mBeginS + s + max_s*t; + ss = profile[mBeginS + s].mV[2] - begin_stex; + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); + norm[cur_vertex].clear(); + + cur_vertex++; + } + } + + + //get bounding box for this side + LLVector4a& face_min = mExtents[0]; + LLVector4a& face_max = mExtents[1]; + mCenter->clear(); + + face_min = face_max = pos[0]; + + for (U32 i = 1; i < mNumVertices; ++i) + { + update_min_max(face_min, face_max, pos[i]); + } + + mCenter->setAdd(face_min, face_max); + mCenter->mul(0.5f); + + S32 cur_index = 0; + S32 cur_edge = 0; + BOOL flat_face = mTypeMask & FLAT_MASK; + + if (!partial_build) + { + // Now we generate the indices. + for (t = 0; t < (mNumT-1); t++) + { + for (s = 0; s < (mNumS-1); s++) + { + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + mIndices[cur_index++] = s + mNumS*(t+1); //top left + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*t; //bottom right + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face + if (t < mNumT-2) { //top right/top left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; + } + else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on T + mEdge[cur_edge++] = s*2+1; + } + if (s > 0) { //top left/bottom left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; + } + else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; + } + + if (t > 0) { //bottom left/bottom right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; + } + else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on T + mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; + } + if (s < mNumS-2) { //bottom right/top right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; + } + else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t; + } + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face + } + } + } + + //clear normals + for (U32 i = 0; i < mNumVertices; i++) + { + mNormals[i].clear(); + } + + //generate normals + for (U32 i = 0; i < mNumIndices/3; i++) //for each triangle + { + const U16* idx = &(mIndices[i*3]); + + + LLVector4a* v[] = + { pos+idx[0], pos+idx[1], pos+idx[2] }; + + LLVector4a* n[] = + { norm+idx[0], norm+idx[1], norm+idx[2] }; + + //calculate triangle normal + LLVector4a a, b, c; + + a.setSub(*v[0], *v[1]); + b.setSub(*v[0], *v[2]); + c.setCross3(a,b); + + n[0]->add(c); + n[1]->add(c); + n[2]->add(c); + + //even out quad contributions + n[i%2+1]->add(c); + } + + // adjust normals based on wrapping and stitching + + LLVector4a top; + top.setSub(pos[0], pos[mNumS*(mNumT-2)]); + BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); + + top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); + BOOL s_top_converges = (top.dot3(top) < 0.000001f); + + if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes + { + if (volume->getPath().isOpen() == FALSE) + { //wrap normals on T + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges)) + { //wrap normals on S + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && + ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) + { + if (s_bottom_converges) + { //all lower S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i].set(1,0,0); + } + } + + if (s_top_converges) + { //all upper S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i+mNumS-1].set(-1,0,0); + } + } + } + } + else // logic for sculpt volumes + { + BOOL average_poles = FALSE; + BOOL wrap_s = FALSE; + BOOL wrap_t = FALSE; + + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + average_poles = TRUE; + + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + wrap_s = TRUE; + + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + wrap_t = TRUE; + + + if (average_poles) + { + // average normals for north pole + + LLVector4a average; + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i] = average; + } + + // average normals for south pole + + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i + mNumS * (mNumT - 1)]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i + mNumS * (mNumT - 1)] = average; + } + + } + + + if (wrap_s) + { + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (wrap_t) + { + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + } + + return TRUE; +} + +// Finds binormal based on three vertices with texture coordinates. +// Fills in dummy values if the triangle has degenerate texture coordinates. +void calc_binormal_from_triangle(LLVector4a& binormal, + + const LLVector4a& pos0, + const LLVector2& tex0, + const LLVector4a& pos1, + const LLVector2& tex1, + const LLVector4a& pos2, + const LLVector2& tex2) +{ + LLVector4a rx0( pos0[VX], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rx1( pos1[VX], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rx2( pos2[VX], tex2.mV[VX], tex2.mV[VY] ); + + LLVector4a ry0( pos0[VY], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a ry1( pos1[VY], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a ry2( pos2[VY], tex2.mV[VX], tex2.mV[VY] ); + + LLVector4a rz0( pos0[VZ], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rz1( pos1[VZ], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rz2( pos2[VZ], tex2.mV[VX], tex2.mV[VY] ); + + LLVector4a lhs, rhs; + + LLVector4a r0; + lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2); + r0.setCross3(lhs, rhs); + + LLVector4a r1; + lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2); + r1.setCross3(lhs, rhs); + + LLVector4a r2; + lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2); + r2.setCross3(lhs, rhs); + + if( r0[VX] && r1[VX] && r2[VX] ) + { + binormal.set( + -r0[VZ] / r0[VX], + -r1[VZ] / r1[VX], + -r2[VZ] / r2[VX]); + // binormal.normVec(); + } + else + { + binormal.set( 0, 1 , 0 ); + } +} diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp index 8064ab217d17c7e5d8e5126cdf58491224a1f7d6..fd0dbb58fc393d621bc16a8febe031ec431783ac 100644 --- a/indra/llmath/tests/llbbox_test.cpp +++ b/indra/llmath/tests/llbbox_test.cpp @@ -34,7 +34,7 @@ #define ANGLE (3.14159265f / 2.0f) -#define APPROX_EQUAL(a, b) dist_vec((a),(b)) < 1e-5 +#define APPROX_EQUAL(a, b) (dist_vec_squared((a),(b)) < 1e-10) namespace tut { diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index aada16cc9a4dac06a0ee0b12c2bf753c119fff83..31cdb1219bd3d1235c915c5e0c5dcafc784f6d92 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -398,6 +398,12 @@ BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback, void *user_data) { + if (user_data) + { + // The *user_data should not be passed without a callback to clean it up. + llassert(callback != NULL) + } + BOOL exists = mStaticVFS->getExists(uuid, type); if (exists) { @@ -432,15 +438,26 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL llinfos << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << llendl; + if (user_data) + { + // The *user_data should not be passed without a callback to clean it up. + llassert(callback != NULL) + } + if (mShutDown) { llinfos << "ASSET_TRACE cancelled " << uuid << " type " << LLAssetType::lookup(type) << " shutting down" << llendl; - return; // don't get the asset or do any callbacks, we are shutting down + + if (callback) + { + callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE); + } + return; } - + if (uuid.isNull()) { - // Special case early out for NULL uuid + // Special case early out for NULL uuid and for shutting down if (callback) { callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID); diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 767001b6337ad05a358914ef3406331aa3effa4a..97f279268647a1e5a247fd558eba5344c803fafa 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -553,12 +553,10 @@ void LLAvatarNameCache::eraseUnrefreshed() if (!sLastExpireCheck || sLastExpireCheck < max_unrefreshed) { sLastExpireCheck = now; - cache_t::iterator it = sCache.begin(); - while (it != sCache.end()) + + for (cache_t::iterator it = sCache.begin(); it != sCache.end();) { - cache_t::iterator cur = it; - ++it; - const LLAvatarName& av_name = cur->second; + const LLAvatarName& av_name = it->second; if (av_name.mExpires < max_unrefreshed) { const LLUUID& agent_id = it->first; @@ -566,8 +564,12 @@ void LLAvatarNameCache::eraseUnrefreshed() << " user '" << av_name.mUsername << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; - sCache.erase(cur); + sCache.erase(it++); } + else + { + ++it; + } } LL_INFOS("AvNameCache") << sCache.size() << " cached avatar names" << LL_ENDL; } diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index c48e2bb5fad36417c88ab61e8ee601aa578f883e..d8140a124db1d5a02b3cf07518d07031ce2896ff 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -840,18 +840,18 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); //GL_NVX_gpu_memory_info constants #ifndef GL_NVX_gpu_memory_info #define GL_NVX_gpu_memory_info -#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 -#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 -#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 -#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A #define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B #endif //GL_ATI_meminfo constants #ifndef GL_ATI_meminfo #define GL_ATI_meminfo -#define GL_VBO_FREE_MEMORY_ATI 0x87FB -#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC #define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD #endif diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 7b29d92ea050eeb9523861dc515332eeb86c5185..c4eec1835cdce8178eea2c1acd5d8121be1f92ea 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -39,56 +39,24 @@ //static LLDefaultChildRegistry::Register<LLLoadingIndicator> r("loading_indicator"); /////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator::Data class +// LLLoadingIndicator class /////////////////////////////////////////////////////////////////////////////// -/** - * Pre-loaded images shared by all instances of the widget - */ -class LLLoadingIndicator::Data: public LLSingleton<LLLoadingIndicator::Data> +LLLoadingIndicator::LLLoadingIndicator(const Params& p) +: LLUICtrl(p), + mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f), + mCurImageIdx(0) { -public: - /*virtual*/ void initSingleton(); // from LLSingleton - - LLPointer<LLUIImage> getNextImage(S8& idx) const; - U8 getImagesCount() const { return NIMAGES; } -private: - - static const U8 NIMAGES = 12; - LLPointer<LLUIImage> mImages[NIMAGES]; -}; +} -// virtual -// Called right after the instance gets constructed. -void LLLoadingIndicator::Data::initSingleton() +void LLLoadingIndicator::initFromParams(const Params& p) { - // Load images. - for (U8 i = 0; i < NIMAGES; ++i) + for (LLInitParam::ParamIterator<LLUIImage*>::const_iterator it = p.images().image.begin(), end_it = p.images().image.end(); + it != end_it; + ++it) { - std::string img_name = llformat("Progress_%d", i+1); - mImages[i] = LLUI::getUIImage(img_name, 0); - llassert(mImages[i]); + mImages.push_back(it->getValue()); } -} - -LLPointer<LLUIImage> LLLoadingIndicator::Data::getNextImage(S8& idx) const -{ - // Calculate next index, performing array bounds checking. - idx = (idx >= NIMAGES || idx < 0) ? 0 : (idx + 1) % NIMAGES; - return mImages[idx]; -} - -/////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator class -/////////////////////////////////////////////////////////////////////////////// - -LLLoadingIndicator::LLLoadingIndicator(const Params& p) -: LLUICtrl(p) - , mRotationsPerSec(p.rotations_per_sec > 0 ? p.rotations_per_sec : 1.0f) - , mCurImageIdx(-1) -{ - // Select initial image. - mCurImagep = Data::instance().getNextImage(mCurImageIdx); // Start timer for switching images. start(); @@ -100,16 +68,21 @@ void LLLoadingIndicator::draw() if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired()) { // Switch to the next image. - mCurImagep = Data::instance().getNextImage(mCurImageIdx); + if (!mImages.empty()) + { + mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); + } // Restart timer. start(); } + LLUIImagePtr cur_image = mImages.empty() ? LLUIImagePtr(NULL) : mImages[mCurImageIdx]; + // Draw current image. - if( mCurImagep.notNull() ) + if( cur_image.notNull() ) { - mCurImagep->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); + cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); } LLUICtrl::draw(); @@ -123,6 +96,6 @@ void LLLoadingIndicator::stop() void LLLoadingIndicator::start() { mImageSwitchTimer.start(); - F32 period = 1.0f / (Data::instance().getImagesCount() * mRotationsPerSec); + F32 period = 1.0f / (mImages.size() * mImagesPerSec); mImageSwitchTimer.setTimerExpirySec(period); } diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index 4e4a224ef6e70a450332953bdc7420cf1137c0e0..c0cb1cc74a9df96fc06566a07648e17c6e6cad24 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -36,8 +36,8 @@ /** * Perpetual loading indicator (a la MacOSX or YouTube) * - * Number of rotations per second can be overriden - * with the "roations_per_sec" parameter. + * Number of rotations per second can be overridden + * with the "images_per_sec" parameter. * * Can start/stop spinning. * @@ -49,11 +49,24 @@ class LLLoadingIndicator { LOG_CLASS(LLLoadingIndicator); public: + + struct Images : public LLInitParam::Block<Images> + { + Multiple<LLUIImage*> image; + + Images() + : image("image") + {} + }; + struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<F32> rotations_per_sec; + Optional<F32> images_per_sec; + Batch<Images> images; + Params() - : rotations_per_sec("rotations_per_sec", 1.0f) + : images_per_sec("images_per_sec", 1.0f), + images("images") {} }; @@ -74,14 +87,15 @@ class LLLoadingIndicator private: LLLoadingIndicator(const Params&); - friend class LLUICtrlFactory; + void initFromParams(const Params&); - class Data; + friend class LLUICtrlFactory; - F32 mRotationsPerSec; + F32 mImagesPerSec; S8 mCurImageIdx; - LLPointer<LLUIImage> mCurImagep; LLFrameTimer mImageSwitchTimer; + + std::vector<LLUIImagePtr> mImages; }; #endif // LL_LLLOADINGINDICATOR_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2060e5f9cf94a7245993bba2bde29a280c811b50..1c19a33c4edfee94763a4932be4db9c321bc59aa 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2021,11 +2021,10 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, pos = segment_line_start + offset; break; } - else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1) + else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd) { // segment wraps to next line, so just set doc pos to the end of the line - // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd) - pos = llmin(getLength(), line_iter->mDocIndexEnd); + pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength()); break; } start_x += text_width; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 5a46c7c98e0721d1178f73da7a02241c58de492e..9bd445988d559ad6d3ebfccc00833860c00ebdbf 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -592,6 +592,10 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) } } + // Disabling parsing on the fly to avoid updating text segments + // until all indentation commands are executed. + mParseOnTheFly = FALSE; + // Find each start-of-line and indent it do { @@ -617,6 +621,8 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) } while( cur < right ); + mParseOnTheFly = TRUE; + if( (right < getLength()) && (text[right] == '\n') ) { right++; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 87669574c2543860de653344ef14484115fcb17e..8020ca802bd2df162653bc2acd89318fd088c58a 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1626,8 +1626,8 @@ void LLUI::cleanupClass() { if(sImageProvider) { - sImageProvider->cleanUp(); - } + sImageProvider->cleanUp(); +} } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) @@ -2074,32 +2074,32 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path) namespace LLInitParam { - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color), red("red"), green("green"), blue("blue"), alpha("alpha"), control("") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() { if (control.isProvided()) { - mData.mValue = LLUIColorTable::instance().getColor(control); + updateValue(LLUIColorTable::instance().getColor(control)); } else { - mData.mValue = LLColor4(red, green, blue, alpha); + updateValue(LLColor4(red, green, blue, alpha)); } } - void TypedParam<LLUIColor>::setBlockFromValue() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() { - LLColor4 color = mData.mValue.get(); + LLColor4 color = getValue(); red.set(color.mV[VRED], false); green.set(color.mV[VGREEN], false); blue.set(color.mV[VBLUE], false); @@ -2107,38 +2107,32 @@ namespace LLInitParam control.set("", false); } - void TypeValues<LLUIColor>::declareValues() - { - declare("white", LLColor4::white); - declare("black", LLColor4::black); - declare("red", LLColor4::red); - declare("green", LLColor4::green); - declare("blue", LLColor4::blue); - } - bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) { return !(a->getFontDesc() < b->getFontDesc()) && !(b->getFontDesc() < a->getFontDesc()); } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count), + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp), name("name"), size("size"), style("style") { - setBlockFromValue(); + if (!fontp) + { + updateValue(LLFontGL::getFontDefault()); + } addSynonym(name, ""); - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() { const LLFontGL* res_fontp = LLFontGL::getFontByName(name); if (res_fontp) { - mData.mValue = res_fontp; + updateValue(res_fontp); return; } @@ -2148,22 +2142,26 @@ namespace LLInitParam const LLFontGL* fontp = LLFontGL::getFont(desc); if (fontp) { - mData.mValue = fontp; - } + updateValue(fontp); + } + else + { + updateValue(LLFontGL::getFontDefault()); + } } - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() { - if (mData.mValue) + if (getValue()) { - name.set(LLFontGL::nameFromFont(mData.mValue), false); - size.set(LLFontGL::sizeFromFont(mData.mValue), false); - style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false); + name.set(LLFontGL::nameFromFont(getValue()), false); + size.set(LLFontGL::sizeFromFont(getValue()), false); + style.set(LLFontGL::getStringFromStyle(getValue()->getFontDesc().getStyle()), false); } } - TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) + : super_t(rect), left("left"), top("top"), right("right"), @@ -2171,10 +2169,10 @@ namespace LLInitParam width("width"), height("height") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLRect>::setValueFromBlock() const + void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock() { LLRect rect; @@ -2235,40 +2233,41 @@ namespace LLInitParam rect.mBottom = bottom; rect.mTop = top; } - mData.mValue = rect; + updateValue(rect); } - void TypedParam<LLRect>::setBlockFromValue() + void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue() { // because of the ambiguity in specifying a rect by position and/or dimensions // we clear the "provided" flag so that values from xui/etc have priority // over those calculated from the rect object - left.set(mData.mValue.mLeft, false); - right.set(mData.mValue.mRight, false); - bottom.set(mData.mValue.mBottom, false); - top.set(mData.mValue.mTop, false); - width.set(mData.mValue.getWidth(), false); - height.set(mData.mValue.getHeight(), false); + LLRect& value = getValue(); + left.set(value.mLeft, false); + right.set(value.mRight, false); + bottom.set(value.mBottom, false); + top.set(value.mTop, false); + width.set(value.getWidth(), false); + height.set(value.getHeight(), false); } - TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) + : super_t(coord), x("x"), y("y") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLCoordGL>::setValueFromBlock() const + void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock() { - mData.mValue.set(x, y); + updateValue(LLCoordGL(x, y)); } - void TypedParam<LLCoordGL>::setBlockFromValue() + void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue() { - x.set(mData.mValue.mX, false); - y.set(mData.mValue.mY, false); + x.set(getValue().mX, false); + y.set(getValue().mY, false); } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 50cb9e663200f91c5b50ed2fc8f559c273c3b236..6a43477693b0f54b488ec8e0b1c0af75f4308faa 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -398,10 +398,10 @@ class LLUICachedControl : public LLCachedControl<T> namespace LLInitParam { template<> - class TypedParam<LLRect> - : public BlockValue<LLRect> + class ParamValue<LLRect, TypeValues<LLRect> > + : public CustomParamValue<LLRect> { - typedef BlockValue<LLRect> super_t; + typedef CustomParamValue<LLRect> super_t; public: Optional<S32> left, top, @@ -410,62 +410,43 @@ namespace LLInitParam width, height; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); + ParamValue(const LLRect& value); - void setValueFromBlock() const; - void setBlockFromValue(); + void updateValueFromBlock(); + void updateBlockFromValue(); }; template<> - struct TypeValues<LLUIColor> : public TypeValuesHelper<LLUIColor> + class ParamValue<LLUIColor, TypeValues<LLUIColor> > + : public CustomParamValue<LLUIColor> { - static void declareValues(); - }; + typedef CustomParamValue<LLUIColor> super_t; - template<> - class TypedParam<LLUIColor> - : public BlockValue<LLUIColor> - { - typedef BlockValue<LLUIColor> super_t; public: - Optional<F32> red, - green, - blue, - alpha; - Optional<std::string> control; - - TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + Optional<F32> red, + green, + blue, + alpha; + Optional<std::string> control; + + ParamValue(const LLUIColor& color); + void updateValueFromBlock(); + void updateBlockFromValue(); }; - // provide a better default for Optional<const LLFontGL*> than NULL - template <> - struct DefaultInitializer<const LLFontGL*> - { - // return reference to a single default instance of T - // built-in types will be initialized to zero, default constructor otherwise - static const LLFontGL* get() - { - static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault(); - return sDefaultFont; - } - }; - - template<> - class TypedParam<const LLFontGL*> - : public BlockValue<const LLFontGL*> + class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> > + : public CustomParamValue<const LLFontGL* > { - typedef BlockValue<const LLFontGL*> super_t; + typedef CustomParamValue<const LLFontGL*> super_t; public: Optional<std::string> name, size, style; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + ParamValue(const LLFontGL* value); + void updateValueFromBlock(); + void updateBlockFromValue(); }; template<> @@ -494,17 +475,17 @@ namespace LLInitParam template<> - class TypedParam<LLCoordGL> - : public BlockValue<LLCoordGL> + class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > + : public CustomParamValue<LLCoordGL> { - typedef BlockValue<LLCoordGL> super_t; + typedef CustomParamValue<LLCoordGL> super_t; public: Optional<S32> x, y; - TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + ParamValue(const LLCoordGL& val); + void updateValueFromBlock(); + void updateBlockFromValue(); }; } diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1ffad4806e3bf5913c83d526998bc11d56f3fa55..f37947a50b6774a7f12b36d3acd124e04d38eda5 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -155,32 +155,32 @@ void LLUIImage::onImageLoaded() namespace LLInitParam { - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() { // The keyword "none" is specifically requesting a null image // do not default to current value. Used to overwrite template images. if (name() == "none") { - mData.mValue = NULL; + updateValue(NULL); return; } LLUIImage* imagep = LLUI::getUIImage(name()); if (imagep) { - mData.mValue = imagep; + updateValue(imagep); } } - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() { - if (mData.mValue == NULL) + if (getValue() == NULL) { name.set("none", false); } else { - name.set(mData.mValue->getName(), false); + name.set(getValue()->getName(), false); } } diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index 38107c112d71edfcccf3e0f6d2386938dd32082a..139d88e0ac65f51c11237a1a127c989998a278ea 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -92,22 +92,23 @@ class LLUIImage : public LLRefCount namespace LLInitParam { template<> - class TypedParam<LLUIImage*, TypeValues<LLUIImage*>, false> - : public BlockValue<LLUIImage*> + class ParamValue<LLUIImage*, TypeValues<LLUIImage*> > + : public CustomParamValue<LLUIImage*> { typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref; - typedef BlockValue<LLUIImage*> super_t; + typedef CustomParamValue<LLUIImage*> super_t; public: Optional<std::string> name; - TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue(LLUIImage* const& image) + : super_t(image) { - setBlockFromValue(); + updateBlockFromValue(); + addSynonym(name, "name"); } - void setValueFromBlock() const; - void setBlockFromValue(); + void updateValueFromBlock(); + void updateBlockFromValue(); }; // Need custom comparison function for our test app, which only loads diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index ac2412c928bd59b11b89cac0df1407b0d6ed036b..26b3b17577b6549e34d7fbc0d4840e005eac8d28 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -114,32 +114,30 @@ namespace LLInitParam const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); mEnclosingBlockOffset = (U16)(my_addr - block_addr); } - void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} + void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {} - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} + void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} + void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) { descriptor.mCurrentBlockPtr = this; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; } - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } - bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; } + void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {} + bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; } + bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color) {} - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() {} - void TypedParam<LLUIColor>::setBlockFromValue() - {} - - void TypeValues<LLUIColor>::declareValues() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -147,14 +145,14 @@ namespace LLInitParam return false; } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count) + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp) {} - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() {} - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -166,10 +164,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() {} - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() {} diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 8f0a48018fb26132f0ca1b5257a1110850dce4d3..2f814f4200cad8bcc9b5a53b017656579a77668f 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -70,6 +70,22 @@ S32 LLUIImage::getHeight() const return 0; } +namespace LLInitParam +{ + S32 Parser::sNextParseGeneration = 0; + BlockDescriptor::BlockDescriptor() {} + ParamDescriptor::ParamDescriptor(param_handle_t p, + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count){} + ParamDescriptor::~ParamDescriptor() {} + +} + namespace tut { struct LLUrlEntryData diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index fdaab00f18bfc9787fecf42c4de5d76e1c2c137a..e09ef33d4911d8e5bca022eabbcead4e4f1baac7 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -66,11 +66,25 @@ namespace LLInitParam BaseBlock::BaseBlock() {} BaseBlock::~BaseBlock() {} - void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} + S32 Parser::sNextParseGeneration = 0; + + BlockDescriptor::BlockDescriptor() {} + ParamDescriptor::ParamDescriptor(param_handle_t p, + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count){} + ParamDescriptor::~ParamDescriptor() {} + + void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {} + + void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} - + void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} + void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) { descriptor.mCurrentBlockPtr = this; @@ -84,23 +98,20 @@ namespace LLInitParam mEnclosingBlockOffset = (U16)(my_addr - block_addr); } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; } - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } - bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; } + void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {} + bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; } + bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color) {} - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() {} - void TypedParam<LLUIColor>::setBlockFromValue() - {} - - void TypeValues<LLUIColor>::declareValues() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -108,14 +119,15 @@ namespace LLInitParam return false; } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count) + + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp) {} - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() {} - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -127,10 +139,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() {} - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() {} bool ParamCompare<LLUIImage*, false>::equals( diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 73f2336f94fa70bf2d43bc6b924ed6262b7bd2e8..72b54f538083c5937012865572526c1b8afca0b6 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -93,11 +93,11 @@ LLDir_Linux::LLDir_Linux() #else mAppRODataDir = tmp_str; #endif - std::string::size_type indra_pos = mExecutableDir.find("/indra"); - if (indra_pos != std::string::npos) + std::string::size_type build_dir_pos = mExecutableDir.rfind("/build-linux-"); + if (build_dir_pos != std::string::npos) { // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, indra_pos) + "/indra/newview/skins"; + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; llinfos << "Running in dev checkout with mSkinBaseDir " << mSkinBaseDir << llendl; } diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 445285aa43ac2c5dae2c11187e73280dc88614db..f9369b043eb47e4583dd88af6c737871f9bf9bea 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -150,11 +150,11 @@ LLDir_Mac::LLDir_Mac() CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true); - U32 indra_pos = mExecutableDir.find("/indra"); - if (indra_pos != std::string::npos) + U32 build_dir_pos = mExecutableDir.rfind("/build-darwin-"); + if (build_dir_pos != std::string::npos) { // ...we're in a dev checkout - mSkinBaseDir = mExecutableDir.substr(0, indra_pos) + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; llinfos << "Running in dev checkout with mSkinBaseDir " << mSkinBaseDir << llendl; diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index fcdbaa430973d93b62eda9283ee7f99f835c4246..b3312798dddc283e6c000e8a3ed05be928d6afdb 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -43,9 +43,52 @@ namespace LLInitParam mEnclosingBlockOffset = (U16)(my_addr - block_addr); } + // + // ParamDescriptor + // + ParamDescriptor::ParamDescriptor(param_handle_t p, + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count) + : mParamHandle(p), + mMergeFunc(merge_func), + mDeserializeFunc(deserialize_func), + mSerializeFunc(serialize_func), + mValidationFunc(validation_func), + mInspectFunc(inspect_func), + mMinCount(min_count), + mMaxCount(max_count), + mGeneration(0), + mUserData(NULL) + {} + + ParamDescriptor::ParamDescriptor() + : mParamHandle(0), + mMergeFunc(NULL), + mDeserializeFunc(NULL), + mSerializeFunc(NULL), + mValidationFunc(NULL), + mInspectFunc(NULL), + mMinCount(0), + mMaxCount(0), + mGeneration(0), + mUserData(NULL) + {} + + ParamDescriptor::~ParamDescriptor() + { + delete mUserData; + } + // // Parser // + S32 Parser::sNextParseGeneration = 0; + Parser::~Parser() {} @@ -73,6 +116,12 @@ namespace LLInitParam std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); } + BlockDescriptor::BlockDescriptor() + : mMaxParamOffset(0), + mInitializationState(UNINITIALIZED), + mCurrentBlockPtr(NULL) + {} + // // BaseBlock // @@ -115,7 +164,7 @@ namespace LLInitParam bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent) { - if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()))) + if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), -1)) { if (!silent) { @@ -145,7 +194,7 @@ namespace LLInitParam return true; } - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const + void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit @@ -212,11 +261,9 @@ namespace LLInitParam name_stack.pop_back(); } } - - return true; } - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const + bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit @@ -273,11 +320,13 @@ namespace LLInitParam return true; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack) + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 parent_generation) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); bool names_left = name_stack.first != name_stack.second; + S32 parse_generation = name_stack.first == name_stack.second ? -1 : name_stack.first->second; + if (names_left) { const std::string& top_name = name_stack.first->first; @@ -294,7 +343,7 @@ namespace LLInitParam Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second); ++new_name_stack.first; - return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second); + return deserialize_func(*paramp, p, new_name_stack, parse_generation); } } @@ -306,7 +355,7 @@ namespace LLInitParam Param* paramp = getParamFromHandle((*it)->mParamHandle); ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc; - if (deserialize_func && deserialize_func(*paramp, p, name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second)) + if (deserialize_func && deserialize_func(*paramp, p, name_stack, parse_generation)) { return true; } @@ -324,32 +373,32 @@ namespace LLInitParam } //static - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name) + void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) { - // create a copy of the paramdescriptor in allparams + // create a copy of the param descriptor in mAllParams // so other data structures can store a pointer to it block_data.mAllParams.push_back(in_param); - ParamDescriptor& param(block_data.mAllParams.back()); + ParamDescriptorPtr param(block_data.mAllParams.back()); std::string name(char_name); - if ((size_t)param.mParamHandle > block_data.mMaxParamOffset) + if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) { llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; } if (name.empty()) { - block_data.mUnnamedParams.push_back(¶m); + block_data.mUnnamedParams.push_back(param); } else { // don't use insert, since we want to overwrite existing entries - block_data.mNamedParams[name] = ¶m; + block_data.mNamedParams[name] = param; } - if (param.mValidationFunc) + if (param->mValidationFunc) { - block_data.mValidationList.push_back(std::make_pair(param.mParamHandle, param.mValidationFunc)); + block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); } } @@ -367,7 +416,7 @@ namespace LLInitParam llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; } - ParamDescriptor* param_descriptor = findParamDescriptor(handle); + ParamDescriptorPtr param_descriptor = findParamDescriptor(param); if (param_descriptor) { if (synonym.empty()) @@ -382,7 +431,7 @@ namespace LLInitParam } } - void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) + void BaseBlock::paramChanged(const Param& changed_param, bool user_provided) { if (user_provided) { @@ -404,22 +453,23 @@ namespace LLInitParam return LLStringUtil::null; } - ParamDescriptor* BaseBlock::findParamDescriptor(param_handle_t handle) + ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param) { + param_handle_t handle = getHandleFromParam(¶m); BlockDescriptor& descriptor = mostDerivedBlockDescriptor(); BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end(); for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin(); it != end_it; ++it) { - if (it->mParamHandle == handle) return &(*it); + if ((*it)->mParamHandle == handle) return *it; } - return NULL; + return ParamDescriptorPtr(); } // take all provided params from other and apply to self // NOTE: this requires that "other" is of the same derived type as this - bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { bool some_param_changed = false; BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end(); @@ -427,19 +477,14 @@ namespace LLInitParam it != end_it; ++it) { - const Param* other_paramp = other.getParamFromHandle(it->mParamHandle); - ParamDescriptor::merge_func_t merge_func = it->mMergeFunc; + const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle); + ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc; if (merge_func) { - Param* paramp = getParamFromHandle(it->mParamHandle); + Param* paramp = getParamFromHandle((*it)->mParamHandle); some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); } } return some_param_changed; } - - bool ParamCompare<LLSD, false>::equals(const LLSD &a, const LLSD &b) - { - return false; - } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 1f9045754a9c8b32d698ff6dd6a57f33edbb5575..a853999e9456d7112d2dcf7ab94191ccf020a803 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1,5 +1,5 @@ /** -f * @file llinitparam.h + * @file llinitparam.h * @brief parameter block abstraction for creating complex objects and * parsing construction parameters from xml and LLSD * @@ -29,18 +29,14 @@ f * @file llinitparam.h #define LL_LLPARAM_H #include <vector> - -#include <stddef.h> #include <boost/function.hpp> -#include <boost/bind.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/unordered_map.hpp> -#include "llregistry.h" -#include "llmemory.h" - +#include <boost/shared_ptr.hpp> namespace LLInitParam { + template<typename T> const T& defaultValue() { static T value; return value; } template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value > struct ParamCompare @@ -61,122 +57,119 @@ namespace LLInitParam } }; - // default constructor adaptor for InitParam Values - // constructs default instances of the given type, returned by const reference - template <typename T> - struct DefaultInitializer + template<> + struct ParamCompare<LLSD, false> { - typedef const T& T_const_ref; - // return reference to a single default instance of T - // built-in types will be initialized to zero, default constructor otherwise - static T_const_ref get() { static T t = T(); return t; } + static bool equals(const LLSD &a, const LLSD &b) { return false; } }; // helper functions and classes typedef ptrdiff_t param_handle_t; + // empty default implementation of key cache + // leverages empty base class optimization template <typename T> class TypeValues { public: - // empty default implemenation of key cache - class KeyCache + typedef std::map<std::string, T> value_name_map_t; + + void setValueName(const std::string& key) {} + std::string getValueName() const { return ""; } + void clearValueName() const {} + + static bool getValueFromName(const std::string& name, T& value) { - public: - void setKey(const std::string& key) {} - std::string getKey() const { return ""; } - void clearKey(){} - }; + return false; + } - static bool get(const std::string& name, T& value) + static bool valueNamesExist() { return false; } - static bool empty() + static std::vector<std::string>* getPossibleValues() { - return true; + return NULL; } - static std::vector<std::string>* getPossibleValues() { return NULL; } + static value_name_map_t* getValueNames() {return NULL;} }; template <typename T, typename DERIVED_TYPE = TypeValues<T> > class TypeValuesHelper - : public LLRegistrySingleton<std::string, T, DERIVED_TYPE > { - typedef LLRegistrySingleton<std::string, T, DERIVED_TYPE> super_t; - typedef LLSingleton<DERIVED_TYPE> singleton_t; public: + typedef typename std::map<std::string, T> value_name_map_t; //TODO: cache key by index to save on param block size - class KeyCache + void setValueName(const std::string& value_name) { - public: - void setKey(const std::string& key) - { - mKey = key; - } - - void clearKey() - { - mKey = ""; - } + mValueName = value_name; + } - std::string getKey() const - { - return mKey; - } + std::string getValueName() const + { + return mValueName; + } - private: - std::string mKey; - }; + void clearValueName() const + { + mValueName.clear(); + } - static bool get(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, T& value) { - if (!singleton_t::instance().exists(name)) return false; + value_name_map_t* map = getValueNames(); + typename value_name_map_t::iterator found_it = map->find(name); + if (found_it == map->end()) return false; - value = *singleton_t::instance().getValue(name); + value = found_it->second; return true; } - static bool empty() + static bool valueNamesExist() { - return singleton_t::instance().LLRegistry<std::string, T>::empty(); + return !getValueNames()->empty(); } - //override this to add name value pairs - static void declareValues() {} - - void initSingleton() + static value_name_map_t* getValueNames() { - DERIVED_TYPE::declareValues(); - } + static value_name_map_t sMap; + static bool sInitialized = false; - static const std::vector<std::string>* getPossibleValues() - { - // in order to return a pointer to a member, we lazily - // evaluate the result and store it in mValues here - if (singleton_t::instance().mValues.empty()) + if (!sInitialized) { - typename super_t::Registrar::registry_map_t::const_iterator it; - for (it = super_t::defaultRegistrar().beginItems(); it != super_t::defaultRegistrar().endItems(); ++it) - { - singleton_t::instance().mValues.push_back(it->first); - } + sInitialized = true; + DERIVED_TYPE::declareValues(); } - return &singleton_t::instance().mValues; + return &sMap; } + static std::vector<std::string>* getPossibleValues() + { + static std::vector<std::string> sValues; + + value_name_map_t* map = getValueNames(); + for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); + it != end_it; + ++it) + { + sValues.push_back(it->first); + } + return &sValues; + } - protected: static void declare(const std::string& name, const T& value) { - super_t::defaultRegistrar().add(name, value); + (*getValueNames())[name] = value; } - private: - std::vector<std::string> mValues; + protected: + static void getName(const std::string& name, const T& value) + {} + + mutable std::string mValueName; }; class Parser @@ -193,9 +186,9 @@ namespace LLInitParam } }; - typedef std::vector<std::pair<std::string, S32> > name_stack_t; + typedef std::vector<std::pair<std::string, S32> > name_stack_t; typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator> name_stack_range_t; - typedef std::vector<std::string> possible_values_t; + typedef std::vector<std::string> possible_values_t; typedef bool (*parser_read_func_t)(Parser& parser, void* output); typedef bool (*parser_write_func_t)(Parser& parser, const void*, const name_stack_t&); @@ -207,7 +200,7 @@ namespace LLInitParam Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) : mParseSilently(false), - mParseGeneration(0), + mParseGeneration(sNextParseGeneration), mParserReadFuncs(&read_map), mParserWriteFuncs(&write_map), mParserInspectFuncs(&inspect_map) @@ -252,7 +245,7 @@ namespace LLInitParam void setParseSilently(bool silent) { mParseSilently = silent; } S32 getParseGeneration() { return mParseGeneration; } - S32 newParseGeneration() { return ++mParseGeneration; } + S32 newParseGeneration() { return mParseGeneration = ++sNextParseGeneration; } protected: @@ -276,6 +269,8 @@ namespace LLInitParam parser_write_func_map_t* mParserWriteFuncs; parser_inspect_func_map_t* mParserInspectFuncs; S32 mParseGeneration; + + static S32 sNextParseGeneration; }; // used to indicate no matching value to a given name when parsing @@ -295,12 +290,13 @@ namespace LLInitParam Param(class BaseBlock* enclosing_block); // store pointer to enclosing block as offset to reduce space and allow for quick copying - BaseBlock& enclosingBlock() const + class BaseBlock& enclosingBlock() const { const U8* my_addr = reinterpret_cast<const U8*>(this); // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class - return *const_cast<BaseBlock*>( - reinterpret_cast<const BaseBlock*>(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); + return *const_cast<class BaseBlock*> + (reinterpret_cast<const class BaseBlock*> + (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); } private: @@ -313,7 +309,11 @@ namespace LLInitParam // various callbacks and constraints associated with an individual param struct ParamDescriptor { - public: + struct UserData + { + virtual ~UserData() {} + }; + typedef bool(*merge_func_t)(Param&, const Param&, bool); typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, S32); typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); @@ -321,40 +321,18 @@ namespace LLInitParam typedef bool(*validation_func_t)(const Param*); ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count) - : mParamHandle(p), - mMergeFunc(merge_func), - mDeserializeFunc(deserialize_func), - mSerializeFunc(serialize_func), - mValidationFunc(validation_func), - mInspectFunc(inspect_func), - mMinCount(min_count), - mMaxCount(max_count), - mGeneration(0), - mNumRefs(0) - {} + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count); - ParamDescriptor() - : mParamHandle(0), - mMergeFunc(NULL), - mDeserializeFunc(NULL), - mSerializeFunc(NULL), - mValidationFunc(NULL), - mInspectFunc(NULL), - mMinCount(0), - mMaxCount(0), - mGeneration(0), - mNumRefs(0) - {} + ParamDescriptor(); + ~ParamDescriptor(); param_handle_t mParamHandle; - merge_func_t mMergeFunc; deserialize_func_t mDeserializeFunc; serialize_func_t mSerializeFunc; @@ -364,17 +342,16 @@ namespace LLInitParam S32 mMaxCount; S32 mGeneration; S32 mNumRefs; + UserData* mUserData; }; + typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; + // each derived Block class keeps a static data structure maintaining offsets to various params class BlockDescriptor { public: - BlockDescriptor() - : mMaxParamOffset(0), - mInitializationState(UNINITIALIZED), - mCurrentBlockPtr(NULL) - {} + BlockDescriptor(); typedef enum e_initialization_state { @@ -385,12 +362,10 @@ namespace LLInitParam void aggregateBlockData(BlockDescriptor& src_block_data); - public: - typedef boost::unordered_map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams - typedef std::vector<ParamDescriptor*> param_list_t; - - typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams - typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t; + typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t; + typedef std::vector<ParamDescriptorPtr> param_list_t; + typedef std::list<ParamDescriptorPtr> all_params_list_t; + typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t; param_map_t mNamedParams; // parameters with associated names param_list_t mUnnamedParams; // parameters with_out_ associated names @@ -456,6 +431,7 @@ namespace LLInitParam Param* getParamFromHandle(const param_handle_t param_handle) { if (param_handle == 0) return NULL; + U8* baseblock_address = reinterpret_cast<U8*>(this); return reinterpret_cast<Param*>(baseblock_address + param_handle); } @@ -469,14 +445,13 @@ namespace LLInitParam void addSynonym(Param& param, const std::string& synonym); // Blocks can override this to do custom tracking of changes - virtual void setLastChangedParam(const Param& last_param, bool user_provided); + virtual void paramChanged(const Param& changed_param, bool user_provided); S32 getLastChangeVersion() const { return mChangeVersion; } - bool isDefault() const { return mChangeVersion == 0; } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack); - bool serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const; - bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t()) const; + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation); + void serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const; + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } @@ -493,13 +468,20 @@ namespace LLInitParam return false; } - static void addParam(BlockDescriptor& block_data, const ParamDescriptor& param, const char* name); + static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); + + ParamDescriptorPtr findParamDescriptor(const Param& param); + protected: void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); + bool mergeBlockParam(bool param_provided, BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + { + return mergeBlock(block_data, other, overwrite); + } // take all provided params from other and apply to self - bool merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); // can be updated in getters mutable S32 mChangeVersion; @@ -512,63 +494,133 @@ namespace LLInitParam private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; - ParamDescriptor* findParamDescriptor(param_handle_t handle); - }; - - - template<typename T> - struct ParamIterator - { - typedef typename std::vector<T>::const_iterator const_iterator; - typedef typename std::vector<T>::iterator iterator; }; // these templates allow us to distinguish between template parameters // that derive from BaseBlock and those that don't - // this is supposedly faster than boost::is_convertible and its ilk template<typename T, typename Void = void> - struct IsBaseBlock + struct IsBlock { static const bool value = false; }; template<typename T> - struct IsBaseBlock<T, typename T::baseblock_base_class_t> + struct IsBlock<T, typename T::baseblock_base_class_t> { static const bool value = true; }; + template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> + class ParamValue : public NAME_VALUE_LOOKUP + { + public: + typedef const T& value_assignment_t; + + ParamValue(): mValue() {} + ParamValue(const T& other) : mValue(other) {} + + void setValue(value_assignment_t val) + { + mValue = val; + } + + value_assignment_t getValue() const + { + return mValue; + } + + T& getValue() + { + return mValue; + } + + private: + T mValue; + }; + + template<typename T, typename NAME_VALUE_LOOKUP> + class ParamValue<T, NAME_VALUE_LOOKUP, true> + : public T, + public NAME_VALUE_LOOKUP + { + public: + typedef const T& value_assignment_t; + + S32 mKeyVersion; + mutable S32 mValidatedVersion; + mutable bool mValidated; // lazy validation flag + + ParamValue() + : T(), + mKeyVersion(0), + mValidatedVersion(-1), + mValidated(false) + {} + + ParamValue(const T& other) + : T(other), + mKeyVersion(0), + mValidatedVersion(-1), + mValidated(false) + { + } + + void setValue(value_assignment_t val) + { + *this = val; + } + + value_assignment_t getValue() const + { + return *this; + } + + T& getValue() + { + return *this; + } + }; + + template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + struct ParamIterator + { + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator const_iterator; + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator iterator; + }; + // specialize for custom parsing/decomposition of specific classes // e.g. TypedParam<LLRect> has left, top, right, bottom, etc... template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBaseBlock<T>::value> + bool VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> class TypedParam - : public Param + : public Param, + public ParamValue<T, NAME_VALUE_LOOKUP> { public: - typedef const T& value_const_ref_t; - typedef value_const_ref_t value_assignment_t; - typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t; + typedef const T& value_assignment_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), &mergeWith, &deserializeParam, &serializeParam, validate_func, &inspectParam, - min_count, max_count); + min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } - mData.mValue = value; + setValue(value); } bool isProvided() const { return Param::anyProvided(); } @@ -579,27 +631,27 @@ namespace LLInitParam // no further names in stack, attempt to parse value now if (name_stack.first == name_stack.second) { - if (parser.readValue(typed_param.mData.mValue)) + if (parser.readValue(typed_param.getValue())) { - typed_param.mData.clearKey(); + typed_param.clearValueName(); typed_param.setProvided(true); - typed_param.enclosingBlock().setLastChangedParam(param, true); + typed_param.enclosingBlock().paramChanged(param, true); return true; } // try to parse a known named value - if(!NAME_VALUE_LOOKUP::empty()) + if(name_value_lookup_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (NAME_VALUE_LOOKUP::get(name, typed_param.mData.mValue)) + if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) { - typed_param.mData.setKey(name); + typed_param.setValueName(name); typed_param.setProvided(true); - typed_param.enclosingBlock().setLastChangedParam(param, true); + typed_param.enclosingBlock().paramChanged(param, true); return true; } @@ -619,13 +671,13 @@ namespace LLInitParam name_stack.back().second = parser.newParseGeneration(); } - std::string key = typed_param.mData.getKey(); + std::string key = typed_param.getValueName(); // first try to write out name of name/value pair if (!key.empty()) { - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key)) + if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) { if (!parser.writeValue(key, name_stack)) { @@ -634,8 +686,9 @@ namespace LLInitParam } } // then try to serialize value directly - else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), static_cast<const self_t*>(diff_param)->get())) { - if (!parser.writeValue(typed_param.mData.mValue, name_stack)) + else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue())) + { + if (!parser.writeValue(typed_param.getValue(), name_stack)) { return; } @@ -647,18 +700,18 @@ namespace LLInitParam // tell parser about our actual type parser.inspectValue<T>(name_stack, min_count, max_count, NULL); // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (NAME_VALUE_LOOKUP::getPossibleValues()) + if (name_value_lookup_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); } } void set(value_assignment_t val, bool flag_as_provided = true) { - mData.mValue = val; - mData.clearKey(); + setValue(val); + param_value_t::clearValueName(); setProvided(flag_as_provided); - Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); + Param::enclosingBlock().paramChanged(*this, flag_as_provided); } void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -670,65 +723,56 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return get(); } + operator value_assignment_t() const { return param_value_t::getValue(); } // explicit conversion - value_assignment_t operator()() const { return get(); } + value_assignment_t operator()() const { return param_value_t::getValue(); } protected: - value_assignment_t get() const - { - return mData.mValue; - } static bool mergeWith(Param& dst, const Param& src, bool overwrite) { const self_t& src_typed_param = static_cast<const self_t&>(src); self_t& dst_typed_param = static_cast<self_t&>(dst); + if (src_typed_param.isProvided() && (overwrite || !dst_typed_param.isProvided())) { - dst_typed_param.mData.clearKey(); - dst_typed_param.set(src_typed_param.get()); + dst_typed_param.clearValueName(); + dst_typed_param.set(src_typed_param.getValue()); return true; } return false; } - - struct Data : public key_cache_t - { - T mValue; - }; - - Data mData; }; // parameter that is a block template <typename T, typename NAME_VALUE_LOOKUP> class TypedParam<T, NAME_VALUE_LOOKUP, false, true> - : public T, - public Param + : public Param, + public ParamValue<T, NAME_VALUE_LOOKUP> { public: typedef const T value_const_t; typedef T value_t; - typedef value_const_t& value_const_ref_t; - typedef value_const_ref_t value_assignment_t; - typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t; + typedef value_const_t& value_assignment_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - T(value) + param_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), &mergeWith, &deserializeParam, &serializeParam, validate_func, &inspectParam, - min_count, max_count); + min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } } @@ -737,25 +781,27 @@ namespace LLInitParam { self_t& typed_param = static_cast<self_t&>(param); // attempt to parse block... - if(typed_param.deserializeBlock(parser, name_stack)) + if(typed_param.deserializeBlock(parser, name_stack, generation)) { - typed_param.mData.clearKey(); - typed_param.enclosingBlock().setLastChangedParam(param, true); + typed_param.clearValueName(); + typed_param.enclosingBlock().paramChanged(param, true); + typed_param.setProvided(true); return true; } - if(!NAME_VALUE_LOOKUP::empty()) + if(name_value_lookup_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (NAME_VALUE_LOOKUP::get(name, typed_param)) + if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) { - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.mData.setKey(name); - typed_param.mData.mKeyVersion = typed_param.getLastChangeVersion(); + typed_param.enclosingBlock().paramChanged(param, true); + typed_param.setValueName(name); + typed_param.setProvided(true); + typed_param.mKeyVersion = typed_param.getLastChangeVersion(); return true; } @@ -767,13 +813,15 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); + if (!typed_param.isProvided()) return; + if (!name_stack.empty()) { name_stack.back().second = parser.newParseGeneration(); } - std::string key = typed_param.mData.getKey(); - if (!key.empty() && typed_param.mData.mKeyVersion == typed_param.getLastChangeVersion()) + std::string key = typed_param.getValueName(); + if (!key.empty() && typed_param.mKeyVersion == typed_param.getLastChangeVersion()) { if (!parser.writeValue(key, name_stack)) { @@ -790,33 +838,33 @@ namespace LLInitParam { // I am a param that is also a block, so just recurse into my contents const self_t& typed_param = static_cast<const self_t&>(param); - typed_param.inspectBlock(parser, name_stack); + typed_param.inspectBlock(parser, name_stack, min_count, max_count); } // a param-that-is-a-block is provided when the user has set one of its child params // *and* the block as a whole validates bool isProvided() const { - // only validate block when it hasn't already passed validation and user has supplied *some* value - if (Param::anyProvided() && mData.mValidatedVersion < T::getLastChangeVersion()) + // only validate block when it hasn't already passed validation with current data + if (Param::anyProvided() && param_value_t::mValidatedVersion < param_value_t::getLastChangeVersion()) { // a sub-block is "provided" when it has been filled in enough to be valid - mData.mValidated = T::validateBlock(false); - mData.mValidatedVersion = T::getLastChangeVersion(); + param_value_t::mValidated = param_value_t::validateBlock(false); + param_value_t::mValidatedVersion = param_value_t::getLastChangeVersion(); } - return Param::anyProvided() && mData.mValidated; + return Param::anyProvided() && param_value_t::mValidated; } // assign block contents to this param-that-is-a-block void set(value_assignment_t val, bool flag_as_provided = true) { - value_t::operator=(val); - mData.clearKey(); + setValue(val); + param_value_t::clearValueName(); // force revalidation of block by clearing known provided version // next call to isProvided() will update provision status based on validity - mData.mValidatedVersion = 0; + param_value_t::mValidatedVersion = -1; setProvided(flag_as_provided); - Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); + Param::enclosingBlock().paramChanged(*this, flag_as_provided); } void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -828,10 +876,10 @@ namespace LLInitParam } // propagate changed status up to enclosing block - /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { - T::setLastChangedParam(last_param, user_provided); - Param::enclosingBlock().setLastChangedParam(*this, user_provided); + ParamValue<T, NAME_VALUE_LOOKUP>::paramChanged(changed_param, user_provided); + Param::enclosingBlock().paramChanged(*this, user_provided); if (user_provided) { // a child param has been explicitly changed @@ -841,41 +889,30 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return get(); } + operator value_assignment_t() const { return param_value_t::getValue(); } // explicit conversion - value_assignment_t operator()() const { return get(); } + value_assignment_t operator()() const { return param_value_t::getValue(); } protected: - value_assignment_t get() const - { - return *this; - } static bool mergeWith(Param& dst, const Param& src, bool overwrite) { const self_t& src_typed_param = static_cast<const self_t&>(src); self_t& dst_typed_param = static_cast<self_t&>(dst); - if (dst_typed_param.T::merge(T::selfBlockDescriptor(), src_typed_param, overwrite)) + + if (src_typed_param.anyProvided()) { - dst_typed_param.mData.clearKey(); - return true; + bool param_provided = src_typed_param.isProvided() && (overwrite || !dst_typed_param.isProvided()); + if (dst_typed_param.mergeBlockParam(param_provided, param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) + { + dst_typed_param.clearValueName(); + dst_typed_param.setProvided(true); + dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); + return true; + } } return false; } - - struct Data : public key_cache_t - { - S32 mKeyVersion; - mutable S32 mValidatedVersion; - mutable bool mValidated; // lazy validation flag - - Data() - : mKeyVersion(0), - mValidatedVersion(0), - mValidated(false) - {} - }; - Data mData; }; // container of non-block parameters @@ -885,29 +922,28 @@ namespace LLInitParam { public: typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> self_t; - typedef typename std::vector<VALUE_TYPE> container_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; + typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; typedef VALUE_TYPE value_t; - typedef value_t& value_ref_t; - typedef const value_t& value_const_ref_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; - typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr), - mValues(value) + : Param(block_descriptor.mCurrentBlockPtr) { - mCachedKeys.resize(mValues.size()); + std::copy(value.begin(), value.end(), std::back_inserter(mValues)); + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), &mergeWith, &deserializeParam, &serializeParam, validate_func, &inspectParam, - min_count, max_count); + min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } } @@ -924,29 +960,22 @@ namespace LLInitParam // attempt to read value directly if (parser.readValue(value)) { - typed_param.mValues.push_back(value); - // save an empty name/value key as a placeholder - typed_param.mCachedKeys.push_back(key_cache_t()); - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.setProvided(true); + typed_param.add(value); return true; } // try to parse a known named value - if(!NAME_VALUE_LOOKUP::empty()) + if(name_value_lookup_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (NAME_VALUE_LOOKUP::get(name, typed_param.mValues)) + if (name_value_lookup_t::getValueFromName(name, typed_param.mValues)) { - typed_param.mValues.push_back(value); - typed_param.mCachedKeys.push_back(key_cache_t()); - typed_param.mCachedKeys.back().setKey(name); - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.setProvided(true); + typed_param.add(value); + typed_param.mValues.back().setValueName(name); return true; } @@ -961,25 +990,27 @@ namespace LLInitParam const self_t& typed_param = static_cast<const self_t&>(param); if (!typed_param.isProvided() || name_stack.empty()) return; - const_iterator it = typed_param.mValues.begin(); - for (typename std::vector<key_cache_t>::const_iterator key_it = typed_param.mCachedKeys.begin(); - it != typed_param.mValues.end(); - ++key_it, ++it) + for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); + it != end_it; + ++it) { - std::string key = key_it->get(); + std::string key = it->getValue(); name_stack.back().second = parser.newParseGeneration(); - if(!key.empty()) + if(key.empty()) + // not parsed via name values, write out value directly { - if(!parser.writeValue(key, name_stack)) + if (!parser.writeValue(*it, name_stack)) { - return; + break; } } - // not parse via name values, write out value directly - else if (!parser.writeValue(*it, name_stack)) + else { - return; + if(!parser.writeValue(key, name_stack)) + { + break; + } } } } @@ -987,19 +1018,17 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); - if (NAME_VALUE_LOOKUP::getPossibleValues()) + if (name_value_lookup_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); } } void set(value_assignment_t val, bool flag_as_provided = true) { mValues = val; - mCachedKeys.clear(); - mCachedKeys.resize(mValues.size()); setProvided(flag_as_provided); - Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); + Param::enclosingBlock().paramChanged(*this, flag_as_provided); } @@ -1011,23 +1040,23 @@ namespace LLInitParam } } - value_ref_t add() + value_t& add() { - mValues.push_back(value_t()); - mCachedKeys.push_back(key_cache_t()); + mValues.push_back(param_value_t(value_t())); setProvided(true); + Param::enclosingBlock().paramChanged(*this, true); return mValues.back(); } - void add(value_const_ref_t item) + void add(const value_t& item) { - mValues.push_back(item); - mCachedKeys.push_back(key_cache_t()); + mValues.push_back(param_value_t(item)); setProvided(true); + Param::enclosingBlock().paramChanged(*this, true); } // implicit conversion - operator value_assignment_t() const { return self_t::get(); } + operator value_assignment_t() const { return mValues; } typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; @@ -1044,27 +1073,31 @@ namespace LLInitParam } protected: - value_assignment_t get() const - { - return mValues; - } - static bool mergeWith(Param& dst, const Param& src, bool overwrite) { const self_t& src_typed_param = static_cast<const self_t&>(src); self_t& dst_typed_param = static_cast<self_t&>(dst); - if (src_typed_param.isProvided() - && (overwrite || !dst_typed_param.isProvided())) + if (overwrite) { - dst_typed_param.set(src_typed_param.get()); - return true; + std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); } - return false; + else + { + container_t new_values(src_typed_param.mValues); + std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); + std::swap(dst_typed_param.mValues, new_values); + } + + if (src_typed_param.begin() != src_typed_param.end()) + { + dst_typed_param.setProvided(true); + dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); + } + return true; } container_t mValues; - std::vector<key_cache_t> mCachedKeys; }; // container of block parameters @@ -1074,80 +1107,76 @@ namespace LLInitParam { public: typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> self_t; - typedef typename std::vector<VALUE_TYPE> container_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; + typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; - typedef VALUE_TYPE value_t; - typedef value_t& value_ref_t; - typedef const value_t& value_const_ref_t; - - typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - mValues(value), - mLastParamGeneration(0) + mLastParseGeneration(0) { - mCachedKeys.resize(mValues.size()); + std::copy(value.begin(), value.end(), back_inserter(mValues)); + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), &mergeWith, &deserializeParam, &serializeParam, validate_func, &inspectParam, - min_count, max_count); + min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } } bool isProvided() const { return Param::anyProvided(); } - value_ref_t operator[](S32 index) { return mValues[index]; } - value_const_ref_t operator[](S32 index) const { return mValues[index]; } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) { self_t& typed_param = static_cast<self_t&>(param); bool new_value = false; - if (generation != typed_param.mLastParamGeneration || typed_param.mValues.empty()) + + if (generation != typed_param.mLastParseGeneration + || typed_param.mValues.empty()) { new_value = true; typed_param.mValues.push_back(value_t()); - typed_param.mCachedKeys.push_back(Data()); } - value_ref_t value = typed_param.mValues.back(); + param_value_t& value = typed_param.mValues.back(); // attempt to parse block... - if(value.deserializeBlock(parser, name_stack)) + if(value.deserializeBlock(parser, name_stack, generation)) { if (new_value) { // successfully parsed new value, let's keep it - typed_param.mLastParamGeneration = generation; + typed_param.mLastParseGeneration = generation; } - typed_param.enclosingBlock().setLastChangedParam(param, true); + typed_param.enclosingBlock().paramChanged(param, true); typed_param.setProvided(true); return true; } - else if(!NAME_VALUE_LOOKUP::empty()) + else if(name_value_lookup_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (NAME_VALUE_LOOKUP::get(name, value)) + if (name_value_lookup_t::getValueFromName(name, value.getValue())) { if (new_value) { // successfully parsed new value, let's keep it - typed_param.mLastParamGeneration = generation; + typed_param.mLastParseGeneration = generation; } - typed_param.mCachedKeys.back().setKey(name); - typed_param.mCachedKeys.back().mKeyVersion = value.getLastChangeVersion(); - typed_param.enclosingBlock().setLastChangedParam(param, true); + typed_param.mValues.back().setValueName(name); + typed_param.mValues.back().mKeyVersion = value.getLastChangeVersion(); + typed_param.enclosingBlock().paramChanged(param, true); typed_param.setProvided(true); return true; } @@ -1158,7 +1187,6 @@ namespace LLInitParam if (new_value) { // failed to parse new value, pop it off typed_param.mValues.pop_back(); - typed_param.mCachedKeys.pop_back(); } return false; @@ -1169,26 +1197,22 @@ namespace LLInitParam const self_t& typed_param = static_cast<const self_t&>(param); if (!typed_param.isProvided() || name_stack.empty()) return; - const_iterator it = typed_param.mValues.begin(); - for (typename std::vector<Data>::const_iterator key_it = typed_param.mCachedKeys.begin(); - it != typed_param.mValues.end(); - ++key_it, ++it) + for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); + it != end_it; + ++it) { name_stack.back().second = parser.newParseGeneration(); - std::string key = key_it->getKey(); - if (!key.empty() && key_it->mKeyVersion == it->getLastChangeVersion()) + std::string key = it->getValueName(); + if (!key.empty() && it->mKeyVersion == it->getLastChangeVersion()) { - if(!parser.writeValue(key, name_stack)) - { - return; - } + parser.writeValue(key, name_stack); } // Not parsed via named values, write out value directly // NOTE: currently we don't worry about removing default values in Multiple - else if (!it->serializeBlock(parser, name_stack, NULL)) + else { - return; + it->serializeBlock(parser, name_stack, NULL); } } } @@ -1196,16 +1220,14 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { // I am a vector of blocks, so describe my contents recursively - value_t().inspectBlock(parser, name_stack); + param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); } void set(value_assignment_t val, bool flag_as_provided = true) { mValues = val; - mCachedKeys.clear(); - mCachedKeys.resize(mValues.size()); setProvided(flag_as_provided); - Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); + Param::enclosingBlock().paramChanged(*this, flag_as_provided); } void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -1216,23 +1238,23 @@ namespace LLInitParam } } - value_ref_t add() + value_t& add() { mValues.push_back(value_t()); - mCachedKeys.push_back(Data()); setProvided(true); + Param::enclosingBlock().paramChanged(*this, true); return mValues.back(); } - void add(value_const_ref_t item) + void add(const value_t& item) { mValues.push_back(item); - mCachedKeys.push_back(Data()); setProvided(true); + Param::enclosingBlock().paramChanged(*this, true); } // implicit conversion - operator value_assignment_t() const { return self_t::get(); } + operator value_assignment_t() const { return mValues; } typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; @@ -1246,8 +1268,8 @@ namespace LLInitParam U32 numValidElements() const { U32 count = 0; - for (const_iterator it = mValues.begin(); - it != mValues.end(); + for (const_iterator it = mValues.begin(), end_it = mValues.end(); + it != end_it; ++it) { if(it->validateBlock(false)) count++; @@ -1256,74 +1278,77 @@ namespace LLInitParam } protected: - value_assignment_t get() const - { - return mValues; - } static bool mergeWith(Param& dst, const Param& src, bool overwrite) { const self_t& src_typed_param = static_cast<const self_t&>(src); self_t& dst_typed_param = static_cast<self_t&>(dst); - if (src_typed_param.isProvided() - && (overwrite || !dst_typed_param.isProvided())) + if (overwrite) { - dst_typed_param.set(src_typed_param.get()); - return true; + std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); + } + else + { + container_t new_values(src_typed_param.mValues); + std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); + std::swap(dst_typed_param.mValues, new_values); } - return false; - } - struct Data : public key_cache_t - { - S32 mKeyVersion; // version of block for which key was last valid + if (src_typed_param.begin() != src_typed_param.end()) + { + dst_typed_param.setProvided(true); + dst_typed_param.enclosingBlock().paramChanged(dst_typed_param, true); + } - Data() : mKeyVersion(0) {} - }; + return true; + } container_t mValues; - std::vector<Data> mCachedKeys; - S32 mLastParamGeneration; + S32 mLastParseGeneration; }; template <typename DERIVED_BLOCK> class Choice : public BaseBlock { - typedef Choice<DERIVED_BLOCK> self_t; - typedef Choice<DERIVED_BLOCK> enclosing_block_t; + typedef Choice<DERIVED_BLOCK> self_t; + typedef Choice<DERIVED_BLOCK> enclosing_block_t; LOG_CLASS(self_t); public: // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return merge(selfBlockDescriptor(), other, true); + return mergeBlock(selfBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return merge(selfBlockDescriptor(), other, false); + return mergeBlock(selfBlockDescriptor(), other, false); } - // merge with other block - bool merge(BlockDescriptor& block_data, const self_t& other, bool overwrite) + bool mergeBlockParam(bool param_provided, BlockDescriptor& block_data, const self_t& other, bool overwrite) { - // only merge a choice if we are overwriting with other's contents - if (overwrite) + if (param_provided) { - mCurChoice = other.mCurChoice; - return BaseBlock::merge(selfBlockDescriptor(), other, overwrite); + return mergeBlock(block_data, other, overwrite); } return false; } + // merge with other block + bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) + { + mCurChoice = other.mCurChoice; + return BaseBlock::mergeBlock(selfBlockDescriptor(), other, overwrite); + } + // clear out old choice when param has changed - /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { - param_handle_t changed_param_handle = BaseBlock::getHandleFromParam(&last_param); + param_handle_t changed_param_handle = BaseBlock::getHandleFromParam(&changed_param); // if we have a new choice... if (changed_param_handle != mCurChoice) { @@ -1335,7 +1360,7 @@ namespace LLInitParam } mCurChoice = changed_param_handle; } - BaseBlock::setLastChangedParam(last_param, user_provided); + BaseBlock::paramChanged(changed_param, user_provided); } virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } @@ -1358,20 +1383,21 @@ namespace LLInitParam friend class Choice<DERIVED_BLOCK>; typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; - explicit Alternative(const char* name, value_assignment_t val = DefaultInitializer<T>::get()) + explicit Alternative(const char* name, value_assignment_t val = defaultValue<T>()) : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { // assign initial choice to first declared option DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); - if (LL_UNLIKELY( - DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING - && blockp->mCurChoice == 0)) + if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) { - blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); + if(blockp->mCurChoice == 0) + { + blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); + } } } @@ -1390,7 +1416,7 @@ namespace LLInitParam { if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this) { - return super_t::get(); + return super_t::getValue(); } return mOriginalValue; } @@ -1399,7 +1425,7 @@ namespace LLInitParam { if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this) { - return super_t::get(); + return super_t::getValue(); } return mOriginalValue; } @@ -1433,8 +1459,8 @@ namespace LLInitParam class Block : public BASE_BLOCK { - typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t; - typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t; + typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t; + typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t; public: typedef BASE_BLOCK base_block_t; @@ -1442,13 +1468,13 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return BaseBlock::merge(selfBlockDescriptor(), other, true); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return BaseBlock::merge(selfBlockDescriptor(), other, false); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); } virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } @@ -1468,10 +1494,10 @@ namespace LLInitParam class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; - explicit Optional(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) + explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") @@ -1483,7 +1509,7 @@ namespace LLInitParam return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(value_assignment_t val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1495,12 +1521,12 @@ namespace LLInitParam class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::value_assignment_t value_assignment_t; // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) + explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>()) : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) {} @@ -1529,15 +1555,15 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBaseBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_assignment_t value_assignment_t; typedef typename super_t::iterator iterator; typedef typename super_t::const_iterator const_iterator; - explicit Multiple(const char* name = "", value_assignment_t val = DefaultInitializer<container_t>::get()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount()) + explicit Multiple(const char* name = "") + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount(), RANGE::maxCount()) {} Multiple& operator=(value_assignment_t val) @@ -1545,7 +1571,7 @@ namespace LLInitParam set(val); return *this; } - + DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) { super_t::set(val); @@ -1559,6 +1585,96 @@ namespace LLInitParam } }; + template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > + class Batch : private TypedParam<T, NAME_VALUE_LOOKUP, false> + { + public: + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<param_value_t>::value> super_t; + typedef Batch<T, RANGE, NAME_VALUE_LOOKUP> self_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; + + struct BatchDefaultValue : public ParamDescriptor::UserData + { + BatchDefaultValue(const T& value) + : mValue(value) + {} + + T mValue; + }; + + explicit Batch(const char* name, value_assignment_t val) + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), + mLastParseGeneration(-1) + { + BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptorp = block_descriptor.mCurrentBlockPtr->findParamDescriptor(*this); + + if (param_descriptorp) + { + param_descriptorp->mDeserializeFunc = &deserializeParam; + param_descriptorp->mUserData = new BatchDefaultValue(new param_value_t(val)); + } + } + } + + explicit Batch(const char* name = "") + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, defaultValue<T>(), NULL, 0, 1), + mLastParseGeneration(-1) + { + BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptorp = block_descriptor.mCurrentBlockPtr->findParamDescriptor(*this); + + if (param_descriptorp) + { + param_descriptorp->mDeserializeFunc = &deserializeParam; + } + } + } + + Batch& operator=(value_assignment_t val) + { + set(val); + return *this; + } + + DERIVED_BLOCK& operator()(value_assignment_t val) + { + super_t::set(val); + return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); + } + + using super_t::operator(); + + private: + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) + { + self_t& typed_param = static_cast<self_t&>(param); + + if (generation != typed_param.mLastParseGeneration) + { + ParamDescriptorPtr descriptor = typed_param.enclosingBlock().findParamDescriptor(param); + if (descriptor && static_cast<BatchDefaultValue*>(descriptor->mUserData)) + { + static_cast<param_value_t&>(typed_param) = (static_cast<BatchDefaultValue*>(descriptor->mUserData))->mValue; + } + else + { + static_cast<param_value_t&>(typed_param) = param_value_t(value_t()); + } + typed_param.mLastParseGeneration = generation; + } + return super_t::deserializeParam(param, parser, name_stack, generation); + } + + S32 mLastParseGeneration; + }; + class Deprecated : public Param { public: @@ -1568,13 +1684,14 @@ namespace LLInitParam BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), NULL, &deserializeParam, NULL, NULL, NULL, - 0, S32_MAX); + 0, S32_MAX)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } } @@ -1602,137 +1719,91 @@ namespace LLInitParam } }; - template<typename T, typename DERIVED = TypedParam<T> > - class BlockValue - : public Block<TypedParam<T, TypeValues<T>, false> >, - public Param + template<typename T> + class CustomParamValue + : public Block<ParamValue<T, TypeValues<T> > >, + public TypeValues<T> { public: typedef enum e_value_age { - OLDER_THAN_BLOCK, // mData.mValue needs to be refreshed from the block parameters - NEWER_THAN_BLOCK, // mData.mValue holds the authoritative value (which has been replicated to the block parameters via setBlockFromValue) - SAME_AS_BLOCK // mData.mValue is derived from the block parameters, which are authoritative + VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters + VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue) + BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef BlockValue<T> self_t; - typedef Block<TypedParam<T, TypeValues<T>, false> > block_t; - typedef const T& value_const_ref_t; - typedef value_const_ref_t value_assignment_t; - typedef typename TypeValues<T>::KeyCache key_cache_t; - - BlockValue(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr), - mData(value, NEWER_THAN_BLOCK) - { - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - } + typedef ParamValue<T, TypeValues<T> > derived_t; + typedef CustomParamValue<T> self_t; + typedef Block<derived_t> block_t; + typedef const T& value_assignment_t; - // implicit conversion - operator value_assignment_t() const { return get(); } - // explicit conversion - value_assignment_t operator()() const { return get(); } + CustomParamValue(const T& value = T()) + : mValue(value), + mValueAge(VALUE_AUTHORITATIVE), + mKeyVersion(0), + mValidatedVersion(-1) + {} - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) + bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack, S32 generation) { - DERIVED& typed_param = static_cast<DERIVED&>(param); + derived_t& typed_param = static_cast<derived_t&>(*this); // type to apply parse direct value T if (name_stack.first == name_stack.second) { - if(parser.readValue(typed_param.mData.mValue)) + if(parser.readValue(typed_param.mValue)) { - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.setProvided(true); - typed_param.mData.clearKey(); - typed_param.mData.mValueAge = NEWER_THAN_BLOCK; - typed_param.setBlockFromValue(); + typed_param.clearValueName(); + typed_param.mValueAge = VALUE_AUTHORITATIVE; + typed_param.updateBlockFromValue(); return true; } - - if(!TypeValues<T>::empty()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (TypeValues<T>::get(name, typed_param.mData.mValue)) - { - typed_param.mData.setKey(name); - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.setProvided(true); - typed_param.mData.mValueAge = NEWER_THAN_BLOCK; - typed_param.setBlockFromValue(); - - return true; - } - } - } } // fall back on parsing block components for T // if we deserialized at least one component... - if (typed_param.BaseBlock::deserializeBlock(parser, name_stack)) + if (typed_param.BaseBlock::deserializeBlock(parser, name_stack, generation)) { - // ...our block is provided, and considered changed - typed_param.enclosingBlock().setLastChangedParam(param, true); - typed_param.setProvided(true); return true; } + return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + void serializeBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const { - const self_t& typed_param = static_cast<const self_t&>(param); - - if (!typed_param.isProvided()) return; + const self_t& typed_param = static_cast<const self_t&>(*this); + const self_t* diff_param = static_cast<const self_t*>(diff_block); - std::string key = typed_param.mData.getKey(); + std::string key = typed_param.getValueName(); // first try to write out name of name/value pair if (!key.empty()) { - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key)) + if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) { - if (!parser.writeValue(key, name_stack)) - { - return; - } + parser.writeValue(key, name_stack); } } // then try to serialize value directly - else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), (static_cast<const self_t*>(diff_param))->get())) + else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) { - if (parser.writeValue(typed_param.mData.mValue, name_stack)) + if (!parser.writeValue(typed_param.getValue(), name_stack)) { - return; + //RN: *always* serialize provided components of BlockValue (don't pass diff_param on), + // since these tend to be viewed as the constructor arguments for the value T. It seems + // cleaner to treat the uniqueness of a BlockValue according to the generated value, and + // not the individual components. This way <color red="0" green="1" blue="0"/> will not + // be exported as <color green="1"/>, since it was probably the intent of the user to + // be specific about the RGB color values. This also fixes an issue where we distinguish + // between rect.left not being provided and rect.left being explicitly set to 0 (same as default) + block_t::serializeBlock(parser, name_stack, NULL); } - - //RN: *always* serialize provided components of BlockValue (don't pass diff_param on), - // since these tend to be viewed as the constructor arguments for the value T. It seems - // cleaner to treat the uniqueness of a BlockValue according to the generated value, and - // not the individual components. This way <color red="0" green="1" blue="0"/> will not - // be exported as <color green="1"/>, since it was probably the intent of the user to - // be specific about the RGB color values. This also fixes an issue where we distinguish - // between rect.left not being provided and rect.left being explicitly set to 0 (same as default) - typed_param.BaseBlock::serializeBlock(parser, name_stack, NULL); } } - static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { // first, inspect with actual type... parser.inspectValue<T>(name_stack, min_count, max_count, NULL); @@ -1742,25 +1813,19 @@ namespace LLInitParam parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues()); } // then recursively inspect contents... - const self_t& typed_param = static_cast<const self_t&>(param); - typed_param.inspectBlock(parser, name_stack); + return block_t::inspectBlock(parser, name_stack, min_count, max_count); } - - bool isProvided() const + bool validateBlock(bool emit_errors = true) const { - if (!Param::anyProvided()) return false; - - // block has an updated parameter - // if cached value is stale, regenerate from params - if (mData.mValueAge == OLDER_THAN_BLOCK) + if (mValueAge == VALUE_NEEDS_UPDATE) { - if (block_t::validateBlock(false)) + if (block_t::validateBlock(emit_errors)) { - static_cast<const DERIVED*>(this)->setValueFromBlock(); // clear stale keyword associated with old value - mData.clearKey(); - mData.mValueAge = SAME_AS_BLOCK; + TypeValues<T>::clearValueName(); + mValueAge = BLOCK_AUTHORITATIVE; + static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock(); return true; } else @@ -1777,104 +1842,84 @@ namespace LLInitParam } } - void set(value_assignment_t val, bool flag_as_provided = true) + // propagate change status up to enclosing block + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) + { + BaseBlock::paramChanged(changed_param, user_provided); + if (user_provided) { - Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); + // a parameter changed, so our value is out of date + mValueAge = VALUE_NEEDS_UPDATE; + } + } + void setValue(value_assignment_t val) + { + derived_t& typed_param = static_cast<derived_t&>(*this); // set param version number to be up to date, so we ignore block contents - mData.mValueAge = NEWER_THAN_BLOCK; - - mData.mValue = val; - mData.clearKey(); - setProvided(flag_as_provided); - static_cast<DERIVED*>(this)->setBlockFromValue(); + mValueAge = VALUE_AUTHORITATIVE; + mValue = val; + typed_param.clearValueName(); + static_cast<derived_t*>(const_cast<self_t*>(this))->updateBlockFromValue(); } - void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) + value_assignment_t getValue() const { - // don't override any user provided value - if (!isProvided()) - { - set(val, flag_as_provided); - } + validateBlock(true); + return mValue; } - // propagate change status up to enclosing block - /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) - { - BaseBlock::setLastChangedParam(last_param, user_provided); - Param::enclosingBlock().setLastChangedParam(*this, user_provided); - if (user_provided) - { - setProvided(true); // some component provided - // a parameter changed, so our value is out of date - mData.mValueAge = OLDER_THAN_BLOCK; - } + T& getValue() + { + validateBlock(true); + return mValue; } + S32 mKeyVersion; + protected: - value_assignment_t get() const - { - // if some parameters were provided, issue warnings on invalid blocks - if (Param::anyProvided() && (mData.mValueAge == OLDER_THAN_BLOCK)) - { - // go ahead and issue warnings at this point if any param is invalid - if(block_t::validateBlock(true)) - { - static_cast<const DERIVED*>(this)->setValueFromBlock(); - mData.clearKey(); - mData.mValueAge = SAME_AS_BLOCK; - } - } - return mData.mValue; + // use this from within updateValueFromBlock() to set the value without making it authoritative + void updateValue(value_assignment_t value) + { + mValue = value; } - - struct Data : public key_cache_t + bool mergeBlockParam(bool param_provided, BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { - Data(const T& value, EValueAge age) - : mValue(value), - mValueAge(age) - {} - - T mValue; - EValueAge mValueAge; - }; - - // mutable to allow lazy updates on get - mutable Data mData; + if (param_provided) + { + return mergeBlock(block_data, other, overwrite); + } + return false; + } - private: - static bool mergeWith(Param& dst, const Param& src, bool overwrite) + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { - const DERIVED& src_typed_param = static_cast<const DERIVED&>(src); - DERIVED& dst_typed_param = static_cast<DERIVED&>(dst); + const derived_t& src_typed_param = static_cast<const derived_t&>(other); - if (src_typed_param.isProvided() - && (overwrite || !dst_typed_param.isProvided())) + if (src_typed_param.mValueAge == VALUE_AUTHORITATIVE) { - if (src_typed_param.mData.mValueAge == NEWER_THAN_BLOCK) - { - // copy value over - dst_typed_param.set(src_typed_param.get()); - } - else - { - // merge individual parameters into destination - dst_typed_param.merge(block_t::selfBlockDescriptor(), src_typed_param, overwrite); - } + // copy value over + setValue(src_typed_param.getValue()); return true; } - return false; + else + { + // merge individual parameters into destination + return block_t::mergeBlock(block_t::selfBlockDescriptor(), src_typed_param, overwrite); + } } - }; - template<> - struct ParamCompare<LLSD, false> - { - static bool equals(const LLSD &a, const LLSD &b); + mutable S32 mValidatedVersion; + mutable bool mValidated; // lazy validation flag + + private: + + mutable T mValue; + mutable EValueAge mValueAge; }; } + #endif // LL_LLPARAM_H diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 80dfe16ee9f0070e264f21adc1aa9663c91948e7..c4af9e2ab6518c03bcd0da7a75f6bf1d0a0b7e46 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -652,17 +652,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AvatarPhysicsTest</key> - <map> - <key>Comment</key> - <string>Simulate continuous physics behavior on all nearby avatars.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AvatarSex</key> <map> <key>Comment</key> @@ -13061,6 +13050,39 @@ <string>Boolean</string> <key>Value</key> <integer>1</integer> + </map> + <key>EnableInventory</key> + <map> + <key>Comment</key> + <string>Enable opening inventory from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>EnableSearch</key> + <map> + <key>Comment</key> + <string>Enable opening search from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>EnableAppearance</key> + <map> + <key>Comment</key> + <string>Enable opening appearance from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> </map> <key>SearchFromAddressBar</key> <map> diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml index 490da2c9d46db8fb7ed83f99b9b7821fe380f2fc..bc97ec00e9bad376dc5a40e889a8e28c8f81a56c 100644 --- a/indra/newview/app_settings/settings_minimal.xml +++ b/indra/newview/app_settings/settings_minimal.xml @@ -303,6 +303,39 @@ <key>Value</key> <integer>0</integer> </map> + <key>EnableInventory</key> + <map> + <key>Comment</key> + <string>Enable opening inventory from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>EnableSearch</key> + <map> + <key>Comment</key> + <string>Enable opening search from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>EnableAppearance</key> + <map> + <key>Comment</key> + <string>Enable opening appearance from web link</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DoubleClickShowWorldMap</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 28a38d43901b4a67c36744e5b9b056ac36104fde..3b12a07a27df958a59de4e0dcc10e488b9bdb9ce 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -23,6 +23,7 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; +varying vec3 vary_pointlight_col; uniform mat4 inv_proj; @@ -46,13 +47,17 @@ void main() vec4 pos = vec4(vary_position, 1.0); + vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + vec4 color = diff * col; color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); + color.rgb += diff.rgb * vary_pointlight_col.rgb; + gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); //gl_FragColor = vec4(1,0,1,1)*shadow; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 7ac410da9516e16202a019854e640207ae738a15..525b68c43793a499514e4057fbca9c0e4fecd647 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -11,7 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -23,11 +22,37 @@ varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; +varying vec3 vary_pointlight_col; uniform float near_clip; uniform float shadow_offset; uniform float shadow_bias; +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} + void main() { //transform vertex @@ -38,33 +63,35 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - vary_position = pos.xyz; + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + // Add windlight lights - col.rgb += atmosAmbient(vec3(0.)); + col.rgb = atmosAmbient(vec3(0.)); vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); - col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + col.rgb = col.rgb*gl_Color.rgb; gl_FrontColor = col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 1dd29bfc70e7374fbef40c86f5186e9694525b29..88ca60318b5fd335622260e716422b0ee48e2491 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -29,6 +29,7 @@ varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; +varying vec3 vary_pointlight_col; uniform float shadow_bias; @@ -105,15 +106,20 @@ void main() } } + vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + vec4 color = diff * col; color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); + color.rgb += diff.rgb * vary_pointlight_col.rgb; + //gl_FragColor = gl_Color; gl_FragColor = color; + //gl_FragColor.r = 0.0; //gl_FragColor = vec4(1,shadow,1,1); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 92f1cb22d6fe9a980a78282b4d346e5997187f7a..ea09d5bb095abcea0b7461fb3ddace91d2b53def 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -11,7 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -23,11 +22,37 @@ varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; +varying vec3 vary_pointlight_col; uniform float near_clip; uniform float shadow_offset; uniform float shadow_bias; +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} + void main() { //transform vertex @@ -46,25 +71,27 @@ void main() //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + // Add windlight lights - col.rgb += atmosAmbient(vec3(0.)); + col.rgb = atmosAmbient(vec3(0.)); vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); - col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + col.rgb = col.rgb*gl_Color.rgb; gl_FrontColor = col; diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ec162e3608fa85cf6f0a4feb92ea3c2dbb056be3..ce15c4b8f7e98cf6ad20ceaa6a7784da48274520 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -4352,8 +4352,8 @@ wearable="shape" edit_group="driven" value_default="0" - value_min="-1.5" - value_max="1.5"> + value_min="-1.25" + value_max="1.25"> <param_morph /> </param> @@ -11875,7 +11875,7 @@ render_pass="bump"> edit_group="physics_advanced" value_default="0" value_min="0" - value_max=".1"> + value_max="30"> <param_driver /> </param> @@ -11887,9 +11887,9 @@ render_pass="bump"> label="Breast Physics Drag" wearable="physics" edit_group="physics_advanced" - value_default=".15" + value_default="1" value_min="0" - value_max=".5"> + value_max="10"> <param_driver /> </param> @@ -11914,9 +11914,9 @@ render_pass="bump"> label="Breast Physics UpDown Spring" wearable="physics" edit_group="physics_breasts_updown" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -11940,11 +11940,9 @@ render_pass="bump"> label="Breast Physics UpDown Damping" wearable="physics" edit_group="physics_breasts_updown" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1" - camera_elevation=".3" - camera_distance=".8"> + value_max="1"> <param_driver /> </param> @@ -11969,9 +11967,9 @@ render_pass="bump"> label="Breast Physics InOut Spring" wearable="physics" edit_group="physics_breasts_inout" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -11995,9 +11993,9 @@ render_pass="bump"> label="Breast Physics InOut Damping" wearable="physics" edit_group="physics_breasts_inout" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1"> + value_max="1"> <param_driver /> </param> @@ -12022,7 +12020,7 @@ render_pass="bump"> edit_group="physics_advanced" value_default="0" value_min="0" - value_max=".1"> + value_max="30"> <param_driver /> </param> <param @@ -12032,9 +12030,9 @@ render_pass="bump"> label="Belly Physics Drag" wearable="physics" edit_group="physics_advanced" - value_default=".15" + value_default="1" value_min="0" - value_max=".5"> + value_max="10"> <param_driver /> </param> <param @@ -12056,9 +12054,9 @@ render_pass="bump"> label="Belly Physics UpDown Spring" wearable="physics" edit_group="physics_belly_updown" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -12080,9 +12078,9 @@ render_pass="bump"> label="Belly Physics UpDown Damping" wearable="physics" edit_group="physics_belly_updown" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1"> + value_max="1"> <param_driver /> </param> @@ -12107,7 +12105,7 @@ render_pass="bump"> edit_group="physics_advanced" value_default="0" value_min="0" - value_max=".1"> + value_max="30"> <param_driver /> </param> <param @@ -12117,9 +12115,9 @@ render_pass="bump"> label="Butt Physics Drag" wearable="physics" edit_group="physics_advanced" - value_default=".15" + value_default="1" value_min="0" - value_max=".5"> + value_max="10"> <param_driver /> </param> @@ -12142,9 +12140,9 @@ render_pass="bump"> label="Butt Physics UpDown Spring" wearable="physics" edit_group="physics_butt_updown" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -12166,9 +12164,9 @@ render_pass="bump"> label="Butt Physics UpDown Damping" wearable="physics" edit_group="physics_butt_updown" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1"> + value_max="1"> <param_driver /> </param> @@ -12191,9 +12189,9 @@ render_pass="bump"> label="Butt Physics LeftRight Spring" wearable="physics" edit_group="physics_butt_leftright" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -12215,9 +12213,9 @@ render_pass="bump"> label="Butt Physics LeftRight Damping" wearable="physics" edit_group="physics_butt_leftright" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1"> + value_max="1"> <param_driver /> </param> @@ -12242,9 +12240,9 @@ render_pass="bump"> label="Breast Physics LeftRight Spring" wearable="physics" edit_group="physics_breasts_leftright" - value_default=".1" + value_default="10" value_min="0" - value_max="3"> + value_max="100"> <param_driver /> </param> <param @@ -12268,9 +12266,9 @@ render_pass="bump"> label="Breast Physics LeftRight Damping" wearable="physics" edit_group="physics_breasts_leftright" - value_default=".05" + value_default=".2" value_min="0" - value_max=".1"> + value_max="1"> <param_driver /> </param> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index ce8efe647fb1b2cfc1188486a520b69fde993053..dd8a88e5586036e14b46bf6ffbeca97485cd83eb 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,575 +1,575 @@ -version 27 - -// NOTE: This is mostly identical to featuretable_mac.txt with a few differences -// Should be combined into one table - -// -// Generates lists of feature mask that can be applied on top of each other. -// -// // Begin comments -// list <name> -// Starts a feature list named <name> -// <name> <available> <recommended> -// <name> is the name of a feature -// <available> is 0 or 1, whether the feature is available -// <recommended> is an F32 which is the recommended value -// -// For now, the first list read sets up all of the default values -// - - -// -// All contains everything at their default settings for high end machines -// NOTE: All settings are set to the MIN of applied values, including 'all'! -// -list all -RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 -RenderAvatarLODFactor 1 1.0 -RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarMaxVisible 1 12 -RenderAvatarVP 1 1 -RenderCubeMap 1 1 -RenderDelayVBUpdate 1 0 -RenderFarClip 1 256 -RenderFlexTimeFactor 1 1.0 -RenderFogRatio 1 4.0 -RenderGamma 1 0 -RenderGlowResolutionPow 1 9 -RenderGround 1 1 -RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 4 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 1.0 -RenderUseImpostors 1 1 -RenderVBOEnable 1 1 -RenderVolumeLODFactor 1 2.0 -UseStartScreen 1 1 -UseOcclusion 1 1 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 128 -Disregard128DefaultDrawDistance 1 1 -Disregard96DefaultDrawDistance 1 1 -RenderTextureMemoryMultiple 1 1.0 -RenderShaderLightingMaxLevel 1 3 -RenderDeferred 1 1 -SkyUseClassicClouds 1 1 -RenderDeferredSSAO 1 1 -RenderShadowDetail 1 2 -WatchdogDisabled 1 1 -RenderUseStreamVBO 1 1 - -// -// Low Graphics Settings -// -list Low -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarPhysicsLODFactor 1 0 -RenderAvatarMaxVisible 1 3 -RenderAvatarVP 1 0 -RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 -RenderGlowResolutionPow 1 8 -RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderLocalLights 1 0 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 -WindLightUseAtmosShaders 1 0 -WLSkyDetail 1 48 -SkyUseClassicClouds 1 0 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// Mid Graphics Settings -// -list Mid -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0.5 -RenderAvatarPhysicsLODFactor 1 0.75 -RenderAvatarVP 1 1 -RenderFarClip 1 96 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 8 -RenderMaxPartCount 1 2048 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 1.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 0.5 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 0 -WLSkyDetail 1 48 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// High Graphics Settings (purty) -// -list High -RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 1.0 -RenderAvatarPhysicsLODFactor 1 0.9 -RenderAvatarVP 1 1 -RenderFarClip 1 128 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 9 -RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 0.5 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 48 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// Ultra graphics (REALLY PURTY!) -// -list Ultra -RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 -RenderAvatarLODFactor 1 1.0 -RenderAvatarVP 1 1 -RenderFarClip 1 256 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 9 -RenderMaxPartCount 1 8192 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 4 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 1.0 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 2.0 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 128 -RenderDeferred 1 1 -RenderDeferredSSAO 1 1 -RenderShadowDetail 1 2 - -// -// Class Unknown Hardware (unknown) -// -list Unknown -RenderVBOEnable 1 0 - -// -// Class 0 Hardware (just old) -// -list Class0 -RenderVBOEnable 1 1 - -// -// Class 1 Hardware -// -list Class1 -RenderVBOEnable 1 1 - -// -// Class 2 Hardware (make it purty) -// -list Class2 -RenderVBOEnable 1 1 - -// -// Class 3 Hardware (make it purty) -// -list Class3 -RenderVBOEnable 1 1 - -// -// No Pixel Shaders available -// -list NoPixelShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -VertexShaderEnable 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - -// -// No Vertex Shaders available -// -list NoVertexShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -VertexShaderEnable 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - - -// -// "Default" setups for safe, low, medium, high -// -list safe -RenderAnisotropic 1 0 -RenderAvatarCloth 0 0 -RenderAvatarVP 0 0 -RenderObjectBump 0 0 -RenderLocalLights 1 0 -RenderMaxPartCount 1 1024 -RenderTerrainDetail 1 0 -RenderUseImpostors 0 0 -RenderVBOEnable 1 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - - -// -// CPU based feature masks -// - -// 1Ghz or less (equiv) -list CPUSlow -RenderMaxPartCount 1 1024 - -// -// RAM based feature masks -// -list RAM256MB -RenderObjectBump 0 0 - -// -// Graphics card based feature masks -// -list OpenGLPre15 -RenderVBOEnable 1 0 - -list OpenGLPre30 -RenderDeferred 0 0 - -list Intel -RenderAnisotropic 1 0 - -list GeForce2 -RenderAnisotropic 1 0 -RenderMaxPartCount 1 2048 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 1 - -list SiS -UseOcclusion 0 0 - - -list Intel_830M -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_845G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_855GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_865G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_900 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_915GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_915G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_945GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_950 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_965 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -UseOcclusion 0 0 - -list Intel_G33 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_G45 -WindLightUseAtmosShaders 0 0 - -list Intel_Bear_Lake -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Broadwater -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Brookdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Eaglelake -WindLightUseAtmosShaders 0 0 - -list Intel_Montara -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Springdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - - -list ATI_FireGL_5200 -RenderVBOEnable 1 0 -WindLightUseAtmosShaders 0 0 - - -list ATI_Mobility_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_Radeon -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_7500 -RenderVBOEnable 0 0 - -list ATI_Mobility_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - - -/// tweaked ATI to 96 Draw distance - -list ATI_Radeon_9000 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9200 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9500 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -/// tweaked ATI to 128 draw distance - -list ATI_Radeon_X300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Mobility_Radeon_X1xxx -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 - -list ATI_Radeon_HD_2300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2400 -Disregard128DefaultDrawDistance 1 0 -list ATI_ASUS_AH24xx -Disregard128DefaultDrawDistance 1 0 - - -// Avatar hardware skinning causes invisible avatars -// on various ATI chipsets on drivers before 8.2 - -list ATIOldDriver -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 - -// ATI cards generally perform better when not using VBOs for streaming data - -list ATI -RenderUseStreamVBO 1 0 -RenderAvatarVP 1 0 - -// Disable vertex buffer objects by default for ATI cards with little video memory -list ATIVramLT256 -RenderVBOEnable 1 0 - -/// Tweaked NVIDIA - -list NVIDIA_GeForce_FX_5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_FX_Go5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5300 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_6100 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6500 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6600 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_G73 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_Go_6100 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6200 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6500 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6600 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6700 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6800 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_7000 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7100 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7500 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7900 -RenderShaderLightingMaxLevel 1 2 - -list NVIDIA_GeForce_Go_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300_LE -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7900 -RenderShaderLightingMaxLevel 1 2 - +version 27 + +// NOTE: This is mostly identical to featuretable_mac.txt with a few differences +// Should be combined into one table + +// +// Generates lists of feature mask that can be applied on top of each other. +// +// // Begin comments +// list <name> +// Starts a feature list named <name> +// <name> <available> <recommended> +// <name> is the name of a feature +// <available> is 0 or 1, whether the feature is available +// <recommended> is an F32 which is the recommended value +// +// For now, the first list read sets up all of the default values +// + + +// +// All contains everything at their default settings for high end machines +// NOTE: All settings are set to the MIN of applied values, including 'all'! +// +list all +RenderAnisotropic 1 1 +RenderAvatarCloth 1 1 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxVisible 1 12 +RenderAvatarVP 1 1 +RenderCubeMap 1 1 +RenderDelayVBUpdate 1 0 +RenderFarClip 1 256 +RenderFlexTimeFactor 1 1.0 +RenderFogRatio 1 4.0 +RenderGamma 1 0 +RenderGlowResolutionPow 1 9 +RenderGround 1 1 +RenderMaxPartCount 1 8192 +RenderNightBrightness 1 1.0 +RenderObjectBump 1 1 +RenderLocalLights 1 1 +RenderReflectionDetail 1 4 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 1.0 +RenderUseImpostors 1 1 +RenderVBOEnable 1 1 +RenderVolumeLODFactor 1 2.0 +UseStartScreen 1 1 +UseOcclusion 1 1 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 128 +Disregard128DefaultDrawDistance 1 1 +Disregard96DefaultDrawDistance 1 1 +RenderTextureMemoryMultiple 1 1.0 +RenderShaderLightingMaxLevel 1 3 +RenderDeferred 1 1 +SkyUseClassicClouds 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 +WatchdogDisabled 1 1 +RenderUseStreamVBO 1 1 + +// +// Low Graphics Settings +// +list Low +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderLocalLights 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +SkyUseClassicClouds 1 0 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// Mid Graphics Settings +// +list Mid +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.75 +RenderAvatarVP 1 1 +RenderFarClip 1 96 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 8 +RenderMaxPartCount 1 2048 +RenderObjectBump 1 1 +RenderLocalLights 1 1 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 1.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 0.5 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// High Graphics Settings (purty) +// +list High +RenderAnisotropic 1 1 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarVP 1 1 +RenderFarClip 1 128 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 9 +RenderMaxPartCount 1 4096 +RenderObjectBump 1 1 +RenderLocalLights 1 1 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 0.5 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// Ultra graphics (REALLY PURTY!) +// +list Ultra +RenderAnisotropic 1 1 +RenderAvatarCloth 1 1 +RenderAvatarLODFactor 1 1.0 +RenderAvatarVP 1 1 +RenderFarClip 1 256 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 9 +RenderMaxPartCount 1 8192 +RenderObjectBump 1 1 +RenderLocalLights 1 1 +RenderReflectionDetail 1 4 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 1.0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 2.0 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 128 +RenderDeferred 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 + +// +// Class Unknown Hardware (unknown) +// +list Unknown +RenderVBOEnable 1 0 + +// +// Class 0 Hardware (just old) +// +list Class0 +RenderVBOEnable 1 1 + +// +// Class 1 Hardware +// +list Class1 +RenderVBOEnable 1 1 + +// +// Class 2 Hardware (make it purty) +// +list Class2 +RenderVBOEnable 1 1 + +// +// Class 3 Hardware (make it purty) +// +list Class3 +RenderVBOEnable 1 1 + +// +// No Pixel Shaders available +// +list NoPixelShaders +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 +RenderReflectionDetail 0 0 +VertexShaderEnable 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + +// +// No Vertex Shaders available +// +list NoVertexShaders +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 +RenderReflectionDetail 0 0 +VertexShaderEnable 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + + +// +// "Default" setups for safe, low, medium, high +// +list safe +RenderAnisotropic 1 0 +RenderAvatarCloth 0 0 +RenderAvatarVP 0 0 +RenderObjectBump 0 0 +RenderLocalLights 1 0 +RenderMaxPartCount 1 1024 +RenderTerrainDetail 1 0 +RenderUseImpostors 0 0 +RenderVBOEnable 1 0 +RenderReflectionDetail 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + + +// +// CPU based feature masks +// + +// 1Ghz or less (equiv) +list CPUSlow +RenderMaxPartCount 1 1024 + +// +// RAM based feature masks +// +list RAM256MB +RenderObjectBump 0 0 + +// +// Graphics card based feature masks +// +list OpenGLPre15 +RenderVBOEnable 1 0 + +list OpenGLPre30 +RenderDeferred 0 0 + +list Intel +RenderAnisotropic 1 0 + +list GeForce2 +RenderAnisotropic 1 0 +RenderMaxPartCount 1 2048 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 1 + +list SiS +UseOcclusion 0 0 + + +list Intel_830M +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_845G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_855GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_865G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_900 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_915GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_915G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_945GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_945G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_950 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_965 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +UseOcclusion 0 0 + +list Intel_G33 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_G45 +WindLightUseAtmosShaders 0 0 + +list Intel_Bear_Lake +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Broadwater +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Brookdale +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Eaglelake +WindLightUseAtmosShaders 0 0 + +list Intel_Montara +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Springdale +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + + +list ATI_FireGL_5200 +RenderVBOEnable 1 0 +WindLightUseAtmosShaders 0 0 + + +list ATI_Mobility_Radeon_7xxx +RenderVBOEnable 0 0 + +list ATI_Radeon_7xxx +RenderVBOEnable 0 0 + +list ATI_All-in-Wonder_Radeon +RenderVBOEnable 0 0 + +list ATI_All-in-Wonder_7500 +RenderVBOEnable 0 0 + +list ATI_Mobility_Radeon_9600 +Disregard96DefaultDrawDistance 1 0 + + +/// tweaked ATI to 96 Draw distance + +list ATI_Radeon_9000 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9200 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9500 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9600 +Disregard96DefaultDrawDistance 1 0 + +/// tweaked ATI to 128 draw distance + +list ATI_Radeon_X300 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X400 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X500 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X600 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X700 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1300 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +UseStartScreen 0 0 +list ATI_Radeon_X1400 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1500 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +UseStartScreen 0 0 +list ATI_Radeon_X1600 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1700 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Mobility_Radeon_X1xxx +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 + +list ATI_Radeon_HD_2300 +Disregard128DefaultDrawDistance 1 0 +list ATI_Radeon_HD_2400 +Disregard128DefaultDrawDistance 1 0 +list ATI_ASUS_AH24xx +Disregard128DefaultDrawDistance 1 0 + + +// Avatar hardware skinning causes invisible avatars +// on various ATI chipsets on drivers before 8.2 + +list ATIOldDriver +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 + +// ATI cards generally perform better when not using VBOs for streaming data + +list ATI +RenderUseStreamVBO 1 0 +RenderAvatarVP 1 0 + +// Disable vertex buffer objects by default for ATI cards with little video memory +list ATIVramLT256 +RenderVBOEnable 1 0 + +/// Tweaked NVIDIA + +list NVIDIA_GeForce_FX_5100 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5200 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5500 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5600 +Disregard96DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_FX_Go5100 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5200 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5300 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5500 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5600 +Disregard96DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_6100 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6200 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6500 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6600 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_G73 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_Go_6100 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6200 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6500 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6600 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6700 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6800 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7200 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7300 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7400 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 + +list NVIDIA_GeForce_Go_7200 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7400 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 + diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index c7ad0df50bf006ba92f52aa8e31f857935159a68..e86663b748fb1b7e4313e51c288d1b45da7adecc 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -26,6 +26,7 @@ list all RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxVisible 1 12 RenderAvatarVP 1 1 RenderCubeMap 1 1 @@ -70,6 +71,7 @@ list Low RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxVisible 1 3 RenderAvatarVP 1 0 RenderFarClip 1 64 @@ -100,6 +102,7 @@ list Mid RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.75 RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 @@ -128,6 +131,7 @@ list High RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 @@ -156,6 +160,7 @@ list Ultra RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 5cc9f44a5f94bc2fb9de0523783b233ff4d59f7a..e715054c54e6a02568dbeb1abaf1f0b2750f6961 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -26,6 +26,7 @@ list all RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxVisible 1 12 RenderAvatarVP 1 0 RenderCubeMap 1 1 @@ -69,6 +70,7 @@ list Low RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxVisible 1 3 RenderAvatarVP 1 0 RenderFarClip 1 64 @@ -97,6 +99,7 @@ list Mid RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.75 RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 @@ -123,6 +126,7 @@ list High RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 @@ -149,6 +153,7 @@ list Ultra RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index 10aeffef0184b2987c47efc28e6ab7d21086eeab..08fb67a0c87e0c048ca1bb888a1d335cfdf322e4 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -1,569 +1,574 @@ -version 27 - -// NOTE: This is mostly identical to featuretable_mac.txt with a few differences -// Should be combined into one table - -// -// Generates lists of feature mask that can be applied on top of each other. -// -// // Begin comments -// list <name> -// Starts a feature list named <name> -// <name> <available> <recommended> -// <name> is the name of a feature -// <available> is 0 or 1, whether the feature is available -// <recommended> is an F32 which is the recommended value -// -// For now, the first list read sets up all of the default values -// - - -// -// All contains everything at their default settings for high end machines -// NOTE: All settings are set to the MIN of applied values, including 'all'! -// -list all -RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 -RenderAvatarLODFactor 1 1.0 -RenderAvatarMaxVisible 1 12 -RenderAvatarVP 1 1 -RenderCubeMap 1 1 -RenderDelayVBUpdate 1 0 -RenderFarClip 1 256 -RenderFlexTimeFactor 1 1.0 -RenderFogRatio 1 4.0 -RenderGamma 1 0 -RenderGlowResolutionPow 1 9 -RenderGround 1 1 -RenderLocalLights 1 1 -RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 -RenderObjectBump 1 1 -RenderReflectionDetail 1 4 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 1.0 -RenderUseImpostors 1 1 -RenderVBOEnable 1 1 -RenderVolumeLODFactor 1 2.0 -UseStartScreen 1 1 -UseOcclusion 1 1 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 128 -Disregard128DefaultDrawDistance 1 1 -Disregard96DefaultDrawDistance 1 1 -RenderTextureMemoryMultiple 1 1.0 -RenderShaderLightingMaxLevel 1 3 -SkyUseClassicClouds 1 1 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 -WatchdogDisabled 1 1 -RenderUseStreamVBO 1 1 - -// -// Low Graphics Settings -// -list Low -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarMaxVisible 1 3 -RenderAvatarVP 1 0 -RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 -RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 -RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 -WindLightUseAtmosShaders 1 0 -WLSkyDetail 1 48 -SkyUseClassicClouds 1 0 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// Mid Graphics Settings -// -list Mid -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0.5 -RenderAvatarVP 1 1 -RenderFarClip 1 96 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 8 -RenderLocalLights 1 1 -RenderMaxPartCount 1 2048 -RenderObjectBump 1 1 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 1.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 0.5 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 0 -WLSkyDetail 1 48 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// High Graphics Settings (purty) -// -list High -RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 1.0 -RenderAvatarVP 1 1 -RenderFarClip 1 128 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 9 -RenderLocalLights 1 1 -RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 0.5 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 48 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// Ultra graphics (REALLY PURTY!) -// -list Ultra -RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 -RenderAvatarLODFactor 1 1.0 -RenderAvatarVP 1 1 -RenderFarClip 1 256 -RenderFlexTimeFactor 1 1.0 -RenderGlowResolutionPow 1 9 -RenderLocalLights 1 1 -RenderMaxPartCount 1 8192 -RenderObjectBump 1 1 -RenderReflectionDetail 1 4 -RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 -RenderTreeLODFactor 1 1.0 -RenderUseImpostors 1 1 -RenderVolumeLODFactor 1 2.0 -VertexShaderEnable 1 1 -WindLightUseAtmosShaders 1 1 -WLSkyDetail 1 128 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderShadowDetail 1 0 - -// -// Class Unknown Hardware (unknown) -// -list Unknown -RenderVBOEnable 1 0 - -// -// Class 0 Hardware (just old) -// -list Class0 -RenderVBOEnable 1 1 - -// -// Class 1 Hardware -// -list Class1 -RenderVBOEnable 1 1 - -// -// Class 2 Hardware (make it purty) -// -list Class2 -RenderVBOEnable 1 1 - -// -// Class 3 Hardware (make it purty) -// -list Class3 -RenderVBOEnable 1 1 - -// -// No Pixel Shaders available -// -list NoPixelShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -VertexShaderEnable 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - -// -// No Vertex Shaders available -// -list NoVertexShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -VertexShaderEnable 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - -// -// "Default" setups for safe, low, medium, high -// -list safe -RenderAnisotropic 1 0 -RenderAvatarCloth 0 0 -RenderAvatarVP 0 0 -RenderObjectBump 0 0 -RenderMaxPartCount 1 1024 -RenderTerrainDetail 1 0 -RenderUseImpostors 0 0 -RenderVBOEnable 1 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 - -// -// CPU based feature masks -// - -// 1Ghz or less (equiv) -list CPUSlow -RenderMaxPartCount 1 1024 - -// -// RAM based feature masks -// -list RAM256MB -RenderObjectBump 0 0 - -// -// Graphics card based feature masks -// -list OpenGLPre15 -RenderVBOEnable 1 0 - -list OpenGLPre30 -RenderDeferred 0 0 - -list Intel -RenderAnisotropic 1 0 - -list GeForce2 -RenderAnisotropic 1 0 -RenderMaxPartCount 1 2048 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 1 - -list SiS -UseOcclusion 0 0 - - -list Intel_830M -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_845G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_855GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_865G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_900 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_915GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_915G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 0 0 - -list Intel_945GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_950 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_965 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderUseImpostors 1 0 -UseOcclusion 0 0 - -list Intel_G33 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_G45 -WindLightUseAtmosShaders 0 0 - -list Intel_Bear_Lake -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Broadwater -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Brookdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Eaglelake -WindLightUseAtmosShaders 0 0 - -list Intel_Montara -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Springdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - - -list ATI_FireGL_5200 -RenderVBOEnable 1 0 -WindLightUseAtmosShaders 0 0 - - -list ATI_Mobility_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_Radeon -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_7500 -RenderVBOEnable 0 0 - -list ATI_Mobility_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - - -/// tweaked ATI to 96 Draw distance - -list ATI_Radeon_9000 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9200 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9500 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -/// tweaked ATI to 128 draw distance - -list ATI_Radeon_X300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Mobility_Radeon_X1xxx -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 - -list ATI_Radeon_HD_2300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2400 -Disregard128DefaultDrawDistance 1 0 -list ATI_ASUS_AH24xx -Disregard128DefaultDrawDistance 1 0 - - -// Avatar hardware skinning causes invisible avatars -// on various ATI chipsets on drivers before 8.2 - -list ATIOldDriver -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 - -// ATI cards generally perform better when not using VBOs for streaming data - -list ATI -RenderUseStreamVBO 1 0 -RenderAvatarVP 1 0 - -// Disable vertex buffer objects by default for ATI cards with little video memory -list ATIVramLT256 -RenderVBOEnable 1 0 - -/// Tweaked NVIDIA - -list NVIDIA_GeForce_FX_5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_FX_Go5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5300 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_6100 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6500 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6600 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_G73 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_Go_6100 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6200 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6500 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6600 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6700 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6800 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_7000 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7100 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7500 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7900 -RenderShaderLightingMaxLevel 1 2 - -list NVIDIA_GeForce_Go_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300_LE -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7900 -RenderShaderLightingMaxLevel 1 2 - +version 27 + +// NOTE: This is mostly identical to featuretable_mac.txt with a few differences +// Should be combined into one table + +// +// Generates lists of feature mask that can be applied on top of each other. +// +// // Begin comments +// list <name> +// Starts a feature list named <name> +// <name> <available> <recommended> +// <name> is the name of a feature +// <available> is 0 or 1, whether the feature is available +// <recommended> is an F32 which is the recommended value +// +// For now, the first list read sets up all of the default values +// + + +// +// All contains everything at their default settings for high end machines +// NOTE: All settings are set to the MIN of applied values, including 'all'! +// +list all +RenderAnisotropic 1 1 +RenderAvatarCloth 1 1 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxVisible 1 12 +RenderAvatarVP 1 1 +RenderCubeMap 1 1 +RenderDelayVBUpdate 1 0 +RenderFarClip 1 256 +RenderFlexTimeFactor 1 1.0 +RenderFogRatio 1 4.0 +RenderGamma 1 0 +RenderGlowResolutionPow 1 9 +RenderGround 1 1 +RenderLocalLights 1 1 +RenderMaxPartCount 1 8192 +RenderNightBrightness 1 1.0 +RenderObjectBump 1 1 +RenderReflectionDetail 1 4 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 1.0 +RenderUseImpostors 1 1 +RenderVBOEnable 1 1 +RenderVolumeLODFactor 1 2.0 +UseStartScreen 1 1 +UseOcclusion 1 1 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 128 +Disregard128DefaultDrawDistance 1 1 +Disregard96DefaultDrawDistance 1 1 +RenderTextureMemoryMultiple 1 1.0 +RenderShaderLightingMaxLevel 1 3 +SkyUseClassicClouds 1 1 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +WatchdogDisabled 1 1 +RenderUseStreamVBO 1 1 + +// +// Low Graphics Settings +// +list Low +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +SkyUseClassicClouds 1 0 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// Mid Graphics Settings +// +list Mid +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.75 +RenderAvatarVP 1 1 +RenderFarClip 1 96 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 1 +RenderMaxPartCount 1 2048 +RenderObjectBump 1 1 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 1.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 0.5 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// High Graphics Settings (purty) +// +list High +RenderAnisotropic 1 1 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarVP 1 1 +RenderFarClip 1 128 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 9 +RenderLocalLights 1 1 +RenderMaxPartCount 1 4096 +RenderObjectBump 1 1 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 0.5 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// Ultra graphics (REALLY PURTY!) +// +list Ultra +RenderAnisotropic 1 1 +RenderAvatarCloth 1 1 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarVP 1 1 +RenderFarClip 1 256 +RenderFlexTimeFactor 1 1.0 +RenderGlowResolutionPow 1 9 +RenderLocalLights 1 1 +RenderMaxPartCount 1 8192 +RenderObjectBump 1 1 +RenderReflectionDetail 1 4 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 1.0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 2.0 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 1 +WLSkyDetail 1 128 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + +// +// Class Unknown Hardware (unknown) +// +list Unknown +RenderVBOEnable 1 0 + +// +// Class 0 Hardware (just old) +// +list Class0 +RenderVBOEnable 1 1 + +// +// Class 1 Hardware +// +list Class1 +RenderVBOEnable 1 1 + +// +// Class 2 Hardware (make it purty) +// +list Class2 +RenderVBOEnable 1 1 + +// +// Class 3 Hardware (make it purty) +// +list Class3 +RenderVBOEnable 1 1 + +// +// No Pixel Shaders available +// +list NoPixelShaders +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 +RenderReflectionDetail 0 0 +VertexShaderEnable 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + +// +// No Vertex Shaders available +// +list NoVertexShaders +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 +RenderReflectionDetail 0 0 +VertexShaderEnable 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + +// +// "Default" setups for safe, low, medium, high +// +list safe +RenderAnisotropic 1 0 +RenderAvatarCloth 0 0 +RenderAvatarVP 0 0 +RenderObjectBump 0 0 +RenderMaxPartCount 1 1024 +RenderTerrainDetail 1 0 +RenderUseImpostors 0 0 +RenderVBOEnable 1 0 +RenderReflectionDetail 0 0 +WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + +// +// CPU based feature masks +// + +// 1Ghz or less (equiv) +list CPUSlow +RenderMaxPartCount 1 1024 + +// +// RAM based feature masks +// +list RAM256MB +RenderObjectBump 0 0 + +// +// Graphics card based feature masks +// +list OpenGLPre15 +RenderVBOEnable 1 0 + +list OpenGLPre30 +RenderDeferred 0 0 + +list Intel +RenderAnisotropic 1 0 + +list GeForce2 +RenderAnisotropic 1 0 +RenderMaxPartCount 1 2048 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 1 + +list SiS +UseOcclusion 0 0 + + +list Intel_830M +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_845G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_855GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_865G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_900 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_915GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_915G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 0 0 + +list Intel_945GM +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_945G +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_950 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_965 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 +RenderUseImpostors 1 0 +UseOcclusion 0 0 + +list Intel_G33 +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_G45 +WindLightUseAtmosShaders 0 0 + +list Intel_Bear_Lake +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Broadwater +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Brookdale +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Eaglelake +WindLightUseAtmosShaders 0 0 + +list Intel_Montara +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + +list Intel_Springdale +RenderTerrainDetail 1 0 +RenderVBOEnable 1 0 + + +list ATI_FireGL_5200 +RenderVBOEnable 1 0 +WindLightUseAtmosShaders 0 0 + + +list ATI_Mobility_Radeon_7xxx +RenderVBOEnable 0 0 + +list ATI_Radeon_7xxx +RenderVBOEnable 0 0 + +list ATI_All-in-Wonder_Radeon +RenderVBOEnable 0 0 + +list ATI_All-in-Wonder_7500 +RenderVBOEnable 0 0 + +list ATI_Mobility_Radeon_9600 +Disregard96DefaultDrawDistance 1 0 + + +/// tweaked ATI to 96 Draw distance + +list ATI_Radeon_9000 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9200 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9500 +Disregard96DefaultDrawDistance 1 0 +list ATI_Radeon_9600 +Disregard96DefaultDrawDistance 1 0 + +/// tweaked ATI to 128 draw distance + +list ATI_Radeon_X300 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X400 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X500 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X600 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X700 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1300 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +UseStartScreen 0 0 +list ATI_Radeon_X1400 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1500 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +UseStartScreen 0 0 +list ATI_Radeon_X1600 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Radeon_X1700 +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 +list ATI_Mobility_Radeon_X1xxx +Disregard128DefaultDrawDistance 1 0 +RenderVBOEnable 1 0 + +list ATI_Radeon_HD_2300 +Disregard128DefaultDrawDistance 1 0 +list ATI_Radeon_HD_2400 +Disregard128DefaultDrawDistance 1 0 +list ATI_ASUS_AH24xx +Disregard128DefaultDrawDistance 1 0 + + +// Avatar hardware skinning causes invisible avatars +// on various ATI chipsets on drivers before 8.2 + +list ATIOldDriver +RenderAvatarVP 0 0 +RenderAvatarCloth 0 0 + +// ATI cards generally perform better when not using VBOs for streaming data + +list ATI +RenderUseStreamVBO 1 0 +RenderAvatarVP 1 0 + +// Disable vertex buffer objects by default for ATI cards with little video memory +list ATIVramLT256 +RenderVBOEnable 1 0 + +/// Tweaked NVIDIA + +list NVIDIA_GeForce_FX_5100 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5200 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5500 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_5600 +Disregard96DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_FX_Go5100 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5200 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5300 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5500 +Disregard96DefaultDrawDistance 1 0 +list NVIDIA_GeForce_FX_Go5600 +Disregard96DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_6100 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6200 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6500 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_6600 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_G73 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_Go_6100 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6200 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6500 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6600 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6700 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6800 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_Go_6 +RenderVBOEnable 1 0 +Disregard128DefaultDrawDistance 1 0 + +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7200 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7300 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7400 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 + +list NVIDIA_GeForce_Go_7200 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7400 +Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 + diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index d2df968544011e9f9ae4d2b18c8f1925c115f09f..283a28a0aa47b8c22401ff76c274afedbbf90a00 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -92,23 +92,23 @@ cd "${RUN_PATH}" ## subprocesses that care. export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" -if [ -n "$LL_TCMALLOC" ]; then - tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0' - all=1 - for f in $tcmalloc_libs; do - if [ ! -f $f ]; then - all=0 - fi - done - if [ $all != 1 ]; then - echo 'Cannot use tcmalloc libraries: components missing' 1>&2 - else - export LD_PRELOAD=$(echo $tcmalloc_libs | tr ' ' :) - if [ -z "$HEAPCHECK" -a -z "$HEAPPROFILE" ]; then - export HEAPCHECK=${HEAPCHECK:-normal} - fi - fi -fi +# if [ -n "$LL_TCMALLOC" ]; then +# tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0' +# all=1 +# for f in $tcmalloc_libs; do +# if [ ! -f $f ]; then +# all=0 +# fi +# done +# if [ $all != 1 ]; then +# echo 'Cannot use tcmalloc libraries: components missing' 1>&2 +# else +# export LD_PRELOAD=$(echo $tcmalloc_libs | tr ' ' :) +# if [ -z "$HEAPCHECK" -a -z "$HEAPPROFILE" ]; then +# export HEAPCHECK=${HEAPCHECK:-normal} +# fi +# fi +#fi export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"' export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-secondlife-bin' diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 790f98e75d9fed57fe80c7726d35310186e90188..f4023502f64533026f4a4fae59d7d7ca9f6aba01 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1343,7 +1343,7 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) //NB: auto pilot can terminate for a reason other than reaching the destination if (mAutoPilotFinishedCallback) { - mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData); + mAutoPilotFinishedCallback(!user_cancel && dist_vec_squared(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < (mAutoPilotStopDistance * mAutoPilotStopDistance), mAutoPilotCallbackData); } mLeaderID = LLUUID::null; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 24c816d58d80f6149e81b4c95ef6030876f1e3a2..1388d9aee010e87806b0efdccf6488be97cd2e1d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -110,6 +110,12 @@ class LLAppearanceHandler : public LLCommandHandler { // support secondlife:///app/appearance/show, but for now we just // make all secondlife:///app/appearance SLapps behave this way + if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAppearance")) + { + LLNotificationsUtil::add("NoAppearance", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD()); return true; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5dc803e2871f91c444860f2a5a756cc40a27ea37..e304729839d1531c6f640a3021b0a1170a2c6ce1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3578,10 +3578,10 @@ bool LLAppViewer::initCache() LLAppViewer::getTextureCache()->setReadOnly(read_only) ; LLVOCache::getInstance()->setReadOnly(read_only); - BOOL texture_cache_mismatch = FALSE ; + bool texture_cache_mismatch = false; if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) { - texture_cache_mismatch = TRUE ; + texture_cache_mismatch = true; if(!read_only) { gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); @@ -3595,7 +3595,9 @@ bool LLAppViewer::initCache() gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) { gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; + mPurgeCache = true; + // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad + texture_cache_mismatch = true; } // We have moved the location of the cache directory over time. diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index ca7ec7cc30a7ce8727ceb25ec4e3400b97aac762..cbbdcb2983fc6d47b767b23d817f49b5fb2d9ec3 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -302,8 +302,14 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids) static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) { - llinfos << "opening web profile for " << av_name.mUsername << llendl; - std::string url = getProfileURL(av_name.mUsername); + std::string username = av_name.mUsername; + if (username.empty()) + { + username = LLCacheName::buildUsername(av_name.mDisplayName); + } + + llinfos << "opening web profile for " << username << llendl; + std::string url = getProfileURL(username); // PROFILES: open in webkit window LLWeb::loadWebURLInternal(url, "", agent_id.asString()); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 0371b7be7132e76b0a1015a334877465f6c13dc9..b6482e0ec473d7eec8ee85cdf935e374d0e726a8 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -492,26 +492,6 @@ void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask) mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Select_All", in_edit_box); } -void LLBottomTray::showGestureButton(BOOL visible) -{ - setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible); -} - -void LLBottomTray::showMoveButton(BOOL visible) -{ - setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible); -} - -void LLBottomTray::showCameraButton(BOOL visible) -{ - setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible); -} - -void LLBottomTray::showSnapshotButton(BOOL visible) -{ - setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible); -} - void LLBottomTray::showSpeakButton(bool visible) { // Show/hide the button @@ -936,15 +916,14 @@ void LLBottomTray::log(LLView* panel, const std::string& descr) { if (NULL == panel) return; LLView* layout = panel->getParent(); - lldebugs << descr << ": " + LL_DEBUGS("Bottom Tray Rects") << descr << ": " << "panel: " << panel->getName() << ", rect: " << panel->getRect() - << "layout: " << layout->getName() + << " layout: " << layout->getName() << ", rect: " << layout->getRect() - << llendl - ; + << LL_ENDL; } void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -964,7 +943,9 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) if (mNearbyChatBar) log(mNearbyChatBar, "before"); if (mChicletPanel) log(mChicletPanel, "before"); - // stores width size on which bottom tray is less than width required by its children. EXT-991 + // Difference between bottom tray width required to fit its children and the actual width. (see EXT-991) + // Positive value means that bottom tray is not wide enough. + // Negative value means that there is free space. static S32 extra_shrink_width = 0; bool should_be_reshaped = true; @@ -986,11 +967,9 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) // bottom tray is narrowed if (delta_width < 0) { - if (extra_shrink_width > 0) + if (extra_shrink_width > 0) // not enough space { - // is world rect was extra shrunk and decreasing again only update this value - // to delta_width negative - extra_shrink_width -= delta_width; // use "-=" because delta_width is negative + extra_shrink_width += llabs(delta_width); should_be_reshaped = false; } else @@ -1001,13 +980,13 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) width += extra_shrink_width; } } - // bottom tray is widen + // bottom tray is widened else { if (extra_shrink_width > delta_width) { - // Less than minimum width is more than increasing (delta_width) - // only reduce it value and make no reshape + // Still not enough space. + // Only subtract the delta from the required delta and don't reshape. extra_shrink_width -= delta_width; should_be_reshaped = false; } @@ -1047,6 +1026,7 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) { mDesiredNearbyChatWidth = new_width; processChatbarCustomization(new_width); + lldebugs << "Setting nearby chat bar width to " << new_width << " px" << llendl; mChatBarContainer->reshape(new_width, mChatBarContainer->getRect().getHeight()); } needs_restore_custom_state = false; @@ -1058,30 +1038,28 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) { bool still_should_be_processed = true; - const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + const S32 chiclet_panel_shrink_headroom = getChicletPanelShrinkHeadroom(); // There are four steps of processing width decrease. If in one of them required width was reached, // further are not needed. // 1. Decreasing width of chiclet panel. - if (chiclet_panel_width > chiclet_panel_min_width) + if (chiclet_panel_shrink_headroom > 0) { // we have some space to decrease chiclet panel - S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width; - - S32 delta_panel = llmin(-delta_width, panel_delta_min); + S32 shrink_by = llmin(-delta_width, chiclet_panel_shrink_headroom); lldebugs << "delta_width: " << delta_width - << ", panel_delta_min: " << panel_delta_min - << ", delta_panel: " << delta_panel + << ", panel_delta_min: " << chiclet_panel_shrink_headroom + << ", shrink_by: " << shrink_by << llendl; - // is chiclet panel width enough to process resizing? - delta_width += panel_delta_min; + // is chiclet panel wide enough to process resizing? + delta_width += chiclet_panel_shrink_headroom; still_should_be_processed = delta_width < 0; - mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight()); + lldebugs << "Shrinking chiclet panel by " << shrink_by << " px" << llendl; + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - shrink_by, mChicletPanel->getParent()->getRect().getHeight()); log(mChicletPanel, "after processing panel decreasing via chiclet panel"); lldebugs << "RS_CHICLET_PANEL" @@ -1105,7 +1083,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) S32 delta_panel = llmin(-delta_width, panel_delta_min); - // whether chatbar panel width is enough to process resizing? + // is chatbar panel wide enough to process resizing? delta_width += panel_delta_min; still_should_be_processed = delta_width < 0; @@ -1113,6 +1091,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) // chatbar should only be shrunk here, not stretched if(delta_panel > 0) { + lldebugs << "Shrinking nearby chat bar by " << delta_panel << " px " << llendl; mChatBarContainer->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mChatBarContainer->getRect().getHeight()); } @@ -1144,6 +1123,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) { S32 compensative_width = nearby_needed_width > buttons_freed_width ? buttons_freed_width : nearby_needed_width; log(mNearbyChatBar, "before applying compensative width"); + lldebugs << "Extending nearby chat bar by " << compensative_width << " px" << llendl; mChatBarContainer->reshape(mChatBarContainer->getRect().getWidth() + compensative_width, mChatBarContainer->getRect().getHeight() ); log(mNearbyChatBar, "after applying compensative width"); lldebugs << buttons_freed_width << llendl; @@ -1158,52 +1138,46 @@ void LLBottomTray::processWidthIncreased(S32 delta_width) { if (delta_width <= 0) return; - const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); - - const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width; + // how much room we have to show hidden buttons + S32 available_width = delta_width + getChicletPanelShrinkHeadroom(); - // how many room we have to show hidden buttons - S32 total_available_width = delta_width + available_width_chiclet; - - lldebugs << "Processing extending, available width:" - << ", chiclets - " << available_width_chiclet - << ", total - " << total_available_width - << llendl; + lldebugs << "Distributing (" << getChicletPanelShrinkHeadroom() + << " + " << delta_width << ") = " << available_width << " px" << llendl; - S32 available_width = total_available_width; + // 1. Try showing buttons that have been auto-hidden. + S32 processed_width = processShowButtons(available_width); + lldebugs << "processed_width = " << processed_width << ", delta_width = " << delta_width << llendl; - processShowButtons(available_width); + lldebugs << "Available_width after showing buttons: " << available_width << llendl; - // if we have to show/extend some buttons but resized delta width is not enough... - S32 processed_width = total_available_width - available_width; + // If the newly shown buttons have consumed more than delta_width pixels, + // shrink the chiclet panel. if (processed_width > delta_width) { - // ... let's shrink nearby chat & chiclet panels - S32 required_to_process_width = processed_width; - // 1. use delta width of resizing - required_to_process_width -= delta_width; + S32 shrink_by = processed_width - delta_width; // 2. use width available via decreasing of chiclet panel - if (required_to_process_width > 0) + if (shrink_by > 0) { - mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight()); + lldebugs << "Shrinking chiclet panel by " << shrink_by << " px" << llendl; + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - shrink_by, mChicletPanel->getParent()->getRect().getHeight()); log(mChicletPanel, "after applying compensative width for chiclets: "); - lldebugs << required_to_process_width << llendl; + lldebugs << shrink_by << llendl; } + // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels + delta_width -= processed_width; } - // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels - delta_width -= processed_width; - - - // how many space can nearby chatbar take? - S32 chatbar_panel_width_ = mChatBarContainer->getRect().getWidth(); - if (delta_width > 0 && chatbar_panel_width_ < mDesiredNearbyChatWidth) + // 2. Expand the nearby chat bar if needed. + S32 chatbar_panel_width = mChatBarContainer->getRect().getWidth(); + lldebugs << "delta_width = " << delta_width + << ", chatbar_panel_width = " << chatbar_panel_width + << ", mDesiredNearbyChatWidth = " << mDesiredNearbyChatWidth << llendl; + if (delta_width > 0 && chatbar_panel_width < mDesiredNearbyChatWidth) { - S32 delta_panel_max = mDesiredNearbyChatWidth - chatbar_panel_width_; + S32 delta_panel_max = mDesiredNearbyChatWidth - chatbar_panel_width; S32 delta_panel = llmin(delta_width, delta_panel_max); lldebugs << "Unprocesed delta width: " << delta_width << ", can be applied to chatbar: " << delta_panel_max @@ -1211,17 +1185,25 @@ void LLBottomTray::processWidthIncreased(S32 delta_width) << llendl; delta_width -= delta_panel_max; - mChatBarContainer->reshape(chatbar_panel_width_ + delta_panel, mChatBarContainer->getRect().getHeight()); + lldebugs << "Extending nearby chat bar by " << delta_panel << " px " << llendl; + mChatBarContainer->reshape(chatbar_panel_width + delta_panel, mChatBarContainer->getRect().getHeight()); log(mNearbyChatBar, "applied unprocessed delta width"); } + + // 3. Expand buttons that have been auto-shrunk, + // if we haven't yet consumed all the available headroom. if (delta_width > 0) { - processExtendButtons(delta_width); + S32 available_width = delta_width + getChicletPanelShrinkHeadroom(); + processExtendButtons(available_width); } } -void LLBottomTray::processShowButtons(S32& available_width) +S32 LLBottomTray::processShowButtons(S32& available_width) { + lldebugs << "Distributing " << available_width << " px" << llendl; + S32 original_available_width = available_width; + // process buttons from left to right resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); @@ -1234,37 +1216,20 @@ void LLBottomTray::processShowButtons(S32& available_width) // try to show next button processShowButton(*it, available_width); } + + return original_available_width - available_width; } bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32& available_width) { - lldebugs << "Trying to show object type: " << shown_object_type << llendl; - - LLPanel* panel = getButtonPanel(shown_object_type); - if (NULL == panel) + // Check if the button was previously auto-hidden (due to lack of space). + if (!isAutoHidden(shown_object_type)) { - lldebugs << "There is no object to process for state: " << shown_object_type << llendl; return false; } - bool can_be_shown = canButtonBeShown(shown_object_type); - if (can_be_shown) - { - //validate if we have enough room to show this button - const S32 required_width = panel->getRect().getWidth(); - can_be_shown = available_width >= required_width; - if (can_be_shown) - { - available_width -= required_width; - - setTrayButtonVisible(shown_object_type, true); - lldebugs << "processed object type: " << shown_object_type - << ", rest available width: " << available_width - << llendl; - mResizeState &= ~shown_object_type; - } - } - return can_be_shown; + // Ok. Try showing the button. + return showButton(shown_object_type, available_width); } void LLBottomTray::processHideButtons(S32& required_width, S32& buttons_freed_width) @@ -1289,7 +1254,6 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& re LLPanel* panel = getButtonPanel(processed_object_type); if (NULL == panel) { - lldebugs << "There is no object to process for state: " << processed_object_type << llendl; return; } @@ -1304,7 +1268,7 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& re setTrayButtonVisible(processed_object_type, false); - mResizeState |= processed_object_type; + setAutoHidden(processed_object_type, true); lldebugs << "processing object type: " << processed_object_type << ", buttons_freed_width: " << buttons_freed_width @@ -1369,7 +1333,6 @@ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& LLPanel* panel = getButtonPanel(processed_object_type); if (NULL == panel) { - lldebugs << "There is no object to process for type: " << processed_object_type << llendl; return; } @@ -1414,122 +1377,130 @@ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& void LLBottomTray::processExtendButtons(S32& available_width) { // do not allow extending any buttons if we have some buttons hidden via resize - if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return; + if (isAutoHidden(RS_BUTTONS_CAN_BE_HIDDEN)) return; - // process buttons from left to right - resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); - const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); + lldebugs << "Distributing " << available_width << " px" << llendl; - // iterate through buttons in the mButtonsProcessOrder first - for (; it != it_end; ++it) + // First try extending the Speak button. + if (available_width > 0) { - // is there available space? - if (available_width <= 0) break; - - // try to extend next button - processExtendButton(*it, available_width); + if (!processExtendSpeakButton(available_width)) + { + // The Speak button needs extension but lacks some space. + // Don't extend other buttons in this case: the Speak button + // should consume the available headroom first. + return; + } } - const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); - const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width; + // Then process the other buttons from left to right. + if (available_width > 0) + { + resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); + const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); + + // iterate through buttons in the mButtonsProcessOrder first + for (; it != it_end; ++it) + { + // is there available space? + if (available_width <= 0) break; - // then try to extend Speak button - if (available_width > 0 || available_width_chiclet > 0) + // try to extend next button + processExtendButton(*it, available_width); + } + } +} + +bool LLBottomTray::processExtendSpeakButton(S32& available_width) +{ + if (available_width <= 0) { - S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK]; - S32 panel_width = mSpeakPanel->getRect().getWidth(); - S32 possible_extend_width = panel_max_width - panel_width; + llassert(available_width > 0); + return true; + } - if (possible_extend_width >= 0 && possible_extend_width <= available_width + available_width_chiclet) // HACK: this button doesn't change size so possible_extend_width will be 0 + const S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK]; + const S32 panel_width = mSpeakPanel->getRect().getWidth(); + const S32 required_headroom = panel_max_width - panel_width; + + if (panel_width < panel_max_width) // if the button isn't extended already + { + if (available_width < required_headroom) // not enough space { - mSpeakBtn->setLabelVisible(true); - mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight()); - log(mSpeakBtn, "speak button is extended"); + lldebugs << "Need (" << required_headroom << " - " << available_width << ") = " + << (required_headroom - available_width) << " more px" + << " to extend the Speak button"<< llendl; - if( available_width > possible_extend_width) - { - available_width -= possible_extend_width; - } - else - { - S32 required_width = possible_extend_width - available_width; - available_width = 0; - mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_width, mChicletPanel->getParent()->getRect().getHeight()); - } - lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName() - << ", extended width: " << possible_extend_width - << ", rest width to process: " << available_width - << llendl; + return false; // Don't extend other buttons until we extend Speak. } + + // Reshape the Speak button to its maximum width. + mSpeakBtn->setLabelVisible(true); + mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight()); + + available_width -= required_headroom; + llassert(available_width >= 0); + + lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName() + << ", extended width: " << required_headroom + << ", rest width to process: " << available_width + << llendl; } + + return true; } void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& available_width) { + llassert(available_width >= 0); + LLPanel* panel = getButtonPanel(processed_object_type); if (NULL == panel) { - lldebugs << "There is no object to process for type: " << processed_object_type << llendl; return; } if (!panel->getVisible()) return; + // Widen the button up to its maximum width, but by not more than <available_width> px. S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type]; S32 panel_width = panel->getRect().getWidth(); - S32 possible_extend_width = panel_max_width - panel_width; + S32 required_headroom = panel_max_width - panel_width; - if (possible_extend_width > 0) + S32 extend_by = llmin(available_width, required_headroom); + if (extend_by > 0) { - // let calculate real width to extend + panel->reshape(panel_width + extend_by, panel->getRect().getHeight()); - // 1. apply all possible width - available_width -= possible_extend_width; + // Decrease amount of headroom available for other panels. + available_width -= extend_by; - // 2. it it is too much... - if (available_width < 0) - { - // reduce applied extended width to the excessive value. - possible_extend_width += available_width; - available_width = 0; - } - panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight()); - - lldebugs << "Extending panel: " << panel->getName() - << ", extended width: " << possible_extend_width - << ", rest width to process: " << available_width + lldebugs << "Extending " << panel->getName() + << " by " << extend_by + << " px; remaining available width: " << available_width << llendl; } } bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const { - // 0. Check if passed button was previously hidden on resize - bool can_be_shown = mResizeState & processed_object_type; - if (can_be_shown) - { - // Yes, it was. Lets now check that all buttons before it (that can be hidden on resize) - // are already shown - - // process buttons in direct order (from left to right) - resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); - const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); + // Check that all buttons (that can be hidden on resize) + // to the left of the given one are already shown. - // 1. Find and accumulate all buttons types before one passed into the method. - MASK buttons_before_mask = RS_NORESIZE; - for (; it != it_end; ++it) - { - const EResizeState button_type = *it; - if (button_type == processed_object_type) break; + // process buttons in direct order (from left to right) + resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); + const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); - buttons_before_mask |= button_type; - } + MASK buttons_before_mask = RS_NORESIZE; + for (; it != it_end; ++it) + { + const EResizeState button_type = *it; + if (button_type == processed_object_type) break; - // 2. Check if some previous buttons are still hidden on resize - can_be_shown = !(buttons_before_mask & mResizeState); + buttons_before_mask |= button_type; } - return can_be_shown; + + return !isAutoHidden(buttons_before_mask); } void LLBottomTray::initResizeStateContainers() @@ -1592,6 +1563,7 @@ void LLBottomTray::initButtonsVisibility() setVisibleAndFitWidths(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton")); setVisibleAndFitWidths(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton")); setVisibleAndFitWidths(RS_BUTTON_MINI_MAP, gSavedSettings.getBOOL("ShowMiniMapButton")); + lldebugs << "mResizeState = " << resizeStateMaskToString(mResizeState) << llendl; } void LLBottomTray::setButtonsControlsAndListeners() @@ -1623,12 +1595,53 @@ bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, cons return true; } +bool LLBottomTray::showButton(EResizeState button_type, S32& available_width) +{ + LLPanel* panel = getButtonPanel(button_type); + if (NULL == panel) + { + return false; + } + + if (panel->getVisible()) + { + return false; + } + + // Check if none of the buttons to the left of the given one was auto-hidden. + // (we auto-show the buttons left to right). + if (!canButtonBeShown(button_type)) + { + return false; + } + + // Make sure we have enough room to show this button. + const S32 required_width = panel->getRect().getWidth(); + if (available_width < required_width) + { + lldebugs << "Need " << (required_width - available_width) << " more px to show " << resizeStateToString(button_type) << llendl; + return false; + } + + // All good. Show the button. + setTrayButtonVisible(button_type, true); + + // Let the caller know that there is now less available space. + available_width -= required_width; + + lldebugs << "Showing button " << resizeStateToString(button_type) + << ", remaining available width: " << available_width + << llendl; + setAutoHidden(button_type, false); + + return true; +} + void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible) { LLPanel* panel = getButtonPanel(shown_object_type); if (NULL == panel) { - lldebugs << "There is no object to show for state: " << shown_object_type << llendl; return; } @@ -1659,7 +1672,6 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible LLPanel* cur_panel = getButtonPanel(object_type); if (NULL == cur_panel) { - lldebugs << "There is no object to process for state: " << object_type << llendl; return false; } @@ -1668,17 +1680,13 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible if (visible) { // Assume that only chiclet panel can be auto-resized - const S32 available_width = - mChicletPanel->getParent()->getRect().getWidth() - mChicletPanel->getMinWidth(); + const S32 available_width = getChicletPanelShrinkHeadroom(); S32 preferred_width = mObjectDefaultWidthMap[object_type]; S32 current_width = cur_panel->getRect().getWidth(); S32 result_width = 0; bool decrease_width = false; - // Mark this button to be shown - mResizeState |= object_type; - if (preferred_width > 0 && available_width >= preferred_width) { result_width = preferred_width; @@ -1722,7 +1730,11 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible } else { - // Nothing can be done, give up... + lldebugs << "Need " << (minimal_width - available_width - possible_shrunk_width) + << " more px to show " << resizeStateToString(object_type) << llendl; + + // Make the button uppear when we have more available space. + setAutoHidden(object_type, true); return false; } } @@ -1733,7 +1745,7 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible current_width = result_width; } - is_set = processShowButton(object_type, current_width); + is_set = showButton(object_type, current_width); // Shrink buttons if needed if (is_set && decrease_width) @@ -1748,7 +1760,8 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible setTrayButtonVisible(object_type, false); // Mark button NOT to show while future bottom tray extending - mResizeState &= ~object_type; + lldebugs << "Removing " << resizeStateToString(object_type) << " from mResizeState" << llendl; + setAutoHidden(object_type, false); // Extend other buttons if need if (delta_width) @@ -1805,12 +1818,14 @@ void LLBottomTray::processChatbarCustomization(S32 new_width) if (delta_width == 0) return; + { + static unsigned dbg_cnt = 0; + lldebugs << llformat("*** (%03d) ************************************* %d", delta_width, ++dbg_cnt) << llendl; + } + mDesiredNearbyChatWidth = new_width; - LLView * chiclet_layout_panel = mChicletPanel->getParent(); - const S32 chiclet_min_width = get_panel_min_width(mToolbarStack, chiclet_layout_panel); - const S32 chiclet_panel_width = chiclet_layout_panel->getRect().getWidth(); - const S32 available_chiclet_shrink_width = chiclet_panel_width - chiclet_min_width; + const S32 available_chiclet_shrink_width = getChicletPanelShrinkHeadroom(); llassert(available_chiclet_shrink_width >= 0); if (delta_width > 0) // panel gets narrowly @@ -1829,6 +1844,16 @@ void LLBottomTray::processChatbarCustomization(S32 new_width) } } +S32 LLBottomTray::getChicletPanelShrinkHeadroom() const +{ + static const S32 min_width = mChicletPanel->getMinWidth(); + const S32 cur_width = mChicletPanel->getParent()->getRect().getWidth(); + + S32 shrink_headroom = cur_width - min_width; + llassert(shrink_headroom >= 0); // the panel cannot get narrower than the minimum + return shrink_headroom; +} + // static std::string LLBottomTray::resizeStateToString(EResizeState state) { @@ -1854,4 +1879,54 @@ std::string LLBottomTray::resizeStateToString(EResizeState state) return "UNKNOWN_BUTTON"; } +// static +std::string LLBottomTray::resizeStateMaskToString(MASK mask) +{ + std::string res; + + bool add_delimiter = false; + for (U32 i = 0; i < 16; i++) + { + EResizeState state = (EResizeState) (1 << i); + if (mask & state) + { + if (!add_delimiter) + { + add_delimiter = true; + } + else + { + res += ", "; + } + + res += resizeStateToString(state); + } + } + + if (res.empty()) + { + res = resizeStateToString(RS_NORESIZE); + } + + res += llformat(" (0x%X)", mask); + return res; +} + +bool LLBottomTray::isAutoHidden(MASK button_types) const +{ + return (mResizeState & button_types) != 0; +} + +void LLBottomTray::setAutoHidden(MASK button_types, bool hide) +{ + if (hide) + { + mResizeState |= button_types; + } + else + { + mResizeState &= ~button_types; + } +} + //EOF diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 04e5f5e9e07f478b25c4e520c29c77717551ada9..52bcd2ddacf90d3db0d72a885f366843794e6b57 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -112,10 +112,6 @@ class LLBottomTray void showBottomTrayContextMenu(S32 x, S32 y, MASK mask); - void showGestureButton(BOOL visible); - void showMoveButton(BOOL visible); - void showCameraButton(BOOL visible); - void showSnapshotButton(BOOL visible); void showSpeakButton(bool visible); void toggleMovementControls(); @@ -240,8 +236,9 @@ class LLBottomTray * * @params[in, out] available_width - reference to available width to be used to show buttons. * @see processShowButton() + * @return consumed pixels (difference in available width). */ - void processShowButtons(S32& available_width); + S32 processShowButtons(S32& available_width); /** * Tries to show panel with specified button using available width. @@ -316,6 +313,20 @@ class LLBottomTray */ void processExtendButtons(S32& available_width); + /** + * Extends the Speak button if there is anough headroom. + * + * Unlike other buttons, the Speak buttons has only two possible widths: + * the minimal one (without label) and the maximal (default) one. + * + * If the button is at its minimum width there is not enough headroom to + * reshape it to the maximum width, the method does nothing. + * + * @param available_width Available headroom. + * @return false if the button requires extension but there's not enough headroom, true otherwise. + */ + bool processExtendSpeakButton(S32& available_width); + /** * Extends shown button to increase total taken space. * @@ -364,6 +375,16 @@ class LLBottomTray */ static bool toggleShowButton(EResizeState button_type, const LLSD& new_visibility); + /** + * Show the button if there is enough space. + * + * @param[in] button_type - type of button to be shown. + * @param[in, out] available_width amount of available space on the bottom bar. + * + * @return true if button was shown, false that's not possible (not enough space, etc) + */ + bool showButton(EResizeState button_type, S32& available_width); + /** * Sets passed visibility to object specified by resize type. */ @@ -417,9 +438,27 @@ class LLBottomTray */ void processChatbarCustomization(S32 new_width); + /** + * @return difference between current chiclet panel width and the minimum. + */ + S32 getChicletPanelShrinkHeadroom() const; + /// Get button name for debugging. static std::string resizeStateToString(EResizeState state); + /// Dump a mask for debugging + static std::string resizeStateMaskToString(MASK mask); + + /// @return true if any of the the passed buttons have been auto-hidden due to lack of available space. + bool isAutoHidden(MASK button_types) const; + + /** + * (Un)Mark the buttons as hidden. + * + * Auto-hidden buttons are those that re-appear as soon as we have enough available space. + */ + void setAutoHidden(MASK button_types, bool hide); + /// Buttons automatically hidden due to lack of space. MASK mResizeState; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index a2a109d5eec6329853bad847e4efc4a146ebc57e..2cfd3b0a33b87498d92abd907e1277ec232bf321 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -210,7 +210,7 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.setColorMask(true, true); } - if (LLPipeline::sAutoMaskAlphaNonDeferred && !deferred_render) + if (LLPipeline::sAutoMaskAlphaNonDeferred) { mColorSFactor = LLRender::BF_ONE; // } mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow @@ -226,7 +226,10 @@ void LLDrawPoolAlpha::render(S32 pass) simple_shader->bind(); pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); } - fullbright_shader->bind(); + if (fullbright_shader) + { + fullbright_shader->bind(); + } pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); LLGLSLShader::bindNoShader(); } @@ -273,6 +276,7 @@ void LLDrawPoolAlpha::render(S32 pass) if (deferred_render && pass == 1) { gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } if (deferred_render && current_shader != NULL) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index ae455a82873f6822c172c997784b92ba3dac4f05..5398c13c44086aca667eabfac288df518b749807 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -979,19 +979,29 @@ bool LLFace::canRenderAsMask() } const LLTextureEntry* te = getTextureEntry(); - return ( - ( - (LLPipeline::sRenderDeferred && LLPipeline::sAutoMaskAlphaDeferred) || - - (!LLPipeline::sRenderDeferred && LLPipeline::sAutoMaskAlphaNonDeferred) - ) // do we want masks at all? - && - (te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha - !(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid + + if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask + getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) + { + if (LLPipeline::sRenderDeferred) + { + if (getViewerObject()->isHUDAttachment() || te->getFullbright()) + { //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe + return LLPipeline::sAutoMaskAlphaNonDeferred; + } + else + { + return LLPipeline::sAutoMaskAlphaDeferred; + } + } + else + { + return LLPipeline::sAutoMaskAlphaNonDeferred; + } + } - getTexture()->getIsAlphaMask() // texture actually qualifies for masking (lazily recalculated but expensive) - ); + return false; } diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index c2c2e7fe22a5fc72fa9be7b1e6565b913c8f1cbe..2679dbb78bac04165b7b9564f9b6f7ef9aa77308 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -413,8 +413,9 @@ LLColor4 get_text_color(const LLChat& chat) if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); - F32 distance = dist_vec(pos_agent, chat.mPosAgent); - if (distance > gAgent.getNearChatRadius()) + F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); + F32 dist_near_chat = gAgent.getNearChatRadius(); + if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat text_color.mV[VALPHA] = 0.8f; diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index d360d5db55fcaf18937bf8133c67e0264dd16691..e4d8e3513d72f79ed481a5a5f27703da8c5e0128 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -325,122 +325,51 @@ void LLFloaterImagePreview::draw() bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { std::string exten = gDirUtilp->getExtension(src_filename); - - U32 codec = IMG_CODEC_INVALID; - std::string temp_str; - if( exten == "bmp") - { - codec = IMG_CODEC_BMP; - } - else if( exten == "tga") - { - codec = IMG_CODEC_TGA; - } - else if( exten == "jpg" || exten == "jpeg") - { - codec = IMG_CODEC_JPEG; - } - else if( exten == "png" ) - { - codec = IMG_CODEC_PNG; - } + U32 codec = LLImageBase::getCodecFromExtension(exten); LLImageDimensionsInfo image_info; - if(!image_info.load(src_filename,codec)) + if (!image_info.load(src_filename,codec)) { mImageLoadError = image_info.getLastError(); return false; } S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); - S32 max_heigh = gSavedSettings.getS32("max_texture_dimension_Y"); + S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); - if(image_info.getWidth() > max_width|| image_info.getHeight() > max_heigh) + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) { LLStringUtil::format_map_t args; args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_heigh); + args["HEIGHT"] = llformat("%d", max_height); mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); return false; } - + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return false; + } + if (!image->load(src_filename)) + { + return false; + } + // Decompress or expand it in a raw image structure LLPointer<LLImageRaw> raw_image = new LLImageRaw; - - switch (codec) + if (!image->decode(raw_image, 0.0f)) { - case IMG_CODEC_BMP: - { - LLPointer<LLImageBMP> bmp_image = new LLImageBMP; - - if (!bmp_image->load(src_filename)) - { - return false; - } - - if (!bmp_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - case IMG_CODEC_TGA: - { - LLPointer<LLImageTGA> tga_image = new LLImageTGA; - - if (!tga_image->load(src_filename)) - { - return false; - } - - if (!tga_image->decode(raw_image)) - { - return false; - } - - if( (tga_image->getComponents() != 3) && - (tga_image->getComponents() != 4) ) - { - tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); - return false; - } - } - break; - case IMG_CODEC_JPEG: - { - LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG; - - if (!jpeg_image->load(src_filename)) - { - return false; - } - - if (!jpeg_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - case IMG_CODEC_PNG: - { - LLPointer<LLImagePNG> png_image = new LLImagePNG; - - if (!png_image->load(src_filename)) - { - return false; - } - - if (!png_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - default: return false; } - + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + raw_image->biasedScaleToPowerOfTwo(1024); mRawImagep = raw_image; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index dd95782161aa0587cd36ba0a19a8363ea1a19189..18b7a48d7bdde443c33932cacd34cf8cde78d756 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -43,6 +43,7 @@ #include "llcombobox.h" #include "llcommandhandler.h" #include "lldirpicker.h" +#include "lleventtimer.h" #include "llfeaturemanager.h" #include "llfocusmgr.h" //#include "llfirstuse.h" @@ -73,6 +74,7 @@ #include "llviewerwindow.h" #include "llviewermessage.h" #include "llviewershadermgr.h" +#include "llviewerthrottle.h" #include "llvotree.h" #include "llvosky.h" @@ -109,6 +111,7 @@ const F32 MAX_USER_FAR_CLIP = 512.f; const F32 MIN_USER_FAR_CLIP = 64.f; +const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f; //control value for middle mouse as talk2push button const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; @@ -1542,10 +1545,56 @@ void LLFloaterPreference::setCacheLocation(const LLStringExplicit& location) cache_location_editor->setToolTip(location); } +//------------------------------Updater--------------------------------------- + +static bool handleBandwidthChanged(const LLSD& newvalue) +{ + gViewerThrottle.setMaxBandwidth((F32) newvalue.asReal()); + return true; +} + +class LLPanelPreference::Updater : public LLEventTimer +{ + +public: + + typedef boost::function<bool(const LLSD&)> callback_t; + + Updater(callback_t cb, F32 period) + :LLEventTimer(period), + mCallback(cb) + { + mEventTimer.stop(); + } + + virtual ~Updater(){} + + void update(const LLSD& new_value) + { + mNewValue = new_value; + mEventTimer.start(); + } + +protected: + + BOOL tick() + { + mCallback(mNewValue); + mEventTimer.stop(); + + return FALSE; + } + +private: + + LLSD mNewValue; + callback_t mCallback; +}; //---------------------------------------------------------------------------- static LLRegisterPanelClassWrapper<LLPanelPreference> t_places("panel_preference"); LLPanelPreference::LLPanelPreference() -: LLPanel() +: LLPanel(), + mBandWidthUpdater(NULL) { mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); mCommitCallbackRegistrar.add("Pref.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelPreference::updateMediaAutoPlayCheckbox, this, _1)); @@ -1615,10 +1664,24 @@ BOOL LLPanelPreference::postBuild() } } + //////////////////////PanelSetup /////////////////// + if (hasChild("max_bandwidth")) + { + mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT); + gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2)); + } + apply(); return true; } +LLPanelPreference::~LLPanelPreference() +{ + if (mBandWidthUpdater) + { + delete mBandWidthUpdater; + } +} void LLPanelPreference::apply() { // no-op diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 4d8a2489be9d21dc5047700852bdf250e0a97b60..5fe509fb37e0c3bef082b050a1ef1f4b49cc3489 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -181,6 +181,8 @@ class LLPanelPreference : public LLPanel LLPanelPreference(); /*virtual*/ BOOL postBuild(); + virtual ~LLPanelPreference(); + virtual void apply(); virtual void cancel(); void setControlFalse(const LLSD& user_data); @@ -194,6 +196,7 @@ class LLPanelPreference : public LLPanel // cancel() can restore them. virtual void saveSettings(); + class Updater; private: //for "Only friends and groups can call or IM me" static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); @@ -205,6 +208,8 @@ class LLPanelPreference : public LLPanel typedef std::map<std::string, LLColor4> string_color_map_t; string_color_map_t mSavedColors; + + Updater* mBandWidthUpdater; }; class LLPanelPreferenceGraphics : public LLPanelPreference diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 2041fac8d8d165cbfd878e5201c2443cceeb50ab..d5806e375c18ab8e02dd623467d65c3c63b28f22 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -31,6 +31,7 @@ #include "llfloaterreg.h" #include "llfloatersearch.h" #include "llmediactrl.h" +#include "llnotificationsutil.h" #include "lllogininstance.h" #include "lluri.h" #include "llagent.h" @@ -46,6 +47,12 @@ class LLSearchHandler : public LLCommandHandler LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { + if (!LLUI::sSettingGroups["config"]->getBOOL("EnableSearch")) + { + LLNotificationsUtil::add("NoSearch", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + const size_t parts = tokens.size(); // get the (optional) category for the search diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 03cf0332a98aa6362aeed7e48a550eb1deee8b78..f8a4ce7ad0fc8362fa220666026840dcf9394f19 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -73,6 +73,7 @@ #include "llslider.h" #include "message.h" #include "llwindow.h" // copyTextToClipboard() +#include <algorithm> //--------------------------------------------------------------------------- // Constants @@ -85,6 +86,16 @@ static const F32 MAP_ZOOM_TIME = 0.2f; // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. static const S32 MAX_VISIBLE_REGIONS = 512; +// It would be more logical to have this inside the method where it is used but to compile under gcc this +// struct has to be here. +struct SortRegionNames +{ + inline bool operator ()(std::pair <U64, LLSimInfo*> const& _left, std::pair <U64, LLSimInfo*> const& _right) + { + return(LLStringUtil::compareInsensitive(_left.second->getName(), _right.second->getName()) < 0); + } +}; + enum EPanDirection { PAN_UP, @@ -1483,10 +1494,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) S32 name_length = mCompletingRegionName.length(); LLSD match; - + S32 num_results = 0; - std::map<U64, LLSimInfo*>::const_iterator it; - for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + + std::vector<std::pair <U64, LLSimInfo*> > sim_info_vec(LLWorldMap::getInstance()->getRegionMap().begin(), LLWorldMap::getInstance()->getRegionMap().end()); + std::sort(sim_info_vec.begin(), sim_info_vec.end(), SortRegionNames()); + + for (std::vector<std::pair <U64, LLSimInfo*> >::const_iterator it = sim_info_vec.begin(); it != sim_info_vec.end(); ++it) { LLSimInfo* info = it->second; std::string sim_name_lower = info->getName(); diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index f658287fb1145afd5b9a035cdfd77bf9f0ee6b10..2f9856c650e8fc5e61dada62a80a8924e752563e 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -33,8 +33,10 @@ #include <algorithm> // library +#include "llaudioengine.h" #include "lldatapacker.h" #include "llinventory.h" +#include "llkeyframemotion.h" #include "llmultigesture.h" #include "llnotificationsutil.h" #include "llstl.h" @@ -526,6 +528,66 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture) gesture->mPlaying = TRUE; mPlaying.push_back(gesture); + // Load all needed assets to minimize the delays + // when gesture is playing. + for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin(); + steps_it != gesture->mSteps.end(); + ++steps_it) + { + LLGestureStep* step = *steps_it; + switch(step->getType()) + { + case STEP_ANIMATION: + { + LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; + const LLUUID& anim_id = anim_step->mAnimAssetID; + + // Don't request the animation if this step stops it or if it is already in Static VFS + if (!(anim_id.isNull() + || anim_step->mFlags & ANIM_FLAG_STOP + || gAssetStorage->hasLocalAsset(anim_id, LLAssetType::AT_ANIMATION))) + { + mLoadingAssets.insert(anim_id); + + LLUUID* id = new LLUUID(gAgentID); + gAssetStorage->getAssetData(anim_id, + LLAssetType::AT_ANIMATION, + onAssetLoadComplete, + (void *)id, + TRUE); + } + break; + } + case STEP_SOUND: + { + LLGestureStepSound* sound_step = (LLGestureStepSound*)step; + const LLUUID& sound_id = sound_step->mSoundAssetID; + if (!(sound_id.isNull() + || gAssetStorage->hasLocalAsset(sound_id, LLAssetType::AT_SOUND))) + { + mLoadingAssets.insert(sound_id); + + gAssetStorage->getAssetData(sound_id, + LLAssetType::AT_SOUND, + onAssetLoadComplete, + NULL, + TRUE); + } + break; + } + case STEP_CHAT: + case STEP_WAIT: + case STEP_EOF: + { + break; + } + default: + { + llwarns << "Unknown gesture step type: " << step->getType() << llendl; + } + } + } + // And get it going stepGesture(gesture); @@ -741,7 +803,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) { return; } - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid() || hasLoadingAssets(gesture)) return; // Of the ones that started playing, have any stopped? @@ -1091,6 +1153,98 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, } } +// static +void LLGestureMgr::onAssetLoadComplete(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LLGestureMgr& self = LLGestureMgr::instance(); + + // Complete the asset loading process depending on the type and + // remove the asset id from pending downloads list. + switch(type) + { + case LLAssetType::AT_ANIMATION: + { + LLKeyframeMotion::onLoadComplete(vfs, asset_uuid, type, user_data, status, ext_status); + + self.mLoadingAssets.erase(asset_uuid); + + break; + } + case LLAssetType::AT_SOUND: + { + LLAudioEngine::assetCallback(vfs, asset_uuid, type, user_data, status, ext_status); + + self.mLoadingAssets.erase(asset_uuid); + + break; + } + default: + { + llwarns << "Unexpected asset type: " << type << llendl; + + // We don't want to return from this callback without + // an animation or sound callback being fired + // and *user_data handled to avoid memory leaks. + llassert(type == LLAssetType::AT_ANIMATION || type == LLAssetType::AT_SOUND); + } + } +} + +// static +bool LLGestureMgr::hasLoadingAssets(LLMultiGesture* gesture) +{ + LLGestureMgr& self = LLGestureMgr::instance(); + + for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin(); + steps_it != gesture->mSteps.end(); + ++steps_it) + { + LLGestureStep* step = *steps_it; + switch(step->getType()) + { + case STEP_ANIMATION: + { + LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; + const LLUUID& anim_id = anim_step->mAnimAssetID; + + if (!(anim_id.isNull() + || anim_step->mFlags & ANIM_FLAG_STOP + || self.mLoadingAssets.find(anim_id) == self.mLoadingAssets.end())) + { + return true; + } + break; + } + case STEP_SOUND: + { + LLGestureStepSound* sound_step = (LLGestureStepSound*)step; + const LLUUID& sound_id = sound_step->mSoundAssetID; + + if (!(sound_id.isNull() + || self.mLoadingAssets.find(sound_id) == self.mLoadingAssets.end())) + { + return true; + } + break; + } + case STEP_CHAT: + case STEP_WAIT: + case STEP_EOF: + { + break; + } + default: + { + llwarns << "Unknown gesture step type: " << step->getType() << llendl; + } + } + } + + return false; +} void LLGestureMgr::stopGesture(LLMultiGesture* gesture) { diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index b9935efeb3c25a009343fbfae61b00e47270887b..5930841cbc1e70302eb0ca64c34f2aca098bcc1a 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -154,9 +154,20 @@ class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchIt // Used by loadGesture static void onLoadComplete(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + + // Used by playGesture to load an asset file + // required to play a gesture step + static void onAssetLoadComplete(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + + // Checks whether all animation and sound assets + // needed to play a gesture are loaded. + static bool hasLoadingAssets(LLMultiGesture* gesture); private: // Active gestures. @@ -172,6 +183,8 @@ class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchIt callback_map_t mCallbackMap; std::vector<LLMultiGesture*> mPlaying; BOOL mValid; + + std::set<LLUUID> mLoadingAssets; }; #endif diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 72f64752d6fa9bde666755a3768148507e410456..b380b3fe2020abe4edb2ae026099ee31a06d05e6 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -56,7 +56,7 @@ const S32 PKT_SIZE = 57; // throttle const F32 MAX_SENDS_PER_SEC = 4.f; -const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; +const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f; const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; @@ -416,7 +416,7 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); // lookat position has moved a certain amount and we haven't just sent an update - lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); if (lookAtChanged) diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp index bfb0f150b3e548034b92001646cae34361f76b16..28fe8e1c015f4dee42efc991e007c7e454f39528 100644 --- a/indra/newview/llhudeffectpointat.cpp +++ b/indra/newview/llhudeffectpointat.cpp @@ -48,7 +48,7 @@ const S32 PKT_SIZE = 57; // throttle const F32 MAX_SENDS_PER_SEC = 4.f; -const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; +const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f; // timeouts // can't use actual F32_MAX, because we add this to the current frametime @@ -244,7 +244,7 @@ BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *ob BOOL targetTypeChanged = (target_type != mTargetType) || (object != mTargetObject); - BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)); if (targetTypeChanged || targetPosChanged) diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index e22363c2f63bdd0e95da0ca4bbc8bf97044cbfa4..dee15a1efdc55c609879e9891f08ac33e2e3d775 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -510,9 +510,15 @@ void LLInventoryFilter::setHoursAgo(U32 hours) { if (mFilterOps.mHoursAgo != hours) { + bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max(); + + bool is_increasing = hours > mFilterOps.mHoursAgo; + bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo; + // *NOTE: need to cache last filter time, in case filter goes stale - BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo); - BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo); + BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours); + BOOL more_restrictive = (are_date_limits_valid && (!is_increasing && hours) || is_increasing_from_zero); + mFilterOps.mHoursAgo = hours; mFilterOps.mMinDate = time_min(); mFilterOps.mMaxDate = time_max(); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index abcd8588dc517a202dfba9d6d545b97297f7d5ff..36c5d12897d55bebd0181e74e6a0427d92bfdb6f 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -558,6 +558,18 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia requested_options.append("buddy-list"); requested_options.append("newuser-config"); requested_options.append("ui-config"); + + //send this info to login.cgi for stats gathering + //since viewerstats isn't reliable enough + if (gSavedSettings.getString("SessionSettingsFile").empty()) + { + requested_options.append("advanced-mode"); + } + else + { + requested_options.append("basic-mode"); + } + #endif requested_options.append("max-agent-groups"); requested_options.append("map-server-url"); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index f1c7e952d17bc76236a6fd2b480206c71b020566..6ee095475fb04fc73e69ee9fee82dc887229ef58 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1127,7 +1127,7 @@ BOOL LLManipRotate::updateVisiblity() if (gSavedSettings.getBOOL("LimitSelectDistance")) { F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); - if (dist_vec(gAgent.getPositionAgent(), center) > max_select_distance) + if (dist_vec_squared(gAgent.getPositionAgent(), center) > (max_select_distance * max_select_distance)) { visible = FALSE; } diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index dcbf17e31fa35004d9ff6d5b136f2e3f103a7239..738d82e7320ec7f1ca978fcc076537753a82391d 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -234,8 +234,6 @@ void LLManipScale::render() LLVector3 center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); - F32 range; - F32 range_from_agent; if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); @@ -243,25 +241,25 @@ void LLManipScale::render() } else { - range = dist_vec(gAgentCamera.getCameraPositionAgent(), center_agent); - range_from_agent = dist_vec(gAgent.getPositionAgent(), center_agent); + F32 range_squared = dist_vec_squared(gAgentCamera.getCameraPositionAgent(), center_agent); + F32 range_from_agent_squared = dist_vec_squared(gAgent.getPositionAgent(), center_agent); // Don't draw manip if object too far away if (gSavedSettings.getBOOL("LimitSelectDistance")) { F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); - if (range_from_agent > max_select_distance) + if (range_from_agent_squared > max_select_distance * max_select_distance) { return; } } - if (range > 0.001f) + if (range_squared > 0.001f * 0.001f) { // range != zero F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - mBoxHandleSize = range * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR; + mBoxHandleSize = (F32) sqrtf(range_squared) * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR; } else { diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 572eeb8fc7702c0ae437524b3d6565cb854e9cf4..03ebc344f17d4087c21a9b1e2051347cc048762b 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -250,9 +250,13 @@ void LLNearbyChat::getAllowedRect(LLRect& rect) void LLNearbyChat::updateChatHistoryStyle() { mChatHistory->clear(); + + LLSD do_not_log; + do_not_log["do_not_log"] = true; for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it) { - addMessage(*it,false); + // Update the messages without re-writing them to a log file. + addMessage(*it,false, do_not_log); } } diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 981b4dbee3afc964ffb1c5d1a5a2f91ebb54d2a8..5fe5c9b1e8a4e03c0073cd053ee3599f8f1d3633 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -330,8 +330,8 @@ void LLNetMap::draw() //localMouse(&local_mouse_x, &local_mouse_y); LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mClosestAgentToCursor.setNull(); - F32 closest_dist = F32_MAX; - F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE; + F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop + F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE); // Draw avatars for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -410,11 +410,11 @@ void LLNetMap::draw() } } - F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), + F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); - if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist) + if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { - closest_dist = dist_to_cursor; + closest_dist_squared = dist_to_cursor_squared; mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i); } } @@ -451,9 +451,9 @@ void LLNetMap::draw() dot_width, dot_width); - F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), + F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); - if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist) + if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { mClosestAgentToCursor = gAgent.getID(); } diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index cb8fbd66b53088885d0d6b409625776dc2d5d68c..b73d97e4c41f13d8fb639a65befb2fcc545eecc6 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1133,7 +1133,7 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL dis LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel); LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab); - + if (!panel_list) { llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl; @@ -1145,7 +1145,18 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL dis llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl; continue; } - + + // Don't show female subparts if you're not female, etc. + if (!(gAgentAvatarp->getSex() & subpart_entry->mSex)) + { + tab->setVisible(FALSE); + continue; + } + else + { + tab->setVisible(TRUE); + } + // what edit group do we want to extract params for? const std::string edit_group = subpart_entry->mEditGroup; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index d85ddcaa603de8328e471a1de7d9631d4d623bff..85c57b490096ab8cef20205827d854d361d193be 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -81,7 +81,6 @@ class LLFloaterInventoryFinder : public LLFloater BOOL getCheckSinceLogoff(); static void onTimeAgo(LLUICtrl*, void *); - static void onCheckSinceLogoff(LLUICtrl*, void *); static void onCloseBtn(void* user_data); static void selectAllTypes(void* user_data); static void selectNoTypes(void* user_data); @@ -619,20 +618,6 @@ LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* invento updateElementsFromFilter(); } - -void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data) -{ - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - bool since_logoff= self->getChild<LLUICtrl>("check_since_logoff")->getValue(); - - if (!since_logoff && - !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) ) - { - self->mSpinSinceHours->set(1.0f); - } -} BOOL LLFloaterInventoryFinder::postBuild() { const LLRect& viewrect = mPanelMainInventory->getRect(); @@ -647,9 +632,6 @@ BOOL LLFloaterInventoryFinder::postBuild() mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago"); childSetCommitCallback("spin_days_ago", onTimeAgo, this); - // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff"); - childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this); - childSetAction("Close", onCloseBtn, this); updateElementsFromFilter(); @@ -660,12 +642,10 @@ void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; if (!self) return; - bool since_logoff=true; if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) { - since_logoff = false; + self->getChild<LLUICtrl>("check_since_logoff")->setValue(false); } - self->getChild<LLUICtrl>("check_since_logoff")->setValue(since_logoff); } void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index b52f33ec3b62eddb0decddad0c1976612bce6473..e3a7b749ea6be37294d2204355fe42feb2988928 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -158,9 +158,8 @@ class LLAvatarItemDistanceComparator : public LLAvatarItemComparator const LLVector3d& me_pos = gAgent.getPositionGlobal(); const LLVector3d& item1_pos = mAvatarsPositions.find(item1->getAvatarId())->second; const LLVector3d& item2_pos = mAvatarsPositions.find(item2->getAvatarId())->second; - F32 dist1 = dist_vec(item1_pos, me_pos); - F32 dist2 = dist_vec(item2_pos, me_pos); - return dist1 < dist2; + + return dist_vec_squared(item1_pos, me_pos) < dist_vec_squared(item2_pos, me_pos); } private: id_to_pos_map_t mAvatarsPositions; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index f40056adbc4bf681aa4ad61ca0da4b96f8ceccf6..e124916c48095131afcec1dc09e9bb0e78a02139 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -43,7 +43,8 @@ typedef std::map<std::string, std::string> controller_map_t; typedef std::map<std::string, F32> default_controller_map_t; -#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f; +#define MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION 0.f +#define TIME_ITERATION_STEP 0.1f inline F64 llsgn(const F64 a) { @@ -122,12 +123,11 @@ class LLPhysicsMotion } void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, - F32 behavior_maxeffect); + F32 behavior_maxeffect); F32 toLocal(const LLVector3 &world); - F32 calculateVelocity_local(const F32 time_delta); - F32 calculateAcceleration_local(F32 velocity_local, - const F32 time_delta); + F32 calculateVelocity_local(); + F32 calculateAcceleration_local(F32 velocity_local); private: const std::string mParamDriverName; const std::string mParamControllerName; @@ -364,7 +364,7 @@ void LLPhysicsMotionController::addMotion(LLPhysicsMotion *motion) F32 LLPhysicsMotionController::getMinPixelArea() { - return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION; + return MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION; } // Local space means "parameter space". @@ -378,19 +378,20 @@ F32 LLPhysicsMotion::toLocal(const LLVector3 &world) return world * dir_world; } -F32 LLPhysicsMotion::calculateVelocity_local(const F32 time_delta) +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; - const LLVector3 velocity_world = (position_world-last_position_world) / time_delta; + 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; } -F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local, - const F32 time_delta) +F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local) { // const F32 smoothing = getParamValue("Smoothing"); static const F32 smoothing = 3.0f; // Removed smoothing param since it's probably not necessary @@ -446,7 +447,15 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) // const F32 time_delta = time - mLastTime; - if (time_delta > 3.0 || time_delta <= 0.01) + + // Don't update too frequently, to avoid precision errors from small time slices. + if (time_delta <= .01) + { + return FALSE; + } + + // If less than 1FPS, we don't want to be spending time updating physics at all. + if (time_delta > 1.0) { mLastTime = time; return FALSE; @@ -468,201 +477,207 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) const F32 behavior_gain = getParamValue("Gain"); const F32 behavior_damping = getParamValue("Damping"); const F32 behavior_drag = getParamValue("Drag"); - const BOOL physics_test = gSavedSettings.getBOOL("AvatarPhysicsTest") && gAgent.isGodlike(); + const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. F32 behavior_maxeffect = getParamValue("MaxEffect"); if (physics_test) behavior_maxeffect = 1.0f; - // mPositon_local should be in normalized 0,1 range already. Just making sure... - F32 position_current_local = llclamp(mPosition_local, - 0.0f, - 1.0f); - - // Normalize the param position to be from [0,1]. - // We have to use normalized values because there may be more than one driven param, - // and each of these driven params may have its own range. - // This means we'll do all our calculations in normalized [0,1] local coordinates. - F32 position_user_local = mParamDriver->getWeight(); - position_user_local = (position_user_local - mParamDriver->getMinWeight()) / (mParamDriver->getMaxWeight() - mParamDriver->getMinWeight()); - - // If the effect is turned off then don't process unless we need one more update - // to set the position to the default (i.e. user) position. - if ((behavior_maxeffect == 0) && (position_current_local == position_user_local)) - { - return FALSE; - } - - // - // End parameters and settings - //////////////////////////////////////////////////////////////////////////////// - - - //////////////////////////////////////////////////////////////////////////////// - // Calculate velocity and acceleration in parameter space. - // + // Normalize the param position to be from [0,1]. + // We have to use normalized values because there may be more than one driven param, + // and each of these driven params may have its own range. + // This means we'll do all our calculations in normalized [0,1] local coordinates. + const F32 position_user_local = (mParamDriver->getWeight() - mParamDriver->getMinWeight()) / (mParamDriver->getMaxWeight() - mParamDriver->getMinWeight()); + + // + // End parameters and settings + //////////////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////////////////// + // Calculate velocity and acceleration in parameter space. + // - const F32 velocity_joint_local = calculateVelocity_local(time_delta); - const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local, time_delta); - - // - // End velocity and acceleration - //////////////////////////////////////////////////////////////////////////////// - - - //////////////////////////////////////////////////////////////////////////////// - // Calculate the total force - // - - // Spring force is a restoring force towards the original user-set breast position. - // F = kx - const F32 spring_length = position_current_local - position_user_local; - const F32 force_spring = -spring_length * behavior_spring; - - // Acceleration is the force that comes from the change in velocity of the torso. - // F = ma - const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass); - - // Gravity always points downward in world space. - // F = mg - const LLVector3 gravity_world(0,0,1); - const F32 force_gravity = behavior_gain * (toLocal(gravity_world) * behavior_gravity * behavior_mass); + //const F32 velocity_joint_local = calculateVelocity_local(time_iteration_step); + const F32 velocity_joint_local = calculateVelocity_local(); + const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local); + + // + // End velocity and acceleration + //////////////////////////////////////////////////////////////////////////////// + + BOOL update_visuals = FALSE; + + // Break up the physics into a bunch of iterations so that differing framerates will show + // roughly the same behavior. + for (F32 time_iteration = 0; time_iteration <= time_delta; time_iteration += TIME_ITERATION_STEP) + { + F32 time_iteration_step = TIME_ITERATION_STEP; + if (time_iteration + TIME_ITERATION_STEP > time_delta) + { + time_iteration_step = time_delta-time_iteration; + } + + // mPositon_local should be in normalized 0,1 range already. Just making sure... + const F32 position_current_local = llclamp(mPosition_local, + 0.0f, + 1.0f); + // If the effect is turned off then don't process unless we need one more update + // to set the position to the default (i.e. user) position. + if ((behavior_maxeffect == 0) && (position_current_local == position_user_local)) + { + return update_visuals; + } + + //////////////////////////////////////////////////////////////////////////////// + // Calculate the total force + // + + // Spring force is a restoring force towards the original user-set breast position. + // F = kx + const F32 spring_length = position_current_local - position_user_local; + const F32 force_spring = -spring_length * behavior_spring; + + // Acceleration is the force that comes from the change in velocity of the torso. + // F = ma + const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass); + + // Gravity always points downward in world space. + // F = mg + const LLVector3 gravity_world(0,0,1); + const F32 force_gravity = (toLocal(gravity_world) * behavior_gravity * behavior_mass); - // Damping is a restoring force that opposes the current velocity. - // F = -kv - const F32 force_damping = -behavior_damping * mVelocity_local; + // Damping is a restoring force that opposes the current velocity. + // F = -kv + const F32 force_damping = -behavior_damping * mVelocity_local; - // Drag is a force imparted by velocity (intuitively it is similar to wind resistance) - // F = .5kv^2 - const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local); + // Drag is a force imparted by velocity (intuitively it is similar to wind resistance) + // F = .5kv^2 + const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local); - const F32 force_net = (force_accel + - force_gravity + - force_spring + - force_damping + - force_drag); + const F32 force_net = (force_accel + + force_gravity + + force_spring + + force_damping + + force_drag); - // - // End total force - //////////////////////////////////////////////////////////////////////////////// + // + // End total force + //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // Calculate new params - // - - // Calculate the new acceleration based on the net force. - // a = F/m - const F32 acceleration_new_local = force_net / behavior_mass; - static const F32 max_acceleration = 10.0f; // magic number, used to be customizable. - F32 velocity_new_local = mVelocity_local + acceleration_new_local; - velocity_new_local = llclamp(velocity_new_local, - -max_acceleration, max_acceleration); + //////////////////////////////////////////////////////////////////////////////// + // Calculate new params + // + + // Calculate the new acceleration based on the net force. + // a = F/m + const F32 acceleration_new_local = force_net / behavior_mass; + static const F32 max_velocity = 100.0f; // magic number, used to be customizable. + F32 velocity_new_local = mVelocity_local + acceleration_new_local*time_iteration_step; + velocity_new_local = llclamp(velocity_new_local, + -max_velocity, max_velocity); - // Temporary debugging setting to cause all avatars to move, for profiling purposes. - if (physics_test) - { - velocity_new_local = sin(time*4.0); - } - // Calculate the new parameters, or remain unchanged if max speed is 0. - F32 position_new_local = position_current_local + velocity_new_local*time_delta; - if (behavior_maxeffect == 0) - position_new_local = position_user_local; - - // Zero out the velocity if the param is being pushed beyond its limits. - if ((position_new_local < 0 && velocity_new_local < 0) || - (position_new_local > 1 && velocity_new_local > 0)) - { - velocity_new_local = 0; - } + // Temporary debugging setting to cause all avatars to move, for profiling purposes. + if (physics_test) + { + velocity_new_local = sin(time*4.0); + } + // Calculate the new parameters, or remain unchanged if max speed is 0. + F32 position_new_local = position_current_local + velocity_new_local*time_iteration_step; + if (behavior_maxeffect == 0) + position_new_local = position_user_local; + + // Zero out the velocity if the param is being pushed beyond its limits. + if ((position_new_local < 0 && velocity_new_local < 0) || + (position_new_local > 1 && velocity_new_local > 0)) + { + velocity_new_local = 0; + } - // Check for NaN values. A NaN value is detected if the variables doesn't equal itself. - // If NaN, then reset everything. - if ((mPosition_local != mPosition_local) || - (mVelocity_local != mVelocity_local) || - (position_new_local != position_new_local)) - { - position_new_local = 0; - position_current_local = 0; - position_user_local = 0; - mVelocity_local = 0; - mVelocityJoint_local = 0; - mAccelerationJoint_local = 0; - mPosition_local = 0; - mPosition_world = LLVector3(0,0,0); - } - - const F32 position_new_local_clamped = llclamp(position_new_local, - 0.0f, - 1.0f); - - LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamDriver); - llassert_always(driver_param); - if (driver_param) - { - // If this is one of our "hidden" driver params, then make sure it's - // the default value. - if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && - (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT)) - { - mCharacter->setVisualParamWeight(driver_param, - 0, - FALSE); - } - for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); - iter != driver_param->mDriven.end(); - ++iter) - { - LLDrivenEntry &entry = (*iter); - LLViewerVisualParam *driven_param = entry.mParam; - setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); - } - } + // Check for NaN values. A NaN value is detected if the variables doesn't equal itself. + // If NaN, then reset everything. + if ((mPosition_local != mPosition_local) || + (mVelocity_local != mVelocity_local) || + (position_new_local != position_new_local)) + { + position_new_local = 0; + mVelocity_local = 0; + mVelocityJoint_local = 0; + mAccelerationJoint_local = 0; + mPosition_local = 0; + mPosition_world = LLVector3(0,0,0); + } + + const F32 position_new_local_clamped = llclamp(position_new_local, + 0.0f, + 1.0f); + + LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamDriver); + llassert_always(driver_param); + if (driver_param) + { + // If this is one of our "hidden" driver params, then make sure it's + // the default value. + if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && + (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT)) + { + mCharacter->setVisualParamWeight(driver_param, + 0, + FALSE); + } + for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); + iter != driver_param->mDriven.end(); + ++iter) + { + LLDrivenEntry &entry = (*iter); + LLViewerVisualParam *driven_param = entry.mParam; + setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); + } + } - // - // End calculate new params - //////////////////////////////////////////////////////////////////////////////// + // + // End calculate new params + //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // Conditionally update the visual params - // + //////////////////////////////////////////////////////////////////////////////// + // Conditionally update the visual params + // - // Updating the visual params (i.e. what the user sees) is fairly expensive. - // So only update if the params have changed enough, and also take into account - // the graphics LOD settings. + // Updating the visual params (i.e. what the user sees) is fairly expensive. + // So only update if the params have changed enough, and also take into account + // the graphics LOD settings. - BOOL update_visuals = FALSE; - - // For non-self, if the avatar is small enough visually, then don't update. - const F32 area_for_max_settings = 0.0; - const F32 area_for_min_settings = 1400.0; - const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); - const F32 pixel_area = sqrtf(mCharacter->getPixelArea()); + // For non-self, if the avatar is small enough visually, then don't update. + const F32 area_for_max_settings = 0.0; + const F32 area_for_min_settings = 1400.0; + const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); + const F32 pixel_area = sqrtf(mCharacter->getPixelArea()); - const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL); - if ((pixel_area > area_for_this_setting) || is_self) - { - const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped); - const F32 min_delta = (1.01f-lod_factor)*0.4f; - if (llabs(position_diff_local) > min_delta) - { - update_visuals = TRUE; - mPositionLastUpdate_local = position_new_local; - } - } - - // - // End update visual params - //////////////////////////////////////////////////////////////////////////////// - - mVelocityJoint_local = velocity_joint_local; - - mVelocity_local = velocity_new_local; - mAccelerationJoint_local = acceleration_joint_local; - mPosition_local = position_new_local; + const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL); + if ((pixel_area > area_for_this_setting) || is_self) + { + const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped); + const F32 min_delta = (1.0001f-lod_factor)*0.4f; + if (llabs(position_diff_local) > min_delta) + { + update_visuals = TRUE; + mPositionLastUpdate_local = position_new_local; + } + } + + // + // End update visual params + //////////////////////////////////////////////////////////////////////////////// + + mVelocity_local = velocity_new_local; + mAccelerationJoint_local = acceleration_joint_local; + mPosition_local = position_new_local; + } + mLastTime = time; + mPosition_world = joint->getWorldPosition(); + mVelocityJoint_local = velocity_joint_local; - mPosition_world = joint->getWorldPosition(); - mLastTime = time; /* // Write out debugging info into a spreadsheet. diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp index 54d54bfcb962f54959904a99f559096ebc031f9f..5bfe5c9941c470443abd6bd3e96170040c240a4a 100644 --- a/indra/newview/llphysicsshapebuilderutil.cpp +++ b/indra/newview/llphysicsshapebuilderutil.cpp @@ -1,24 +1,28 @@ /** -* @file llphysicsshapebuilder.cpp -* @brief Generic system to convert LL(Physics)VolumeParams to physics shapes -* @author falcon@lindenlab.com -* -* $LicenseInfo:firstyear=2010&license=internal$ -* -* Copyright (c) 2010, Linden Research, Inc. -* -* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of -* this source code is governed by the Linden Lab Source Code Disclosure -* Agreement ("Agreement") previously entered between you and Linden -* Lab. By accessing, using, copying, modifying or distributing this -* software, you acknowledge that you have been informed of your -* obligations under the Agreement and agree to abide by those obligations. -* -* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO -* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -* COMPLETENESS OR PERFORMANCE. -* $/LicenseInfo$ -*/ + * @file llphysicsshapebuilder.cpp + * @brief Generic system to convert LL(Physics)VolumeParams to physics shapes + * + * $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 "llviewerprecompiledheaders.h" diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h index 3de9afcb25b2b09cb938ab234e201c7441001868..7dedfb05e223b774741b658619e3960164eb036d 100644 --- a/indra/newview/llphysicsshapebuilderutil.h +++ b/indra/newview/llphysicsshapebuilderutil.h @@ -1,22 +1,26 @@ /** * @file llphysicsshapebuilder.h - * @author falcon@lindenlab.com * @brief Generic system to convert LL(Physics)VolumeParams to physics shapes * - * $LicenseInfo:firstyear=2010&license=internal$ + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. * - * 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. * - * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of - * this source code is governed by the Linden Lab Source Code Disclosure - * Agreement ("Agreement") previously entered between you and Linden - * Lab. By accessing, using, copying, modifying or distributing this - * software, you acknowledge that you have been informed of your - * obligations under the Agreement and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -42,39 +46,39 @@ const F32 SHAPE_BUILDER_ENTRY_SNAP_PARAMETER_BIN_SIZE = 0.010f; const F32 SHAPE_BUILDER_CONVEXIFICATION_SIZE = 2.f * COLLISION_TOLERANCE; const F32 SHAPE_BUILDER_MIN_GEOMETRY_SIZE = 0.5f * COLLISION_TOLERANCE; -class LLPhysicsVolumeParams : public LLVolumeParams -{ -public: - - LLPhysicsVolumeParams( const LLVolumeParams& params, bool forceConvex ) : - LLVolumeParams( params ), - mForceConvex(forceConvex) {} - - bool operator==(const LLPhysicsVolumeParams ¶ms) const - { - return ( LLVolumeParams::operator==(params) && (mForceConvex == params.mForceConvex) ); - } - - bool operator!=(const LLPhysicsVolumeParams ¶ms) const - { - return !operator==(params); - } - - bool operator<(const LLPhysicsVolumeParams ¶ms) const - { - if ( LLVolumeParams::operator!=(params) ) - { - return LLVolumeParams::operator<(params); - } - return (params.mForceConvex == false) && (mForceConvex == true); - } - - bool shouldForceConvex() const { return mForceConvex; } - -private: - bool mForceConvex; -}; - +class LLPhysicsVolumeParams : public LLVolumeParams +{ +public: + + LLPhysicsVolumeParams( const LLVolumeParams& params, bool forceConvex ) : + LLVolumeParams( params ), + mForceConvex(forceConvex) {} + + bool operator==(const LLPhysicsVolumeParams ¶ms) const + { + return ( LLVolumeParams::operator==(params) && (mForceConvex == params.mForceConvex) ); + } + + bool operator!=(const LLPhysicsVolumeParams ¶ms) const + { + return !operator==(params); + } + + bool operator<(const LLPhysicsVolumeParams ¶ms) const + { + if ( LLVolumeParams::operator!=(params) ) + { + return LLVolumeParams::operator<(params); + } + return (params.mForceConvex == false) && (mForceConvex == true); + } + + bool shouldForceConvex() const { return mForceConvex; } + +private: + bool mForceConvex; +}; + class LLPhysicsShapeBuilderUtil { diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 6cfb708112ab10ab270e7eaa90ac6672e8af4427..18d6731fcb2c997b21773a04b32c371beb080c53 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -143,10 +143,7 @@ void LLPreviewTexture::onSaveAsBtn(void* data) void LLPreviewTexture::draw() { - if (mUpdateDimensions) - { - updateDimensions(); - } + updateDimensions(); LLPreview::draw(); @@ -396,27 +393,32 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success, void LLPreviewTexture::updateDimensions() { if (!mImage) + { return; - - if(mImage->getFullWidth() == 0 || mImage->getFullHeight() == 0) + } + if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) { return; } - mUpdateDimensions = FALSE; - - getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", mImage->getFullWidth())); + // Update the width/height display every time + getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", mImage->getFullWidth())); getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight())); - - //reshape floater - reshape(getRect().getWidth(), getRect().getHeight()); + // Reshape the floater only when required + if (mUpdateDimensions) + { + mUpdateDimensions = FALSE; + + //reshape floater + reshape(getRect().getWidth(), getRect().getHeight()); - gFloaterView->adjustToFitScreen(this, FALSE); + gFloaterView->adjustToFitScreen(this, FALSE); - LLRect dim_rect(getChildView("dimensions")->getRect()); - LLRect aspect_label_rect(getChildView("aspect_ratio")->getRect()); - getChildView("aspect_ratio")->setVisible( dim_rect.mRight < aspect_label_rect.mLeft); + LLRect dim_rect(getChildView("dimensions")->getRect()); + LLRect aspect_label_rect(getChildView("aspect_ratio")->getRect()); + getChildView("aspect_ratio")->setVisible( dim_rect.mRight < aspect_label_rect.mLeft); + } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 20eee0d0cf29777af54daa343be68ee7b03d5c66..9b264b81c782dfd6ba9b75ae68713e8e81e1062a 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6966,26 +6966,27 @@ bool LLSelectMgr::selectionMove(const LLVector3& displ, if (update_position) { // calculate the distance of the object closest to the camera origin - F32 min_dist = 1e+30f; + F32 min_dist_squared = F32_MAX; // value will be overridden in the loop + LLVector3 obj_pos; for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); it != getSelection()->root_end(); ++it) { obj_pos = (*it)->getObject()->getPositionEdit(); - F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin()); - if (obj_dist < min_dist) + F32 obj_dist_squared = dist_vec_squared(obj_pos, LLViewerCamera::getInstance()->getOrigin()); + if (obj_dist_squared < min_dist_squared) { - min_dist = obj_dist; + min_dist_squared = obj_dist_squared; } } - // factor the distance inside the displacement vector. This will get us + // factor the distance into the displacement vector. This will get us // equally visible movements for both close and far away selections. - min_dist = sqrt(min_dist) / 2; - displ_global.setVec(displ.mV[0]*min_dist, - displ.mV[1]*min_dist, - displ.mV[2]*min_dist); + F32 min_dist = sqrt((F32) sqrtf(min_dist_squared)) / 2; + displ_global.setVec(displ.mV[0] * min_dist, + displ.mV[1] * min_dist, + displ.mV[2] * min_dist); // equates to: Displ_global = Displ * M_cam_axes_in_global_frame displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 4f18ee1da2948ba7f99d7d192819f9e55e228f06..e4c2293938a2727df169ac997a2e9121dcd22c8f 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -1192,6 +1192,38 @@ void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent) arrange(); } +// This is just LLView::findChildView specialized to restrict the search to LLPanels. +// Optimization for EXT-4068 to avoid searching down to the individual item level +// when inventories are large. +LLPanel *findChildPanel(LLPanel *panel, const std::string& name, bool recurse) +{ + for (LLView::child_list_const_iter_t child_it = panel->beginChild(); + child_it != panel->endChild(); ++child_it) + { + LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); + if (!child_panel) + continue; + if (child_panel->getName() == name) + return child_panel; + } + if (recurse) + { + for (LLView::child_list_const_iter_t child_it = panel->beginChild(); + child_it != panel->endChild(); ++child_it) + { + LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); + if (!child_panel) + continue; + LLPanel *found_panel = findChildPanel(child_panel,name,recurse); + if (found_panel) + { + return found_panel; + } + } + } + return NULL; +} + /** * Activate tab with "panel_name" panel * if no such tab - return false, otherwise true. @@ -1221,23 +1253,50 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para return new_panel; } -void LLSideTray::hidePanel(const std::string& panel_name) +bool LLSideTray::hidePanel(const std::string& panel_name) { + bool panelHidden = false; + LLPanel* panelp = getPanel(panel_name); + if (panelp) { - if(isTabAttached(panel_name)) + LLView* parentp = panelp->getParent(); + + // Collapse the side bar if the panel or the panel's parent is an attached tab + if (isTabAttached(panel_name) || (parentp && isTabAttached(parentp->getName()))) { collapseSideBar(); + panelHidden = true; } else { - LLFloaterReg::hideInstance("side_bar_tab", panel_name); + panelHidden = LLFloaterReg::hideInstance("side_bar_tab", panel_name); + + if (!panelHidden) + { + // Look up the panel in the list of detached tabs. + for (child_vector_const_iter_t child_it = mDetachedTabs.begin(); child_it != mDetachedTabs.end(); ++child_it) + { + LLPanel *detached_panel = dynamic_cast<LLPanel*>(*child_it); + + if (detached_panel) + { + // Hide this detached panel if it is a parent of our panel + if (findChildPanel(detached_panel, panel_name, true) != NULL) + { + panelHidden = LLFloaterReg::hideInstance("side_bar_tab", detached_panel->getName()); + break; + } + } + } + } } } + + return panelHidden; } - void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params) { if(!sub_panel) @@ -1255,38 +1314,6 @@ void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, } } -// This is just LLView::findChildView specialized to restrict the search to LLPanels. -// Optimization for EXT-4068 to avoid searching down to the individual item level -// when inventories are large. -LLPanel *findChildPanel(LLPanel *panel, const std::string& name, bool recurse) -{ - for (LLView::child_list_const_iter_t child_it = panel->beginChild(); - child_it != panel->endChild(); ++child_it) - { - LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); - if (!child_panel) - continue; - if (child_panel->getName() == name) - return child_panel; - } - if (recurse) - { - for (LLView::child_list_const_iter_t child_it = panel->beginChild(); - child_it != panel->endChild(); ++child_it) - { - LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); - if (!child_panel) - continue; - LLPanel *found_panel = findChildPanel(child_panel,name,recurse); - if (found_panel) - { - return found_panel; - } - } - } - return NULL; -} - LLPanel* LLSideTray::getPanel(const std::string& panel_name) { // Look up the panel in the list of detached tabs. diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 1dddd9e9bc288cbcfaf0401e8ba5eaa7d17b6d35..46765bfbcca57d84f66263a66892adeaa25b9148 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -104,7 +104,7 @@ class LLSideTray : public LLPanel, private LLDestroyClass<LLSideTray> */ LLPanel* showPanel (const std::string& panel_name, const LLSD& params = LLSD()); - void hidePanel (const std::string& panel_name); + bool hidePanel (const std::string& panel_name); /** * Toggling Side Tray tab which contains "sub_panel" child of "panel_name" panel. diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 40aea058397345450d5216f98b24eec130a67942..c588bd8fb44e63a6c8dfcaa601512c16094c5d02 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -920,7 +920,7 @@ void LLLocalSpeakerMgr::updateSpeakerList() if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id); - if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS) + if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS_SQUARED) { setSpeakerNotInChannel(speakerp); } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 95bd210ae37647b4af0142b688167ae60bcf95d1..06e0d17b8c5041e6a14f877ec312b96f0b3c4361 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -639,6 +639,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) if (click_action == CLICK_ACTION_NONE // not doing 1-click action && gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled && !gAgent.getFlying() // don't auto-navigate while flying until that works + && !gAgentAvatarp->isSitting() && !mBlockClickToWalk // another behavior hasn't cancelled click to walk && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp index f5484ff010376dc764ea70db7e157158d48567db..e7a0d17c3a42ed3e1e385437e51bd4595bfa9db8 100644 --- a/indra/newview/llviewerchat.cpp +++ b/indra/newview/llviewerchat.cpp @@ -90,8 +90,9 @@ void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color) if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); - F32 distance = dist_vec(pos_agent, chat.mPosAgent); - if (distance > gAgent.getNearChatRadius()) + F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); + F32 dist_near_chat = gAgent.getNearChatRadius(); + if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color.mV[VALPHA] = 0.8f; @@ -155,8 +156,9 @@ void LLViewerChat::getChatColor(const LLChat& chat, std::string& r_color_name, F if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); - F32 distance = dist_vec(pos_agent, chat.mPosAgent); - if (distance > gAgent.getNearChatRadius()) + F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); + F32 dist_near_chat = gAgent.getNearChatRadius(); + if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color_alpha = 0.8f; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index e3b34ec93056156fcf2edc3df6b54b23ed00efe2..379bbe614d62161a5d83a0cabd4cca2830c4db84 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -278,12 +278,6 @@ static bool handleVideoMemoryChanged(const LLSD& newvalue) return true; } -static bool handleBandwidthChanged(const LLSD& newvalue) -{ - gViewerThrottle.setMaxBandwidth((F32) newvalue.asReal()); - return true; -} - static bool handleChatFontSizeChanged(const LLSD& newvalue) { if(gConsole) @@ -591,7 +585,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _2)); gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _2)); - gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&handleBandwidthChanged, _2)); gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _2)); gSavedSettings.getControl("RenderFogRatio")->getSignal()->connect(boost::bind(&handleFogRatioChanged, _2)); gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _2)); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 42750f8b3f78cee8d522561646b1cdfb2e6ca90b..9e58acdcd35308ee1b4011b0f138ca821fca8529 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -183,6 +183,12 @@ class LLInventoryHandler : public LLCommandHandler return false; } + if (!LLUI::sSettingGroups["config"]->getBOOL("EnableInventory")) + { + LLNotificationsUtil::add("NoInventory", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + // support secondlife:///app/inventory/show if (params[0].asString() == "show") { diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 9ecb11d253f628a569132b35d243f49172cd0c8f..37640ad0d45ea7cd4a62de1b5ecd2b29e3e394e4 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -620,6 +620,7 @@ LLUUID upload_new_resource( LLSD args; std::string exten = gDirUtilp->getExtension(src_filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); LLAssetType::EType asset_type = LLAssetType::AT_NONE; std::string error_message; @@ -637,66 +638,20 @@ LLUUID upload_new_resource( upload_error(error_message, "NoFileExtension", filename, args); return LLUUID(); } - else if( exten == "bmp") + else if (codec != IMG_CODEC_INVALID) { + // It's an image file, the upload procedure is the same for all asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_BMP )) + if (!LLViewerTextureList::createUploadFile(src_filename, filename, codec )) { error_message = llformat( "Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); + src_filename.c_str(), LLImage::getLastError().c_str()); args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); return LLUUID(); } } - else if( exten == "tga") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_TGA )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return LLUUID(); - } - } - else if( exten == "jpg" || exten == "jpeg") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_JPEG )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return LLUUID(); - } - } - else if( exten == "png") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_PNG )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return LLUUID(); - } - } else if(exten == "wav") { asset_type = LLAssetType::AT_SOUND; // tag it as audio diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fe9301d85933ad985c387aa0309c4366f01f25d2..9c13a96b8127ddae9ecf21ba2d29675b8dcb4a77 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -122,6 +122,7 @@ // const F32 BIRD_AUDIBLE_RADIUS = 32.0f; const F32 SIT_DISTANCE_FROM_TARGET = 0.25f; +const F32 CAMERA_POSITION_THRESHOLD_SQUARED = 0.001f * 0.001f; static const F32 LOGOUT_REPLY_TIME = 3.f; // Wait this long after LogoutReply before quitting. // Determine how quickly residents' scripts can issue question dialogs @@ -4745,7 +4746,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) BOOL force_mouselook; mesgsys->getBOOLFast(_PREHASH_SitTransform, _PREHASH_ForceMouselook, force_mouselook); - if (isAgentAvatarValid() && dist_vec_squared(camera_eye, camera_at) > 0.0001f) + if (isAgentAvatarValid() && dist_vec_squared(camera_eye, camera_at) > CAMERA_POSITION_THRESHOLD_SQUARED) { gAgentCamera.setSitCamera(sitObjectID, camera_eye, camera_at); } @@ -5523,7 +5524,11 @@ void process_alert_core(const std::string& message, BOOL modal) { LLSD args; std::string new_msg =LLNotifications::instance().getGlobalString(message); - args["MESSAGE"] = new_msg; + + std::string localized_msg; + bool is_message_localized = LLTrans::findString(localized_msg, new_msg); + + args["MESSAGE"] = is_message_localized ? localized_msg : new_msg; LLNotificationsUtil::add("SystemMessageTip", args); } } @@ -6461,9 +6466,12 @@ void process_script_dialog(LLMessageSystem* msg, void**) LLSD payload; LLUUID object_id; + LLUUID owner_id; + msg->getUUID("Data", "ObjectID", object_id); + msg->getUUID("OwnerData", "OwnerID", owner_id); - if (LLMuteList::getInstance()->isMuted(object_id)) + if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id)) { return; } diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index d07e06f6a7ed171e7864517bcc8b6eaa89f287cf..26765bdd01e00e65c49aa017a59bdf0c2ccbeafe 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -833,7 +833,7 @@ S32 LLViewerParcelOverlay::renderPropertyLines () U8* colorp; bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); - const F32 PROPERTY_LINE_CLIP_DIST = 256.f; + const F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; for (i = 0; i < mVertexCount; i += vertex_per_edge) { @@ -844,7 +844,7 @@ S32 LLViewerParcelOverlay::renderPropertyLines () vertex.mV[VY] = *(vertexp+1); vertex.mV[VZ] = *(vertexp+2); - if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST*PROPERTY_LINE_CLIP_DIST) + if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 76c6c3512e9b1d87ffa3c3bbf2a6c2664d7a4dbd..7a10dfc414942f51e627c5df4a652c348b81f4e4 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -927,99 +927,43 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) BOOL LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec) -{ - // First, load the image. +{ + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return FALSE; + } + if (!image->load(filename)) + { + return FALSE; + } + // Decompress or expand it in a raw image structure LLPointer<LLImageRaw> raw_image = new LLImageRaw; - - switch (codec) + if (!image->decode(raw_image, 0.0f)) { - case IMG_CODEC_BMP: - { - LLPointer<LLImageBMP> bmp_image = new LLImageBMP; - - if (!bmp_image->load(filename)) - { - return FALSE; - } - - if (!bmp_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_TGA: - { - LLPointer<LLImageTGA> tga_image = new LLImageTGA; - - if (!tga_image->load(filename)) - { - return FALSE; - } - - if (!tga_image->decode(raw_image)) - { - return FALSE; - } - - if( (tga_image->getComponents() != 3) && - (tga_image->getComponents() != 4) ) - { - tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); - return FALSE; - } - } - break; - case IMG_CODEC_JPEG: - { - LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG; - - if (!jpeg_image->load(filename)) - { - return FALSE; - } - - if (!jpeg_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_PNG: - { - LLPointer<LLImagePNG> png_image = new LLImagePNG; - - if (!png_image->load(filename)) - { - return FALSE; - } - - if (!png_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - default: - return FALSE; + return FALSE; } - - LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image); - - if( !compressedImage->save(out_filename) ) + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) { - llinfos << "Couldn't create output file " << out_filename << llendl; + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); return FALSE; } - - // test to see if the encode and save worked. + // Convert to j2c (JPEG2000) and save the file locally + LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image); + if (!compressedImage->save(out_filename)) + { + llinfos << "Couldn't create output file : " << out_filename << llendl; + return FALSE; + } + // Test to see if the encode and save worked LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; - if( !integrity_test->loadAndValidate( out_filename ) ) + if (!integrity_test->loadAndValidate( out_filename )) { - llinfos << "Image: " << out_filename << " is corrupt." << llendl; + llinfos << "Image file : " << out_filename << " is corrupt" << llendl; return FALSE; } - return TRUE; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 88e6cf3dbe2084d2be19d6c68d12c3647223723c..8af90622ec7736e9b95e74dbf53df1e42043bcb0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4131,7 +4131,9 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); } -// Saves the image from the screen to the specified filename and path. +// Saves the image from the screen to a raw image +// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy +// the results over to the final raw image. BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size) { @@ -4149,8 +4151,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // Hide all the UI widgets first and draw a frame BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE; - show_ui = show_ui ? TRUE : FALSE; - if ( prev_draw_ui != show_ui) { LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); @@ -4170,55 +4170,49 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // from window LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); - S32 snapshot_width = window_rect.getWidth(); + S32 snapshot_width = window_rect.getWidth(); S32 snapshot_height = window_rect.getHeight(); // SNAPSHOT - S32 window_width = snapshot_width; + S32 window_width = snapshot_width; S32 window_height = snapshot_height; + // Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested if (show_ui) { - image_width = llmin(image_width, window_width); + // If the user wants the UI, limit the output size to the available screen size + image_width = llmin(image_width, window_width); image_height = llmin(image_height, window_height); } F32 scale_factor = 1.0f ; - if(!keep_window_aspect) //image cropping - { + if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) + { + // if image cropping or need to enlarge the scene, compute a scale_factor F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; + snapshot_width = (S32)(ratio * image_width) ; snapshot_height = (S32)(ratio * image_height) ; scale_factor = llmax(1.0f, 1.0f / ratio) ; } - else //the scene(window) proportion needs to be maintained. - { - if(image_width > window_width || image_height > window_height) //need to enlarge the scene - { - F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; - snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; - } - } if (show_ui && scale_factor > 1.f) { + // Note: we should never get there... llwarns << "over scaling UI not supported." << llendl; } - S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); + S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); - S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ; - S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ; + S32 image_buffer_x = llfloor(snapshot_width * scale_factor) ; + S32 image_buffer_y = llfloor(snapshot_height * scale_factor) ; - if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow + if ((image_buffer_x > max_size) || (image_buffer_y > max_size)) // boundary check to avoid memory overflow { scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ; - image_buffer_x = llfloor(snapshot_width*scale_factor) ; - image_buffer_y = llfloor(snapshot_height *scale_factor) ; + image_buffer_x = llfloor(snapshot_width * scale_factor) ; + image_buffer_y = llfloor(snapshot_height * scale_factor) ; } - if(image_buffer_x > 0 && image_buffer_y > 0) + if ((image_buffer_x > 0) && (image_buffer_y > 0)) { raw->resize(image_buffer_x, image_buffer_y, 3); } @@ -4226,7 +4220,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { return FALSE ; } - if(raw->isBufferInvalid()) + if (raw->isBufferInvalid()) { return FALSE ; } @@ -4234,6 +4228,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher if (high_res && show_ui) { + // Note: we should never get there... llwarns << "High res UI snapshot not supported. " << llendl; /*send_agent_pause(); //rescale fonts @@ -4248,6 +4243,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gObjectList.generatePickList(*LLViewerCamera::getInstance()); + // Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen. + // In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) { S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; @@ -4261,69 +4258,70 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gDisplaySwapBuffers = FALSE; gDepthDirty = TRUE; - const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); - - if (LLPipeline::sRenderDeferred) - { - display(do_rebuild, scale_factor, subfield, TRUE); - } - else - { - display(do_rebuild, scale_factor, subfield, TRUE); - // Required for showing the GUI in snapshots and performing bloom composite overlay - // Call even if show_ui is FALSE - render_ui(scale_factor, subfield); - } - S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); // handle fractional rows U32 read_width = llmax(0, (window_width - subimage_x_offset) - llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); - for(U32 out_y = 0; out_y < read_height ; out_y++) + + // Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases) + if (read_width && read_height) { - S32 output_buffer_offset = ( - (out_y * (raw->getWidth())) // ...plus iterated y... - + (window_width * subimage_x) // ...plus subimage start in x... - + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... - - output_buffer_offset_x // ...minus buffer padding x... - - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... - ) * raw->getComponents(); + const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); + display(do_rebuild, scale_factor, subfield, TRUE); - // Ping the wathdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) - if (out_y % 100 == 0) + if (!LLPipeline::sRenderDeferred) { - LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); + // Required for showing the GUI in snapshots and performing bloom composite overlay + // Call even if show_ui is FALSE + render_ui(scale_factor, subfield); } - if (type == SNAPSHOT_TYPE_COLOR) + for (U32 out_y = 0; out_y < read_height ; out_y++) { - glReadPixels( - subimage_x_offset, out_y + subimage_y_offset, - read_width, 1, - GL_RGB, GL_UNSIGNED_BYTE, - raw->getData() + output_buffer_offset - ); - } - else // SNAPSHOT_TYPE_DEPTH - { - LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values - glReadPixels( - subimage_x_offset, out_y + subimage_y_offset, - read_width, 1, - GL_DEPTH_COMPONENT, GL_FLOAT, - depth_line_buffer->getData()// current output pixel is beginning of buffer... - ); - - for (S32 i = 0; i < (S32)read_width; i++) + S32 output_buffer_offset = ( + (out_y * (raw->getWidth())) // ...plus iterated y... + + (window_width * subimage_x) // ...plus subimage start in x... + + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... + - output_buffer_offset_x // ...minus buffer padding x... + - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... + ) * raw->getComponents(); + + // Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) + if (out_y % 100 == 0) { - F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); - //write converted scanline out to result image - for(S32 j = 0; j < raw->getComponents(); j++) + LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); + } + + if (type == SNAPSHOT_TYPE_COLOR) + { + glReadPixels( + subimage_x_offset, out_y + subimage_y_offset, + read_width, 1, + GL_RGB, GL_UNSIGNED_BYTE, + raw->getData() + output_buffer_offset + ); + } + else // SNAPSHOT_TYPE_DEPTH + { + LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values + glReadPixels( + subimage_x_offset, out_y + subimage_y_offset, + read_width, 1, + GL_DEPTH_COMPONENT, GL_FLOAT, + depth_line_buffer->getData()// current output pixel is beginning of buffer... + ); + + for (S32 i = 0; i < (S32)read_width; i++) { - *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); + + F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); + U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); + // write converted scanline out to result image + for (S32 j = 0; j < raw->getComponents(); j++) + { + *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + } } } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index fdf4f5bdaae6ec81a1b1c1fc660f9682fec04759..295799fd247bf95a2c86f3bb999484ce2be9d799 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1,1090 +1,1090 @@ -/** - * @file llvoavatar.h - * @brief Declaration of LLVOAvatar class which is a derivation of - * LLViewerObject - * - * $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_LLVOAVATAR_H -#define LL_LLVOAVATAR_H - -#include <map> -#include <deque> -#include <string> -#include <vector> - -#include <boost/signals2.hpp> - -#include "imageids.h" // IMG_INVISIBLE -#include "llchat.h" -#include "lldrawpoolalpha.h" -#include "llviewerobject.h" -#include "llcharacter.h" -#include "llviewerjointmesh.h" -#include "llviewerjointattachment.h" -#include "llrendertarget.h" -#include "llvoavatardefines.h" -#include "lltexglobalcolor.h" -#include "lldriverparam.h" -#include "material_codes.h" // LL_MCODE_END - -extern const LLUUID ANIM_AGENT_BODY_NOISE; -extern const LLUUID ANIM_AGENT_BREATHE_ROT; -extern const LLUUID ANIM_AGENT_PHYSICS_MOTION; -extern const LLUUID ANIM_AGENT_EDITING; -extern const LLUUID ANIM_AGENT_EYE; -extern const LLUUID ANIM_AGENT_FLY_ADJUST; -extern const LLUUID ANIM_AGENT_HAND_MOTION; -extern const LLUUID ANIM_AGENT_HEAD_ROT; -extern const LLUUID ANIM_AGENT_PELVIS_FIX; -extern const LLUUID ANIM_AGENT_TARGET; -extern const LLUUID ANIM_AGENT_WALK_ADJUST; - -class LLTexLayerSet; -class LLVoiceVisualizer; -class LLHUDNameTag; -class LLHUDEffectSpiral; -class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLVOAvatar -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLVOAvatar : - public LLViewerObject, - public LLCharacter, - public boost::signals2::trackable -{ -public: - friend class LLVOAvatarSelf; -protected: - struct LLVOAvatarXmlInfo; - struct LLMaskedMorph; - -/******************************************************************************** - ** ** - ** INITIALIZATION - **/ - -public: - LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - virtual void markDead(); - static void initClass(); // Initialize data that's only init'd once per class. - static void cleanupClass(); // Cleanup data that's only init'd once per class. - virtual void initInstance(); // Called after construction to initialize the class. -protected: - virtual ~LLVOAvatar(); - BOOL loadSkeletonNode(); - BOOL loadMeshNodes(); - virtual BOOL loadLayersets(); - -/** Initialization - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** INHERITED - **/ - - //-------------------------------------------------------------------- - // LLViewerObject interface and related - //-------------------------------------------------------------------- -public: - virtual void updateGL(); - virtual LLVOAvatar* asAvatar(); - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); - virtual BOOL 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, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - S32* face_hit = NULL, // which face was hit - LLVector3* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector3* normal = NULL, // return the surface normal at the intersection point - LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point - - //-------------------------------------------------------------------- - // 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 void stopMotionFromSource(const LLUUID& source_id); - virtual void requestStopMotion(LLMotion* motion); - LLMotion* findMotion(const LLUUID& id) const; - void startDefaultMotions(); - 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(); - 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 void updateVisualParams(); - - -/** Inherited - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** STATE - **/ - -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 - LLVector4a mImpostorExtents[2]; - -private: - BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients - - //-------------------------------------------------------------------- - // Updates - //-------------------------------------------------------------------- -public: - virtual BOOL updateCharacter(LLAgent &agent); - void idleUpdateVoiceVisualizer(bool voice_enabled); - void idleUpdateMisc(bool detailed_update); - virtual void idleUpdateAppearanceAnimation(); - void idleUpdateLipSync(bool voice_enabled); - void idleUpdateLoadingEffect(); - void idleUpdateWindEffect(); - void idleUpdateNameTag(const LLVector3& root_pos_last); - void idleUpdateNameTagText(BOOL new_name); - LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); - void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); - LLColor4 getNameTagColor(bool is_friend); - void clearNameTag(); - static void invalidateNameTag(const LLUUID& agent_id); - // force all name tags to rebuild, useful when display names turned on/off - static void invalidateNameTags(); - void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font); - void idleUpdateRenderCost(); - void idleUpdateBelowWater(); - - //-------------------------------------------------------------------- - // Static preferences (controlled by user settings/menus) - //-------------------------------------------------------------------- -public: - static S32 sRenderName; - static BOOL sRenderGroupTitles; - static U32 sMaxVisible; //(affected by control "RenderAvatarMaxVisible") - static F32 sRenderDistance; //distance at which avatars will render. - static BOOL sShowAnimationDebug; // show animation debug info - static BOOL sUseImpostors; //use impostors for far away avatars - static BOOL sShowFootPlane; // show foot collision plane reported by server - static BOOL sShowCollisionVolumes; // show skeletal collision volumes - static BOOL sVisibleInFirstPerson; - static S32 sNumLODChangesThisFrame; - static S32 sNumVisibleChatBubbles; - static BOOL sDebugInvisible; - static BOOL sShowAttachmentPoints; - static F32 sLODFactor; // user-settable LOD factor - static F32 sPhysicsLODFactor; // user-settable physics LOD factor - static BOOL sJointDebug; // output total number of joints being touched for each avatar - static BOOL sDebugAvatarRotation; - - //-------------------------------------------------------------------- - // Region state - //-------------------------------------------------------------------- -public: - LLHost getObjectHost() const; - - //-------------------------------------------------------------------- - // Loading state - //-------------------------------------------------------------------- -public: - BOOL isFullyLoaded() const; - bool visualParamWeightsAreDefault(); -protected: - virtual BOOL getIsCloud(); - BOOL updateIsFullyLoaded(); - BOOL processFullyLoadedChange(bool loading); - void updateRuthTimer(bool loading); - F32 calcMorphAmount(); -private: - BOOL mFullyLoaded; - BOOL mPreviousFullyLoaded; - BOOL mFullyLoadedInitialized; - S32 mFullyLoadedFrameCounter; - LLFrameTimer mFullyLoadedTimer; - LLFrameTimer mRuthTimer; -protected: - LLFrameTimer mInvisibleTimer; - -/** State - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** SKELETON - **/ - -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 ); - - bool mHasPelvisOffset; - LLVector3 mPelvisOffset; - F32 mLastPelvisToFoot; - F32 mPelvisFixup; - F32 mLastPelvisFixup; - - LLVector3 mHeadOffset; // current head position - LLViewerJoint mRoot; -protected: - static BOOL parseSkeletonFile(const std::string& filename); - void buildCharacter(); - virtual BOOL loadAvatar(); - - BOOL setupBone(const LLVOAvatarBoneInfo* 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 LLXmlTree sSkeletonXMLTree; // avatar skeleton file - -/** Skeleton - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** RENDERING - **/ - -public: - U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); - U32 renderRigid(); - U32 renderSkinned(EAvatarRenderPass pass); - F32 getLastSkinTime() { return mLastSkinTime; } - U32 renderSkinnedAttachments(); - U32 renderTransparent(BOOL first_pass); - void renderCollisionVolumes(); - static void deleteCachedImages(bool clearAll=true); - static void destroyGL(); - static void restoreGL(); - BOOL mIsDummy; // for special views - S32 mSpecialRenderMode; // special lighting -private: - bool shouldAlphaMask(); - - BOOL mNeedsSkin; // avatar has been animated and verts have not been updated - F32 mLastSkinTime; //value of gFrameTimeSeconds at last skin update - - S32 mUpdatePeriod; - S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. - - //-------------------------------------------------------------------- - // 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); - - //-------------------------------------------------------------------- - // Visibility - //-------------------------------------------------------------------- -protected: - void updateVisibility(); -private: - U32 mVisibilityRank; - BOOL mVisible; - - //-------------------------------------------------------------------- - // Shadowing - //-------------------------------------------------------------------- -public: - void updateShadowFaces(); - LLDrawable* mShadow; -private: - LLFace* mShadow0Facep; - LLFace* mShadow1Facep; - LLPointer<LLViewerTexture> mShadowImagep; - - //-------------------------------------------------------------------- - // Impostors - //-------------------------------------------------------------------- -public: - BOOL isImpostor() const; - BOOL needsImpostorUpdate() const; - const LLVector3& getImpostorOffset() const; - const LLVector2& getImpostorDim() const; - void getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const; - void cacheImpostorValues(); - void setImpostorDim(const LLVector2& dim); - static void resetImpostors(); - static void updateImpostors(); - LLRenderTarget mImpostor; - BOOL mNeedsImpostorUpdate; -private: - LLVector3 mImpostorOffset; - LLVector2 mImpostorDim; - BOOL mNeedsAnimUpdate; - LLVector3 mImpostorAngle; - F32 mImpostorDistance; - F32 mImpostorPixelArea; - LLVector3 mLastAnimExtents[2]; - - //-------------------------------------------------------------------- - // Wind rippling in clothes - //-------------------------------------------------------------------- -public: - LLVector4 mWindVec; - F32 mRipplePhase; - BOOL mBelowWater; -private: - F32 mWindFreq; - LLFrameTimer mRippleTimer; - F32 mRippleTimeLast; - LLVector3 mRippleAccel; - LLVector3 mLastVel; - - //-------------------------------------------------------------------- - // Culling - //-------------------------------------------------------------------- -public: - static void cullAvatarsByPixelArea(); - BOOL isCulled() const { return mCulled; } -private: - BOOL mCulled; - - //-------------------------------------------------------------------- - // Freeze counter - //-------------------------------------------------------------------- -public: - static void updateFreezeCounter(S32 counter = 0); -private: - static S32 sFreezeCounter; - - //-------------------------------------------------------------------- - // Constants - //-------------------------------------------------------------------- -public: - virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; } - virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; } - virtual S32 getTexImageSize() const; - virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } - -/** Rendering - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** TEXTURES - **/ - - //-------------------------------------------------------------------- - // 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; - -protected: - BOOL isFullyBaked(); - static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); - - //-------------------------------------------------------------------- - // Baked textures - //-------------------------------------------------------------------- -public: - 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); - static void onInitialBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); - 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); - - 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; - //-------------------------------------------------------------------- - // 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); - // MULTI-WEARABLE: make self-only? - virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); - - //-------------------------------------------------------------------- - // Texture accessors - //-------------------------------------------------------------------- -private: - virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); - virtual LLViewerTexture* getImage(const U8 te, const U32 index) const; - - virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; - virtual void setTexEntry(const U8 index, const LLTextureEntry &te); - - void checkTextureLoading() ; - //-------------------------------------------------------------------- - // Layers - //-------------------------------------------------------------------- -protected: - void deleteLayerSetCaches(bool clearAll = true); - void addBakedTextureStats(LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); - - //-------------------------------------------------------------------- - // Composites - //-------------------------------------------------------------------- -public: - virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); - virtual void invalidateAll(); - virtual void setCompositeUpdatesEnabled(bool b) {} - virtual void setCompositeUpdatesEnabled(U32 index, bool b) {} - virtual bool isCompositeUpdateEnabled(U32 index) { return false; } - - //-------------------------------------------------------------------- - // Static texture/mesh/baked dictionary - //-------------------------------------------------------------------- -public: - static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); - static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); -private: - static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } - static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary; - static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; - static LLVOAvatarXmlInfo* sAvatarXmlInfo; - - //-------------------------------------------------------------------- - // Messaging - //-------------------------------------------------------------------- -public: - void onFirstTEMessageReceived(); -private: - BOOL mFirstTEMessageReceived; - BOOL mFirstAppearanceMessageReceived; - -/** Textures - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** MESHES - **/ - -public: - void updateMeshTextures(); - void updateSexDependentLayerSets(BOOL upload_bake); - 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 - 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 - //-------------------------------------------------------------------- -protected: - BOOL mMeshValid; - LLFrameTimer mMeshInvisibleTime; - -/** Meshes - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** APPEARANCE - **/ - -public: - void processAvatarAppearance(LLMessageSystem* mesgsys); - void hideSkirt(); - void startAppearanceAnimation(); - - //-------------------------------------------------------------------- - // Appearance morphing - //-------------------------------------------------------------------- -public: - BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } -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; - - //-------------------------------------------------------------------- - // Visibility - //-------------------------------------------------------------------- -public: - BOOL isVisible() const; - void setVisibilityRank(U32 rank); - U32 getVisibilityRank() const { return mVisibilityRank; } // unused - static S32 sNumVisibleAvatars; // Number of instances of this class - static LLColor4 getDummyColor(); -/** Appearance - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** WEARABLES - **/ - -public: - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; - - //-------------------------------------------------------------------- - // Attachments - //-------------------------------------------------------------------- -public: - void clampAttachmentPositions(); - virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); - virtual BOOL detachObject(LLViewerObject *viewer_object); - void cleanupAttachedMesh( LLViewerObject* pVO ); - static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); -protected: - LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); - void lazyAttach(); - void rebuildRiggedAttachments( void ); - - //-------------------------------------------------------------------- - // Map of attachment points, by ID - //-------------------------------------------------------------------- -public: - S32 getAttachmentCount(); // Warning: order(N) not order(1) // currently used only by -self - typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t; - attachment_map_t mAttachmentPoints; - std::vector<LLPointer<LLViewerObject> > mPendingAttachment; - - //-------------------------------------------------------------------- - // HUD functions - //-------------------------------------------------------------------- -public: - BOOL hasHUDAttachment() const; - LLBBox getHUDBBox() const; - void rebuildHUD(); - void resetHUDAttachments(); - BOOL canAttachMoreObjects() const; - BOOL canAttachMoreObjects(U32 n) const; -protected: - U32 getNumAttachments() const; // O(N), not O(1) - -/** Wearables - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** ACTIONS - **/ - - //-------------------------------------------------------------------- - // Animations - //-------------------------------------------------------------------- -public: - BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const; - void processAnimationStateChanges(); -protected: - BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start); - void resetAnimations(); -private: - LLTimer mAnimTimer; - F32 mTimeLast; - - //-------------------------------------------------------------------- - // Animation state data - //-------------------------------------------------------------------- -public: - typedef std::map<LLUUID, S32>::iterator AnimIterator; - std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value - std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value - - typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap; - typedef AnimationSourceMap::iterator AnimSourceIterator; - AnimationSourceMap mAnimationSources; // object ids that triggered anim ids - - //-------------------------------------------------------------------- - // Chat - //-------------------------------------------------------------------- -public: - void addChat(const LLChat& chat); - void clearChat(); - void startTyping() { mTyping = TRUE; mTypingTimer.reset(); } - void stopTyping() { mTyping = FALSE; } -private: - BOOL mVisibleChat; - - //-------------------------------------------------------------------- - // Lip synch morphs - //-------------------------------------------------------------------- -private: - bool mLipSyncActive; // we're morphing for lip sync - LLVisualParam* mOohMorph; // cached pointers morphs for lip sync - LLVisualParam* mAahMorph; // cached pointers morphs for lip sync - - //-------------------------------------------------------------------- - // Flight - //-------------------------------------------------------------------- -public: - BOOL mInAir; - LLFrameTimer mTimeInAir; - -/** Actions - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** PHYSICS - **/ - -private: - F32 mSpeedAccum; // measures speed (for diagnostics mostly). - BOOL mTurning; // controls hysteresis on avatar rotation - F32 mSpeed; // misc. animation repeated state - - //-------------------------------------------------------------------- - // Collision volumes - //-------------------------------------------------------------------- -public: - S32 mNumCollisionVolumes; - LLViewerJointCollisionVolume* mCollisionVolumes; -protected: - BOOL allocateCollisionVolumes(U32 num); - - //-------------------------------------------------------------------- - // Dimensions - //-------------------------------------------------------------------- -public: - void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm); - bool distanceToGround( const LLVector3d &startPoint, LLVector3d &collisionPoint, F32 distToIntersectionAlongRay ); - void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); - 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 - //-------------------------------------------------------------------- -private: - BOOL mStepOnLand; - U8 mStepMaterial; - LLVector3 mStepObjectVelocity; - -/** Physics - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** HIERARCHY - **/ - -public: - virtual BOOL setParent(LLViewerObject* parent); - virtual void addChild(LLViewerObject *childp); - virtual void removeChild(LLViewerObject *childp); - - //-------------------------------------------------------------------- - // Sitting - //-------------------------------------------------------------------- -public: - void sitDown(BOOL bSitting); - BOOL isSitting(){return mIsSitting;} - void sitOnObject(LLViewerObject *sit_object); - void getOffObject(); -private: - // set this property only with LLVOAvatar::sitDown method - BOOL mIsSitting; - -/** Hierarchy - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** NAME - **/ - -public: - std::string getFullname() const; // Returns "FirstName LastName" -protected: - static void getAnimLabels(LLDynamicArray<std::string>* labels); - static void getAnimNames(LLDynamicArray<std::string>* names); -private: - std::string mNameString; // UTF-8 title + name + status - std::string mTitle; - bool mNameAway; - bool mNameBusy; - bool mNameMute; - bool mNameAppearance; - bool mNameFriend; - bool mNameCloud; - F32 mNameAlpha; - BOOL mRenderGroupTitles; - - //-------------------------------------------------------------------- - // Display the name (then optionally fade it out) - //-------------------------------------------------------------------- -public: - LLFrameTimer mChatTimer; - LLPointer<LLHUDNameTag> mNameText; -private: - LLFrameTimer mTimeVisible; - std::deque<LLChat> mChats; - BOOL mTyping; - LLFrameTimer mTypingTimer; - -/** Name - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** SOUNDS - **/ - - //-------------------------------------------------------------------- - // Voice visualizer - //-------------------------------------------------------------------- -public: - // Responsible for detecting the user's voice signal (and when the - // user speaks, it puts a voice symbol over the avatar's head) and gesticulations - LLPointer<LLVoiceVisualizer> mVoiceVisualizer; - int mCurrentGesticulationLevel; - - //-------------------------------------------------------------------- - // Step sound - //-------------------------------------------------------------------- -protected: - const LLUUID& getStepSound() const; -private: - // Global table of sound ids per material, and the ground - const static LLUUID sStepSounds[LL_MCODE_END]; - const static LLUUID sStepSoundOnLand; - - //-------------------------------------------------------------------- - // Foot step state (for generating sounds) - //-------------------------------------------------------------------- -public: - void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } - LLVector4 mFootPlane; -private: - BOOL mWasOnGroundLeft; - BOOL mWasOnGroundRight; - -/** Sounds - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** DIAGNOSTICS - **/ - - //-------------------------------------------------------------------- - // General - //-------------------------------------------------------------------- -public: - static void dumpArchetypeXML(void*); - static void dumpBakedStatus(); - const std::string getBakedStatusForPrintout() const; - void dumpAvatarTEs(const std::string& context) const; - - static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars - static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) - static F32 sGreyTime; // Total seconds with >=1 grey avatars - static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) -protected: - S32 getUnbakedPixelAreaRank(); - BOOL mHasGrey; -private: - F32 mMinPixelArea; - F32 mMaxPixelArea; - F32 mAdjustedPixelArea; - std::string mDebugText; - - - //-------------------------------------------------------------------- - // Avatar Rez Metrics - //-------------------------------------------------------------------- -public: - F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } -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. - -/** Diagnostics - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** SUPPORT CLASSES - **/ - -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 - ** ** - *******************************************************************************/ - -}; // LLVOAvatar -extern const F32 SELF_ADDITIONAL_PRI; -extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; - -#endif // LL_VO_AVATAR_H +/** + * @file llvoavatar.h + * @brief Declaration of LLVOAvatar class which is a derivation of + * LLViewerObject + * + * $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_LLVOAVATAR_H +#define LL_LLVOAVATAR_H + +#include <map> +#include <deque> +#include <string> +#include <vector> + +#include <boost/signals2.hpp> + +#include "imageids.h" // IMG_INVISIBLE +#include "llchat.h" +#include "lldrawpoolalpha.h" +#include "llviewerobject.h" +#include "llcharacter.h" +#include "llviewerjointmesh.h" +#include "llviewerjointattachment.h" +#include "llrendertarget.h" +#include "llvoavatardefines.h" +#include "lltexglobalcolor.h" +#include "lldriverparam.h" +#include "material_codes.h" // LL_MCODE_END + +extern const LLUUID ANIM_AGENT_BODY_NOISE; +extern const LLUUID ANIM_AGENT_BREATHE_ROT; +extern const LLUUID ANIM_AGENT_PHYSICS_MOTION; +extern const LLUUID ANIM_AGENT_EDITING; +extern const LLUUID ANIM_AGENT_EYE; +extern const LLUUID ANIM_AGENT_FLY_ADJUST; +extern const LLUUID ANIM_AGENT_HAND_MOTION; +extern const LLUUID ANIM_AGENT_HEAD_ROT; +extern const LLUUID ANIM_AGENT_PELVIS_FIX; +extern const LLUUID ANIM_AGENT_TARGET; +extern const LLUUID ANIM_AGENT_WALK_ADJUST; + +class LLTexLayerSet; +class LLVoiceVisualizer; +class LLHUDNameTag; +class LLHUDEffectSpiral; +class LLTexGlobalColor; +class LLVOAvatarBoneInfo; +class LLVOAvatarSkeletonInfo; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLVOAvatar +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLVOAvatar : + public LLViewerObject, + public LLCharacter, + public boost::signals2::trackable +{ +public: + friend class LLVOAvatarSelf; +protected: + struct LLVOAvatarXmlInfo; + struct LLMaskedMorph; + +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ + +public: + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + virtual void markDead(); + static void initClass(); // Initialize data that's only init'd once per class. + static void cleanupClass(); // Cleanup data that's only init'd once per class. + virtual void initInstance(); // Called after construction to initialize the class. +protected: + virtual ~LLVOAvatar(); + BOOL loadSkeletonNode(); + BOOL loadMeshNodes(); + virtual BOOL loadLayersets(); + +/** Initialization + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** INHERITED + **/ + + //-------------------------------------------------------------------- + // LLViewerObject interface and related + //-------------------------------------------------------------------- +public: + virtual void updateGL(); + virtual LLVOAvatar* asAvatar(); + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); + virtual BOOL 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, + S32 face = -1, // which face to check, -1 = ALL_SIDES + BOOL pick_transparent = FALSE, + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point + + //-------------------------------------------------------------------- + // 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 void stopMotionFromSource(const LLUUID& source_id); + virtual void requestStopMotion(LLMotion* motion); + LLMotion* findMotion(const LLUUID& id) const; + void startDefaultMotions(); + 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(); + 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 void updateVisualParams(); + + +/** Inherited + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** STATE + **/ + +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 + LLVector4a mImpostorExtents[2]; + +private: + BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients + + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- +public: + virtual BOOL updateCharacter(LLAgent &agent); + void idleUpdateVoiceVisualizer(bool voice_enabled); + void idleUpdateMisc(bool detailed_update); + virtual void idleUpdateAppearanceAnimation(); + void idleUpdateLipSync(bool voice_enabled); + void idleUpdateLoadingEffect(); + void idleUpdateWindEffect(); + void idleUpdateNameTag(const LLVector3& root_pos_last); + void idleUpdateNameTagText(BOOL new_name); + LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); + LLColor4 getNameTagColor(bool is_friend); + void clearNameTag(); + static void invalidateNameTag(const LLUUID& agent_id); + // force all name tags to rebuild, useful when display names turned on/off + static void invalidateNameTags(); + void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font); + void idleUpdateRenderCost(); + void idleUpdateBelowWater(); + + //-------------------------------------------------------------------- + // Static preferences (controlled by user settings/menus) + //-------------------------------------------------------------------- +public: + static S32 sRenderName; + static BOOL sRenderGroupTitles; + static U32 sMaxVisible; //(affected by control "RenderAvatarMaxVisible") + static F32 sRenderDistance; //distance at which avatars will render. + static BOOL sShowAnimationDebug; // show animation debug info + static BOOL sUseImpostors; //use impostors for far away avatars + static BOOL sShowFootPlane; // show foot collision plane reported by server + static BOOL sShowCollisionVolumes; // show skeletal collision volumes + static BOOL sVisibleInFirstPerson; + static S32 sNumLODChangesThisFrame; + static S32 sNumVisibleChatBubbles; + static BOOL sDebugInvisible; + static BOOL sShowAttachmentPoints; + static F32 sLODFactor; // user-settable LOD factor + static F32 sPhysicsLODFactor; // user-settable physics LOD factor + static BOOL sJointDebug; // output total number of joints being touched for each avatar + static BOOL sDebugAvatarRotation; + + //-------------------------------------------------------------------- + // Region state + //-------------------------------------------------------------------- +public: + LLHost getObjectHost() const; + + //-------------------------------------------------------------------- + // Loading state + //-------------------------------------------------------------------- +public: + BOOL isFullyLoaded() const; + bool visualParamWeightsAreDefault(); +protected: + virtual BOOL getIsCloud(); + BOOL updateIsFullyLoaded(); + BOOL processFullyLoadedChange(bool loading); + void updateRuthTimer(bool loading); + F32 calcMorphAmount(); +private: + BOOL mFullyLoaded; + BOOL mPreviousFullyLoaded; + BOOL mFullyLoadedInitialized; + S32 mFullyLoadedFrameCounter; + LLFrameTimer mFullyLoadedTimer; + LLFrameTimer mRuthTimer; +protected: + LLFrameTimer mInvisibleTimer; + +/** State + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SKELETON + **/ + +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 ); + + bool mHasPelvisOffset; + LLVector3 mPelvisOffset; + F32 mLastPelvisToFoot; + F32 mPelvisFixup; + F32 mLastPelvisFixup; + + LLVector3 mHeadOffset; // current head position + LLViewerJoint mRoot; +protected: + static BOOL parseSkeletonFile(const std::string& filename); + void buildCharacter(); + virtual BOOL loadAvatar(); + + BOOL setupBone(const LLVOAvatarBoneInfo* 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 LLXmlTree sSkeletonXMLTree; // avatar skeleton file + +/** Skeleton + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** RENDERING + **/ + +public: + U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); + U32 renderRigid(); + U32 renderSkinned(EAvatarRenderPass pass); + F32 getLastSkinTime() { return mLastSkinTime; } + U32 renderSkinnedAttachments(); + U32 renderTransparent(BOOL first_pass); + void renderCollisionVolumes(); + static void deleteCachedImages(bool clearAll=true); + static void destroyGL(); + static void restoreGL(); + BOOL mIsDummy; // for special views + S32 mSpecialRenderMode; // special lighting +private: + bool shouldAlphaMask(); + + BOOL mNeedsSkin; // avatar has been animated and verts have not been updated + F32 mLastSkinTime; //value of gFrameTimeSeconds at last skin update + + S32 mUpdatePeriod; + S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. + + //-------------------------------------------------------------------- + // 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); + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +protected: + void updateVisibility(); +private: + U32 mVisibilityRank; + BOOL mVisible; + + //-------------------------------------------------------------------- + // Shadowing + //-------------------------------------------------------------------- +public: + void updateShadowFaces(); + LLDrawable* mShadow; +private: + LLFace* mShadow0Facep; + LLFace* mShadow1Facep; + LLPointer<LLViewerTexture> mShadowImagep; + + //-------------------------------------------------------------------- + // Impostors + //-------------------------------------------------------------------- +public: + BOOL isImpostor() const; + BOOL needsImpostorUpdate() const; + const LLVector3& getImpostorOffset() const; + const LLVector2& getImpostorDim() const; + void getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const; + void cacheImpostorValues(); + void setImpostorDim(const LLVector2& dim); + static void resetImpostors(); + static void updateImpostors(); + LLRenderTarget mImpostor; + BOOL mNeedsImpostorUpdate; +private: + LLVector3 mImpostorOffset; + LLVector2 mImpostorDim; + BOOL mNeedsAnimUpdate; + LLVector3 mImpostorAngle; + F32 mImpostorDistance; + F32 mImpostorPixelArea; + LLVector3 mLastAnimExtents[2]; + + //-------------------------------------------------------------------- + // Wind rippling in clothes + //-------------------------------------------------------------------- +public: + LLVector4 mWindVec; + F32 mRipplePhase; + BOOL mBelowWater; +private: + F32 mWindFreq; + LLFrameTimer mRippleTimer; + F32 mRippleTimeLast; + LLVector3 mRippleAccel; + LLVector3 mLastVel; + + //-------------------------------------------------------------------- + // Culling + //-------------------------------------------------------------------- +public: + static void cullAvatarsByPixelArea(); + BOOL isCulled() const { return mCulled; } +private: + BOOL mCulled; + + //-------------------------------------------------------------------- + // Freeze counter + //-------------------------------------------------------------------- +public: + static void updateFreezeCounter(S32 counter = 0); +private: + static S32 sFreezeCounter; + + //-------------------------------------------------------------------- + // Constants + //-------------------------------------------------------------------- +public: + virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; } + virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; } + virtual S32 getTexImageSize() const; + virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } + +/** Rendering + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** TEXTURES + **/ + + //-------------------------------------------------------------------- + // 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; + +protected: + BOOL isFullyBaked(); + static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); + + //-------------------------------------------------------------------- + // Baked textures + //-------------------------------------------------------------------- +public: + 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); + static void onInitialBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + 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); + + 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; + //-------------------------------------------------------------------- + // 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); + // MULTI-WEARABLE: make self-only? + virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); + + //-------------------------------------------------------------------- + // Texture accessors + //-------------------------------------------------------------------- +private: + virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); + virtual LLViewerTexture* getImage(const U8 te, const U32 index) const; + + virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; + virtual void setTexEntry(const U8 index, const LLTextureEntry &te); + + void checkTextureLoading() ; + //-------------------------------------------------------------------- + // Layers + //-------------------------------------------------------------------- +protected: + void deleteLayerSetCaches(bool clearAll = true); + void addBakedTextureStats(LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); + virtual void invalidateAll(); + virtual void setCompositeUpdatesEnabled(bool b) {} + virtual void setCompositeUpdatesEnabled(U32 index, bool b) {} + virtual bool isCompositeUpdateEnabled(U32 index) { return false; } + + //-------------------------------------------------------------------- + // Static texture/mesh/baked dictionary + //-------------------------------------------------------------------- +public: + static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); + static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); +private: + static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } + static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary; + static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLVOAvatarXmlInfo* sAvatarXmlInfo; + + //-------------------------------------------------------------------- + // Messaging + //-------------------------------------------------------------------- +public: + void onFirstTEMessageReceived(); +private: + BOOL mFirstTEMessageReceived; + BOOL mFirstAppearanceMessageReceived; + +/** Textures + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** MESHES + **/ + +public: + void updateMeshTextures(); + void updateSexDependentLayerSets(BOOL upload_bake); + 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 + 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 + //-------------------------------------------------------------------- +protected: + BOOL mMeshValid; + LLFrameTimer mMeshInvisibleTime; + +/** Meshes + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** APPEARANCE + **/ + +public: + void processAvatarAppearance(LLMessageSystem* mesgsys); + void hideSkirt(); + void startAppearanceAnimation(); + + //-------------------------------------------------------------------- + // Appearance morphing + //-------------------------------------------------------------------- +public: + BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } +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; + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + BOOL isVisible() const; + void setVisibilityRank(U32 rank); + U32 getVisibilityRank() const { return mVisibilityRank; } // unused + static S32 sNumVisibleAvatars; // Number of instances of this class + static LLColor4 getDummyColor(); +/** Appearance + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** WEARABLES + **/ + +public: + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; + + //-------------------------------------------------------------------- + // Attachments + //-------------------------------------------------------------------- +public: + void clampAttachmentPositions(); + virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); + virtual BOOL detachObject(LLViewerObject *viewer_object); + void cleanupAttachedMesh( LLViewerObject* pVO ); + static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); +protected: + LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); + void lazyAttach(); + void rebuildRiggedAttachments( void ); + + //-------------------------------------------------------------------- + // Map of attachment points, by ID + //-------------------------------------------------------------------- +public: + S32 getAttachmentCount(); // Warning: order(N) not order(1) // currently used only by -self + typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t; + attachment_map_t mAttachmentPoints; + std::vector<LLPointer<LLViewerObject> > mPendingAttachment; + + //-------------------------------------------------------------------- + // HUD functions + //-------------------------------------------------------------------- +public: + BOOL hasHUDAttachment() const; + LLBBox getHUDBBox() const; + void rebuildHUD(); + void resetHUDAttachments(); + BOOL canAttachMoreObjects() const; + BOOL canAttachMoreObjects(U32 n) const; +protected: + U32 getNumAttachments() const; // O(N), not O(1) + +/** Wearables + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** ACTIONS + **/ + + //-------------------------------------------------------------------- + // Animations + //-------------------------------------------------------------------- +public: + BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const; + void processAnimationStateChanges(); +protected: + BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start); + void resetAnimations(); +private: + LLTimer mAnimTimer; + F32 mTimeLast; + + //-------------------------------------------------------------------- + // Animation state data + //-------------------------------------------------------------------- +public: + typedef std::map<LLUUID, S32>::iterator AnimIterator; + std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value + std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value + + typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap; + typedef AnimationSourceMap::iterator AnimSourceIterator; + AnimationSourceMap mAnimationSources; // object ids that triggered anim ids + + //-------------------------------------------------------------------- + // Chat + //-------------------------------------------------------------------- +public: + void addChat(const LLChat& chat); + void clearChat(); + void startTyping() { mTyping = TRUE; mTypingTimer.reset(); } + void stopTyping() { mTyping = FALSE; } +private: + BOOL mVisibleChat; + + //-------------------------------------------------------------------- + // Lip synch morphs + //-------------------------------------------------------------------- +private: + bool mLipSyncActive; // we're morphing for lip sync + LLVisualParam* mOohMorph; // cached pointers morphs for lip sync + LLVisualParam* mAahMorph; // cached pointers morphs for lip sync + + //-------------------------------------------------------------------- + // Flight + //-------------------------------------------------------------------- +public: + BOOL mInAir; + LLFrameTimer mTimeInAir; + +/** Actions + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** PHYSICS + **/ + +private: + F32 mSpeedAccum; // measures speed (for diagnostics mostly). + BOOL mTurning; // controls hysteresis on avatar rotation + F32 mSpeed; // misc. animation repeated state + + //-------------------------------------------------------------------- + // Collision volumes + //-------------------------------------------------------------------- +public: + S32 mNumCollisionVolumes; + LLViewerJointCollisionVolume* mCollisionVolumes; +protected: + BOOL allocateCollisionVolumes(U32 num); + + //-------------------------------------------------------------------- + // Dimensions + //-------------------------------------------------------------------- +public: + void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm); + bool distanceToGround( const LLVector3d &startPoint, LLVector3d &collisionPoint, F32 distToIntersectionAlongRay ); + void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); + 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 + //-------------------------------------------------------------------- +private: + BOOL mStepOnLand; + U8 mStepMaterial; + LLVector3 mStepObjectVelocity; + +/** Physics + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** HIERARCHY + **/ + +public: + virtual BOOL setParent(LLViewerObject* parent); + virtual void addChild(LLViewerObject *childp); + virtual void removeChild(LLViewerObject *childp); + + //-------------------------------------------------------------------- + // Sitting + //-------------------------------------------------------------------- +public: + void sitDown(BOOL bSitting); + BOOL isSitting(){return mIsSitting;} + void sitOnObject(LLViewerObject *sit_object); + void getOffObject(); +private: + // set this property only with LLVOAvatar::sitDown method + BOOL mIsSitting; + +/** Hierarchy + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** NAME + **/ + +public: + std::string getFullname() const; // Returns "FirstName LastName" +protected: + static void getAnimLabels(LLDynamicArray<std::string>* labels); + static void getAnimNames(LLDynamicArray<std::string>* names); +private: + std::string mNameString; // UTF-8 title + name + status + std::string mTitle; + bool mNameAway; + bool mNameBusy; + bool mNameMute; + bool mNameAppearance; + bool mNameFriend; + bool mNameCloud; + F32 mNameAlpha; + BOOL mRenderGroupTitles; + + //-------------------------------------------------------------------- + // Display the name (then optionally fade it out) + //-------------------------------------------------------------------- +public: + LLFrameTimer mChatTimer; + LLPointer<LLHUDNameTag> mNameText; +private: + LLFrameTimer mTimeVisible; + std::deque<LLChat> mChats; + BOOL mTyping; + LLFrameTimer mTypingTimer; + +/** Name + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SOUNDS + **/ + + //-------------------------------------------------------------------- + // Voice visualizer + //-------------------------------------------------------------------- +public: + // Responsible for detecting the user's voice signal (and when the + // user speaks, it puts a voice symbol over the avatar's head) and gesticulations + LLPointer<LLVoiceVisualizer> mVoiceVisualizer; + int mCurrentGesticulationLevel; + + //-------------------------------------------------------------------- + // Step sound + //-------------------------------------------------------------------- +protected: + const LLUUID& getStepSound() const; +private: + // Global table of sound ids per material, and the ground + const static LLUUID sStepSounds[LL_MCODE_END]; + const static LLUUID sStepSoundOnLand; + + //-------------------------------------------------------------------- + // Foot step state (for generating sounds) + //-------------------------------------------------------------------- +public: + void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } + LLVector4 mFootPlane; +private: + BOOL mWasOnGroundLeft; + BOOL mWasOnGroundRight; + +/** Sounds + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** DIAGNOSTICS + **/ + + //-------------------------------------------------------------------- + // General + //-------------------------------------------------------------------- +public: + static void dumpArchetypeXML(void*); + static void dumpBakedStatus(); + const std::string getBakedStatusForPrintout() const; + void dumpAvatarTEs(const std::string& context) const; + + static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars + static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) + static F32 sGreyTime; // Total seconds with >=1 grey avatars + static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) +protected: + S32 getUnbakedPixelAreaRank(); + BOOL mHasGrey; +private: + F32 mMinPixelArea; + F32 mMaxPixelArea; + F32 mAdjustedPixelArea; + std::string mDebugText; + + + //-------------------------------------------------------------------- + // Avatar Rez Metrics + //-------------------------------------------------------------------- +public: + F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } +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. + +/** Diagnostics + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SUPPORT CLASSES + **/ + +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 + ** ** + *******************************************************************************/ + +}; // LLVOAvatar +extern const F32 SELF_ADDITIONAL_PRI; +extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; + +#endif // LL_VO_AVATAR_H diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 1f9be20c751f30c55c3c17010dbac1f177f667ad..b888a263d0c863c1d7f3ea15e9c4d90e0dc1d98c 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1,756 +1,756 @@ -/** - * @file llvocache.cpp - * @brief Cache of objects on the viewer. - * - * $LicenseInfo:firstyear=2003&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 "llvocache.h" -#include "llerror.h" -#include "llregionhandle.h" -#include "llviewercontrol.h" - -BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) -{ - return apr_file->read(src, n_bytes) == n_bytes ; -} - -BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) -{ - return apr_file->write(src, n_bytes) == n_bytes ; -} - - -//--------------------------------------------------------------------------- -// LLVOCacheEntry -//--------------------------------------------------------------------------- - -LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) - : - mLocalID(local_id), - mCRC(crc), - mHitCount(0), - mDupeCount(0), - mCRCChangeCount(0) -{ - mBuffer = new U8[dp.getBufferSize()]; - mDP.assignBuffer(mBuffer, dp.getBufferSize()); - mDP = dp; -} - -LLVOCacheEntry::LLVOCacheEntry() - : - mLocalID(0), - mCRC(0), - mHitCount(0), - mDupeCount(0), - mCRCChangeCount(0), - mBuffer(NULL) -{ - mDP.assignBuffer(mBuffer, 0); -} - -LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) - : mBuffer(NULL) -{ - S32 size = -1; - BOOL success; - - success = check_read(apr_file, &mLocalID, sizeof(U32)); - if(success) - { - success = check_read(apr_file, &mCRC, sizeof(U32)); - } - if(success) - { - success = check_read(apr_file, &mHitCount, sizeof(S32)); - } - if(success) - { - success = check_read(apr_file, &mDupeCount, sizeof(S32)); - } - if(success) - { - success = check_read(apr_file, &mCRCChangeCount, sizeof(S32)); - } - if(success) - { - success = check_read(apr_file, &size, sizeof(S32)); - - // Corruption in the cache entries - if ((size > 10000) || (size < 1)) - { - // We've got a bogus size, skip reading it. - // We won't bother seeking, because the rest of this file - // is likely bogus, and will be tossed anyway. - llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl; - success = FALSE; - } - } - if(success && size > 0) - { - mBuffer = new U8[size]; - success = check_read(apr_file, mBuffer, size); - - if(success) - { - mDP.assignBuffer(mBuffer, size); - } - else - { - delete[] mBuffer ; - mBuffer = NULL ; - } - } - - if(!success) - { - mLocalID = 0; - mCRC = 0; - mHitCount = 0; - mDupeCount = 0; - mCRCChangeCount = 0; - mBuffer = NULL; - } -} - -LLVOCacheEntry::~LLVOCacheEntry() -{ - if(mBuffer) - { - delete[] mBuffer; - } -} - - -// New CRC means the object has changed. -void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) -{ - if ( (mCRC != crc) - ||(mDP.getBufferSize() == 0)) - { - mCRC = crc; - mHitCount = 0; - mCRCChangeCount++; - - mDP.freeBuffer(); - mBuffer = new U8[dp.getBufferSize()]; - mDP.assignBuffer(mBuffer, dp.getBufferSize()); - mDP = dp; - } -} - -LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) -{ - if ( (mCRC != crc) - ||(mDP.getBufferSize() == 0)) - { - //llinfos << "Not getting cache entry, invalid!" << llendl; - return NULL; - } - mHitCount++; - return &mDP; -} - - -void LLVOCacheEntry::recordHit() -{ - mHitCount++; -} - - -void LLVOCacheEntry::dump() const -{ - llinfos << "local " << mLocalID - << " crc " << mCRC - << " hits " << mHitCount - << " dupes " << mDupeCount - << " change " << mCRCChangeCount - << llendl; -} - -BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const -{ - BOOL success; - success = check_write(apr_file, (void*)&mLocalID, sizeof(U32)); - if(success) - { - success = check_write(apr_file, (void*)&mCRC, sizeof(U32)); - } - if(success) - { - success = check_write(apr_file, (void*)&mHitCount, sizeof(S32)); - } - if(success) - { - success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32)); - } - if(success) - { - success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32)); - } - if(success) - { - S32 size = mDP.getBufferSize(); - success = check_write(apr_file, (void*)&size, sizeof(S32)); - - if(success) - { - success = check_write(apr_file, (void*)mBuffer, size); - } - } - - return success ; -} - -//------------------------------------------------------------------- -//LLVOCache -//------------------------------------------------------------------- -// Format string used to construct filename for the object cache -static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; - -const U32 MAX_NUM_OBJECT_ENTRIES = 128 ; -const U32 MIN_ENTRIES_TO_PURGE = 16 ; -const U32 INVALID_TIME = 0 ; -const char* object_cache_dirname = "objectcache"; -const char* header_filename = "object.cache"; - -LLVOCache* LLVOCache::sInstance = NULL; - -//static -LLVOCache* LLVOCache::getInstance() -{ - if(!sInstance) - { - sInstance = new LLVOCache() ; - } - return sInstance ; -} - -//static -BOOL LLVOCache::hasInstance() -{ - return sInstance != NULL ; -} - -//static -void LLVOCache::destroyClass() -{ - if(sInstance) - { - delete sInstance ; - sInstance = NULL ; - } -} - -LLVOCache::LLVOCache(): - mInitialized(FALSE), - mReadOnly(TRUE), - mNumEntries(0), - mCacheSize(1) -{ - mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); - mLocalAPRFilePoolp = new LLVolatileAPRPool() ; -} - -LLVOCache::~LLVOCache() -{ - if(mEnabled) - { - writeCacheHeader(); - clearCacheInMemory(); - } - delete mLocalAPRFilePoolp; -} - -void LLVOCache::setDirNames(ELLPath location) -{ - std::string delem = gDirUtilp->getDirDelimiter(); - - mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); - mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); -} - -void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) -{ - if(!mEnabled) - { - llwarns << "Not initializing cache: Cache is currently disabled." << llendl; - return ; - } - - if(mInitialized) - { - llwarns << "Cache already initialized." << llendl; - return ; - } - mInitialized = TRUE ; - - setDirNames(location); - if (!mReadOnly) - { - LLFile::mkdir(mObjectCacheDirName); - } - mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES); - mMetaInfo.mVersion = cache_version; - readCacheHeader(); - - if(mMetaInfo.mVersion != cache_version) - { - mMetaInfo.mVersion = cache_version ; - if(mReadOnly) //disable cache - { - clearCacheInMemory(); - } - else //delete the current cache if the format does not match. - { - removeCache(); - } - } -} - -void LLVOCache::removeCache(ELLPath location) -{ - if(mReadOnly) - { - llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; - return ; - } - - llinfos << "about to remove the object cache due to settings." << llendl ; - - std::string delem = gDirUtilp->getDirDelimiter(); - std::string mask = delem + "*"; - std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); - llinfos << "Removing cache at " << cache_dir << llendl; - gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files - LLFile::rmdir(cache_dir); - - clearCacheInMemory(); - mInitialized = FALSE ; -} - -void LLVOCache::removeCache() -{ - llassert_always(mInitialized) ; - if(mReadOnly) - { - llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; - return ; - } - - llinfos << "about to remove the object cache due to some error." << llendl ; - - std::string delem = gDirUtilp->getDirDelimiter(); - std::string mask = delem + "*"; - llinfos << "Removing cache at " << mObjectCacheDirName << llendl; - gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); - - clearCacheInMemory() ; - writeCacheHeader(); -} - -void LLVOCache::removeEntry(HeaderEntryInfo* entry) -{ - llassert_always(mInitialized) ; - if(mReadOnly) - { - return ; - } - if(!entry) - { - return ; - } - - header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ; - if(iter != mHeaderEntryQueue.end()) - { - mHandleEntryMap.erase(entry->mHandle) ; - mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; - delete entry ; - - mNumEntries = mHandleEntryMap.size() ; - } -} - -void LLVOCache::removeEntry(U64 handle) -{ - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //no cache - { - return ; - } - HeaderEntryInfo* entry = iter->second ; - removeEntry(entry) ; -} - -void LLVOCache::clearCacheInMemory() -{ - if(!mHeaderEntryQueue.empty()) - { - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter) - { - delete *iter ; - } - mHeaderEntryQueue.clear(); - mHandleEntryMap.clear(); - mNumEntries = 0 ; - } - -} - -void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) -{ - U32 region_x, region_y; - - grid_from_region_handle(handle, ®ion_x, ®ion_y); - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, - llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); - - return ; -} - -void LLVOCache::removeFromCache(HeaderEntryInfo* entry) -{ - if(mReadOnly) - { - llwarns << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << llendl; - return ; - } - - std::string filename; - getObjectCacheFilename(entry->mHandle, filename); - LLAPRFile::remove(filename, mLocalAPRFilePoolp); - entry->mTime = INVALID_TIME ; - updateEntry(entry) ; //update the head file. -} - -void LLVOCache::readCacheHeader() -{ - if(!mEnabled) - { - llwarns << "Not reading cache header: Cache is currently disabled." << llendl; - return; - } - - //clear stale info. - clearCacheInMemory(); - - bool success = true ; - if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) - { - LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - - //read the meta element - success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; - - if(success) - { - HeaderEntryInfo* entry = NULL ; - mNumEntries = 0 ; - U32 num_read = 0 ; - while(num_read++ < MAX_NUM_OBJECT_ENTRIES) - { - if(!entry) - { - entry = new HeaderEntryInfo() ; - } - success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); - - if(!success) //failed - { - llwarns << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << llendl; - delete entry ; - entry = NULL ; - break ; - } - else if(entry->mTime == INVALID_TIME) - { - continue ; //an empty entry - } - - entry->mIndex = mNumEntries++ ; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[entry->mHandle] = entry ; - entry = NULL ; - } - if(entry) - { - delete entry ; - } - } - - //--------- - //debug code - //---------- - //std::string name ; - //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) - //{ - // getObjectCacheFilename((*iter)->mHandle, name) ; - // llinfos << name << llendl ; - //} - //----------- - } - else - { - writeCacheHeader() ; - } - - if(!success) - { - removeCache() ; //failed to read header, clear the cache - } - else if(mNumEntries >= mCacheSize) - { - purgeEntries(mCacheSize) ; - } - - return ; -} - -void LLVOCache::writeCacheHeader() -{ - if (!mEnabled) - { - llwarns << "Not writing cache header: Cache is currently disabled." << llendl; - return; - } - - if(mReadOnly) - { - llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl; - return; - } - - bool success = true ; - { - LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - - //write the meta element - success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; - - - mNumEntries = 0 ; - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) - { - (*iter)->mIndex = mNumEntries++ ; - success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo)); - } - - mNumEntries = mHeaderEntryQueue.size() ; - if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) - { - HeaderEntryInfo* entry = new HeaderEntryInfo() ; - entry->mTime = INVALID_TIME ; - for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) - { - //fill the cache with the default entry. - success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ; - - } - delete entry ; - } - } - - if(!success) - { - clearCacheInMemory() ; - mReadOnly = TRUE ; //disable the cache. - } - return ; -} - -BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) -{ - LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - - return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; -} - -void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) -{ - if(!mEnabled) - { - llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl; - return ; - } - llassert_always(mInitialized); - - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //no cache - { - llwarns << "No handle map entry for " << handle << llendl; - return ; - } - - bool success = true ; - { - std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - - LLUUID cache_id ; - success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ; - - if(success) - { - if(cache_id != id) - { - llinfos << "Cache ID doesn't match for this region, discarding"<< llendl; - success = false ; - } - - if(success) - { - S32 num_entries; - success = check_read(&apr_file, &num_entries, sizeof(S32)) ; - - for (S32 i = 0; success && i < num_entries; i++) - { - LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); - if (!entry->getLocalID()) - { - llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; - delete entry ; - success = false ; - } - cache_entry_map[entry->getLocalID()] = entry; - } - } - } - } - - if(!success) - { - if(cache_entry_map.empty()) - { - removeEntry(iter->second) ; - } - } - - return ; -} - -void LLVOCache::purgeEntries(U32 size) -{ - while(mHeaderEntryQueue.size() > size) - { - header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; - HeaderEntryInfo* entry = *iter ; - mHandleEntryMap.erase(entry->mHandle); - mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; - delete entry; - } - mNumEntries = mHandleEntryMap.size() ; -} - -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) -{ - if(!mEnabled) - { - llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl; - return ; - } - llassert_always(mInitialized); - - if(mReadOnly) - { - llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; - return ; - } - - HeaderEntryInfo* entry; - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //new entry - { - if(mNumEntries >= mCacheSize - 1) - { - purgeEntries(mCacheSize - 1) ; - } - - entry = new HeaderEntryInfo(); - entry->mHandle = handle ; - entry->mTime = time(NULL) ; - entry->mIndex = mNumEntries++; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[handle] = entry ; - } - else - { - // Update access time. - entry = iter->second ; - - //resort - mHeaderEntryQueue.erase(entry) ; - - entry->mTime = time(NULL) ; - mHeaderEntryQueue.insert(entry) ; - } - - //update cache header - if(!updateEntry(entry)) - { - llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl; - return ; //update failed. - } - - if(!dirty_cache) - { - llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl; - return ; //nothing changed, no need to update. - } - - //write to cache file - bool success = true ; - { - std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - - success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ; - - - if(success) - { - S32 num_entries = cache_entry_map.size() ; - success = check_write(&apr_file, &num_entries, sizeof(S32)); - - for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) - { - success = iter->second->writeToFile(&apr_file) ; - } - } - } - - if(!success) - { - removeEntry(entry) ; - - } - - return ; -} - +/** + * @file llvocache.cpp + * @brief Cache of objects on the viewer. + * + * $LicenseInfo:firstyear=2003&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 "llvocache.h" +#include "llerror.h" +#include "llregionhandle.h" +#include "llviewercontrol.h" + +BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) +{ + return apr_file->read(src, n_bytes) == n_bytes ; +} + +BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) +{ + return apr_file->write(src, n_bytes) == n_bytes ; +} + + +//--------------------------------------------------------------------------- +// LLVOCacheEntry +//--------------------------------------------------------------------------- + +LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) + : + mLocalID(local_id), + mCRC(crc), + mHitCount(0), + mDupeCount(0), + mCRCChangeCount(0) +{ + mBuffer = new U8[dp.getBufferSize()]; + mDP.assignBuffer(mBuffer, dp.getBufferSize()); + mDP = dp; +} + +LLVOCacheEntry::LLVOCacheEntry() + : + mLocalID(0), + mCRC(0), + mHitCount(0), + mDupeCount(0), + mCRCChangeCount(0), + mBuffer(NULL) +{ + mDP.assignBuffer(mBuffer, 0); +} + +LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) + : mBuffer(NULL) +{ + S32 size = -1; + BOOL success; + + success = check_read(apr_file, &mLocalID, sizeof(U32)); + if(success) + { + success = check_read(apr_file, &mCRC, sizeof(U32)); + } + if(success) + { + success = check_read(apr_file, &mHitCount, sizeof(S32)); + } + if(success) + { + success = check_read(apr_file, &mDupeCount, sizeof(S32)); + } + if(success) + { + success = check_read(apr_file, &mCRCChangeCount, sizeof(S32)); + } + if(success) + { + success = check_read(apr_file, &size, sizeof(S32)); + + // Corruption in the cache entries + if ((size > 10000) || (size < 1)) + { + // We've got a bogus size, skip reading it. + // We won't bother seeking, because the rest of this file + // is likely bogus, and will be tossed anyway. + llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl; + success = FALSE; + } + } + if(success && size > 0) + { + mBuffer = new U8[size]; + success = check_read(apr_file, mBuffer, size); + + if(success) + { + mDP.assignBuffer(mBuffer, size); + } + else + { + delete[] mBuffer ; + mBuffer = NULL ; + } + } + + if(!success) + { + mLocalID = 0; + mCRC = 0; + mHitCount = 0; + mDupeCount = 0; + mCRCChangeCount = 0; + mBuffer = NULL; + } +} + +LLVOCacheEntry::~LLVOCacheEntry() +{ + if(mBuffer) + { + delete[] mBuffer; + } +} + + +// New CRC means the object has changed. +void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) +{ + if ( (mCRC != crc) + ||(mDP.getBufferSize() == 0)) + { + mCRC = crc; + mHitCount = 0; + mCRCChangeCount++; + + mDP.freeBuffer(); + mBuffer = new U8[dp.getBufferSize()]; + mDP.assignBuffer(mBuffer, dp.getBufferSize()); + mDP = dp; + } +} + +LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) +{ + if ( (mCRC != crc) + ||(mDP.getBufferSize() == 0)) + { + //llinfos << "Not getting cache entry, invalid!" << llendl; + return NULL; + } + mHitCount++; + return &mDP; +} + + +void LLVOCacheEntry::recordHit() +{ + mHitCount++; +} + + +void LLVOCacheEntry::dump() const +{ + llinfos << "local " << mLocalID + << " crc " << mCRC + << " hits " << mHitCount + << " dupes " << mDupeCount + << " change " << mCRCChangeCount + << llendl; +} + +BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const +{ + BOOL success; + success = check_write(apr_file, (void*)&mLocalID, sizeof(U32)); + if(success) + { + success = check_write(apr_file, (void*)&mCRC, sizeof(U32)); + } + if(success) + { + success = check_write(apr_file, (void*)&mHitCount, sizeof(S32)); + } + if(success) + { + success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32)); + } + if(success) + { + success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32)); + } + if(success) + { + S32 size = mDP.getBufferSize(); + success = check_write(apr_file, (void*)&size, sizeof(S32)); + + if(success) + { + success = check_write(apr_file, (void*)mBuffer, size); + } + } + + return success ; +} + +//------------------------------------------------------------------- +//LLVOCache +//------------------------------------------------------------------- +// Format string used to construct filename for the object cache +static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; + +const U32 MAX_NUM_OBJECT_ENTRIES = 128 ; +const U32 MIN_ENTRIES_TO_PURGE = 16 ; +const U32 INVALID_TIME = 0 ; +const char* object_cache_dirname = "objectcache"; +const char* header_filename = "object.cache"; + +LLVOCache* LLVOCache::sInstance = NULL; + +//static +LLVOCache* LLVOCache::getInstance() +{ + if(!sInstance) + { + sInstance = new LLVOCache() ; + } + return sInstance ; +} + +//static +BOOL LLVOCache::hasInstance() +{ + return sInstance != NULL ; +} + +//static +void LLVOCache::destroyClass() +{ + if(sInstance) + { + delete sInstance ; + sInstance = NULL ; + } +} + +LLVOCache::LLVOCache(): + mInitialized(FALSE), + mReadOnly(TRUE), + mNumEntries(0), + mCacheSize(1) +{ + mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; +} + +LLVOCache::~LLVOCache() +{ + if(mEnabled) + { + writeCacheHeader(); + clearCacheInMemory(); + } + delete mLocalAPRFilePoolp; +} + +void LLVOCache::setDirNames(ELLPath location) +{ + std::string delem = gDirUtilp->getDirDelimiter(); + + mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); + mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); +} + +void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) +{ + if(!mEnabled) + { + llwarns << "Not initializing cache: Cache is currently disabled." << llendl; + return ; + } + + if(mInitialized) + { + llwarns << "Cache already initialized." << llendl; + return ; + } + mInitialized = TRUE ; + + setDirNames(location); + if (!mReadOnly) + { + LLFile::mkdir(mObjectCacheDirName); + } + mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES); + mMetaInfo.mVersion = cache_version; + readCacheHeader(); + + if(mMetaInfo.mVersion != cache_version) + { + mMetaInfo.mVersion = cache_version ; + if(mReadOnly) //disable cache + { + clearCacheInMemory(); + } + else //delete the current cache if the format does not match. + { + removeCache(); + } + } +} + +void LLVOCache::removeCache(ELLPath location) +{ + if(mReadOnly) + { + llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; + return ; + } + + llinfos << "about to remove the object cache due to settings." << llendl ; + + std::string delem = gDirUtilp->getDirDelimiter(); + std::string mask = delem + "*"; + std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); + llinfos << "Removing cache at " << cache_dir << llendl; + gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files + LLFile::rmdir(cache_dir); + + clearCacheInMemory(); + mInitialized = FALSE ; +} + +void LLVOCache::removeCache() +{ + llassert_always(mInitialized) ; + if(mReadOnly) + { + llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; + return ; + } + + llinfos << "about to remove the object cache due to some error." << llendl ; + + std::string delem = gDirUtilp->getDirDelimiter(); + std::string mask = delem + "*"; + llinfos << "Removing cache at " << mObjectCacheDirName << llendl; + gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); + + clearCacheInMemory() ; + writeCacheHeader(); +} + +void LLVOCache::removeEntry(HeaderEntryInfo* entry) +{ + llassert_always(mInitialized) ; + if(mReadOnly) + { + return ; + } + if(!entry) + { + return ; + } + + header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ; + if(iter != mHeaderEntryQueue.end()) + { + mHandleEntryMap.erase(entry->mHandle) ; + mHeaderEntryQueue.erase(iter) ; + removeFromCache(entry) ; + delete entry ; + + mNumEntries = mHandleEntryMap.size() ; + } +} + +void LLVOCache::removeEntry(U64 handle) +{ + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //no cache + { + return ; + } + HeaderEntryInfo* entry = iter->second ; + removeEntry(entry) ; +} + +void LLVOCache::clearCacheInMemory() +{ + if(!mHeaderEntryQueue.empty()) + { + for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter) + { + delete *iter ; + } + mHeaderEntryQueue.clear(); + mHandleEntryMap.clear(); + mNumEntries = 0 ; + } + +} + +void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) +{ + U32 region_x, region_y; + + grid_from_region_handle(handle, ®ion_x, ®ion_y); + filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, + llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); + + return ; +} + +void LLVOCache::removeFromCache(HeaderEntryInfo* entry) +{ + if(mReadOnly) + { + llwarns << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << llendl; + return ; + } + + std::string filename; + getObjectCacheFilename(entry->mHandle, filename); + LLAPRFile::remove(filename, mLocalAPRFilePoolp); + entry->mTime = INVALID_TIME ; + updateEntry(entry) ; //update the head file. +} + +void LLVOCache::readCacheHeader() +{ + if(!mEnabled) + { + llwarns << "Not reading cache header: Cache is currently disabled." << llendl; + return; + } + + //clear stale info. + clearCacheInMemory(); + + bool success = true ; + if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) + { + LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + + //read the meta element + success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + if(success) + { + HeaderEntryInfo* entry = NULL ; + mNumEntries = 0 ; + U32 num_read = 0 ; + while(num_read++ < MAX_NUM_OBJECT_ENTRIES) + { + if(!entry) + { + entry = new HeaderEntryInfo() ; + } + success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); + + if(!success) //failed + { + llwarns << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << llendl; + delete entry ; + entry = NULL ; + break ; + } + else if(entry->mTime == INVALID_TIME) + { + continue ; //an empty entry + } + + entry->mIndex = mNumEntries++ ; + mHeaderEntryQueue.insert(entry) ; + mHandleEntryMap[entry->mHandle] = entry ; + entry = NULL ; + } + if(entry) + { + delete entry ; + } + } + + //--------- + //debug code + //---------- + //std::string name ; + //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) + //{ + // getObjectCacheFilename((*iter)->mHandle, name) ; + // llinfos << name << llendl ; + //} + //----------- + } + else + { + writeCacheHeader() ; + } + + if(!success) + { + removeCache() ; //failed to read header, clear the cache + } + else if(mNumEntries >= mCacheSize) + { + purgeEntries(mCacheSize) ; + } + + return ; +} + +void LLVOCache::writeCacheHeader() +{ + if (!mEnabled) + { + llwarns << "Not writing cache header: Cache is currently disabled." << llendl; + return; + } + + if(mReadOnly) + { + llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl; + return; + } + + bool success = true ; + { + LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + + //write the meta element + success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + + mNumEntries = 0 ; + for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) + { + (*iter)->mIndex = mNumEntries++ ; + success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo)); + } + + mNumEntries = mHeaderEntryQueue.size() ; + if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) + { + HeaderEntryInfo* entry = new HeaderEntryInfo() ; + entry->mTime = INVALID_TIME ; + for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) + { + //fill the cache with the default entry. + success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ; + + } + delete entry ; + } + } + + if(!success) + { + clearCacheInMemory() ; + mReadOnly = TRUE ; //disable the cache. + } + return ; +} + +BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) +{ + LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; + + return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; +} + +void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +{ + if(!mEnabled) + { + llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl; + return ; + } + llassert_always(mInitialized); + + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //no cache + { + llwarns << "No handle map entry for " << handle << llendl; + return ; + } + + bool success = true ; + { + std::string filename; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + + LLUUID cache_id ; + success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ; + + if(success) + { + if(cache_id != id) + { + llinfos << "Cache ID doesn't match for this region, discarding"<< llendl; + success = false ; + } + + if(success) + { + S32 num_entries; + success = check_read(&apr_file, &num_entries, sizeof(S32)) ; + + for (S32 i = 0; success && i < num_entries; i++) + { + LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); + if (!entry->getLocalID()) + { + llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; + delete entry ; + success = false ; + } + cache_entry_map[entry->getLocalID()] = entry; + } + } + } + } + + if(!success) + { + if(cache_entry_map.empty()) + { + removeEntry(iter->second) ; + } + } + + return ; +} + +void LLVOCache::purgeEntries(U32 size) +{ + while(mHeaderEntryQueue.size() > size) + { + header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; + HeaderEntryInfo* entry = *iter ; + mHandleEntryMap.erase(entry->mHandle); + mHeaderEntryQueue.erase(iter) ; + removeFromCache(entry) ; + delete entry; + } + mNumEntries = mHandleEntryMap.size() ; +} + +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) +{ + if(!mEnabled) + { + llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl; + return ; + } + llassert_always(mInitialized); + + if(mReadOnly) + { + llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; + return ; + } + + HeaderEntryInfo* entry; + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //new entry + { + if(mNumEntries >= mCacheSize - 1) + { + purgeEntries(mCacheSize - 1) ; + } + + entry = new HeaderEntryInfo(); + entry->mHandle = handle ; + entry->mTime = time(NULL) ; + entry->mIndex = mNumEntries++; + mHeaderEntryQueue.insert(entry) ; + mHandleEntryMap[handle] = entry ; + } + else + { + // Update access time. + entry = iter->second ; + + //resort + mHeaderEntryQueue.erase(entry) ; + + entry->mTime = time(NULL) ; + mHeaderEntryQueue.insert(entry) ; + } + + //update cache header + if(!updateEntry(entry)) + { + llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl; + return ; //update failed. + } + + if(!dirty_cache) + { + llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl; + return ; //nothing changed, no need to update. + } + + //write to cache file + bool success = true ; + { + std::string filename; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + + success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ; + + + if(success) + { + S32 num_entries = cache_entry_map.size() ; + success = check_write(&apr_file, &num_entries, sizeof(S32)); + + for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) + { + success = iter->second->writeToFile(&apr_file) ; + } + } + } + + if(!success) + { + removeEntry(entry) ; + + } + + return ; +} + diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index daaf2a4e96af6df4a2887f8063d22efa63a1e3dc..6ee6822e2fcdc4eae6b7bc4f9d1a49d337c98e2c 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5088,7 +5088,7 @@ void LLVivoxVoiceClient::enforceTether(void) } } - if(dist_vec(mCameraPosition, tethered) > 0.1) + if(dist_vec_squared(mCameraPosition, tethered) > 0.01) { mCameraPosition = tethered; mSpatialCoordsDirty = true; @@ -5150,7 +5150,7 @@ void LLVivoxVoiceClient::setCameraPosition(const LLVector3d &position, const LLV void LLVivoxVoiceClient::setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot) { - if(dist_vec(mAvatarPosition, position) > 0.1) + if(dist_vec_squared(mAvatarPosition, position) > 0.01) { mAvatarPosition = position; mSpatialCoordsDirty = true; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 45277265df73b31eccd17a69275a3a75283648c8..9d2887d2e83af647e3c729f064b91d671e8459e0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1,4709 +1,4709 @@ -/** - * @file llvovolume.cpp - * @brief LLVOVolume class implementation - * - * $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$ - */ - -// A "volume" is a box, cylinder, sphere, or other primitive shape. - -#include "llviewerprecompiledheaders.h" - -#include "llvovolume.h" - -#include <sstream> - -#include "llviewercontrol.h" -#include "lldir.h" -#include "llflexibleobject.h" -#include "llfloatertools.h" -#include "llmaterialtable.h" -#include "llprimitive.h" -#include "llvolume.h" -#include "llvolumeoctree.h" -#include "llvolumemgr.h" -#include "llvolumemessage.h" -#include "material_codes.h" -#include "message.h" -#include "llpluginclassmedia.h" // for code in the mediaEvent handler -#include "object_flags.h" -#include "llagentconstants.h" -#include "lldrawable.h" -#include "lldrawpoolavatar.h" -#include "lldrawpoolbump.h" -#include "llface.h" -#include "llspatialpartition.h" -#include "llhudmanager.h" -#include "llflexibleobject.h" -#include "llsky.h" -#include "lltexturefetch.h" -#include "llvector4a.h" -#include "llviewercamera.h" -#include "llviewertexturelist.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llviewertextureanim.h" -#include "llworld.h" -#include "llselectmgr.h" -#include "pipeline.h" -#include "llsdutil.h" -#include "llmatrix4a.h" -#include "llmediaentry.h" -#include "llmediadataclient.h" -#include "llmeshrepository.h" -#include "llagent.h" -#include "llviewermediafocus.h" -#include "llvoavatar.h" - -const S32 MIN_QUIET_FRAMES_COALESCE = 30; -const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; -const F32 FORCE_CULL_AREA = 8.f; -const F32 MAX_LOD_DISTANCE = 24.f; - - -BOOL gAnimateTextures = TRUE; -//extern BOOL gHideSelectedObjects; - -F32 LLVOVolume::sLODFactor = 1.f; -F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop -F32 LLVOVolume::sDistanceFactor = 1.0f; -S32 LLVOVolume::sNumLODChanges = 0; -LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL; -LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL; - -static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); -static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); -static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); - -// Implementation class of LLMediaDataClientObject. See llmediadataclient.h -class LLMediaDataClientObjectImpl : public LLMediaDataClientObject -{ -public: - LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) - { - mObject->addMDCImpl(); - } - ~LLMediaDataClientObjectImpl() - { - mObject->removeMDCImpl(); - } - - virtual U8 getMediaDataCount() const - { return mObject->getNumTEs(); } - - virtual LLSD getMediaDataLLSD(U8 index) const - { - LLSD result; - LLTextureEntry *te = mObject->getTE(index); - if (NULL != te) - { - llassert((te->getMediaData() != NULL) == te->hasMedia()); - if (te->getMediaData() != NULL) - { - result = te->getMediaData()->asLLSD(); - // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly - // See DEV-41949 - if (!result.has(LLMediaEntry::WHITELIST_KEY)) - { - result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); - } - } - } - return result; - } - virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const - { - LLTextureEntry *te = mObject->getTE(index); - if (te) - { - if (te->getMediaData()) - { - return (te->getMediaData()->getCurrentURL() == url); - } - } - return url.empty(); - } - - virtual LLUUID getID() const - { return mObject->getID(); } - - virtual void mediaNavigateBounceBack(U8 index) - { mObject->mediaNavigateBounceBack(index); } - - virtual bool hasMedia() const - { return mObject->hasMedia(); } - - virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) - { mObject->updateObjectMediaData(data, version_string); } - - virtual F64 getMediaInterest() const - { - F64 interest = mObject->getTotalMediaInterest(); - if (interest < (F64)0.0) - { - // media interest not valid yet, try pixel area - interest = mObject->getPixelArea(); - // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. - if (interest == 1024.f) - { - const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent); - interest = mObject->getPixelArea(); - } - } - return interest; - } - - virtual bool isInterestingEnough() const - { - return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); - } - - virtual std::string getCapabilityUrl(const std::string &name) const - { return mObject->getRegion()->getCapability(name); } - - virtual bool isDead() const - { return mObject->isDead(); } - - virtual U32 getMediaVersion() const - { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } - - virtual bool isNew() const - { return mNew; } - -private: - LLPointer<LLVOVolume> mObject; - bool mNew; -}; - - -LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp), - mVolumeImpl(NULL) -{ - mTexAnimMode = 0; - mRelativeXform.setIdentity(); - mRelativeXformInvTrans.setIdentity(); - - mFaceMappingChanged = FALSE; - mLOD = MIN_LOD; - mTextureAnimp = NULL; - mVolumeChanged = FALSE; - mVObjRadius = LLVector3(1,1,0.5f).length(); - mNumFaces = 0; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mSpotLightPriority = 0.f; - - mMediaImplList.resize(getNumTEs()); - mLastFetchedMediaVersion = -1; - mIndexInTex = 0; - mMDCImplCount = 0; -} - -LLVOVolume::~LLVOVolume() -{ - delete mTextureAnimp; - mTextureAnimp = NULL; - delete mVolumeImpl; - mVolumeImpl = NULL; - - if(!mMediaImplList.empty()) - { - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - if(mMediaImplList[i].notNull()) - { - mMediaImplList[i]->removeObject(this) ; - } - } - } -} - -void LLVOVolume::markDead() -{ - if (!mDead) - { - if(getMDCImplCount() > 0) - { - LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); - if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); - if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); - } - - // Detach all media impls from this object - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - removeMediaImpl(i); - } - - if (mSculptTexture.notNull()) - { - mSculptTexture->removeVolume(this); - } - } - - LLViewerObject::markDead(); -} - - -// static -void LLVOVolume::initClass() -{ - // gSavedSettings better be around - if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) - { - const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); - const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); - const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); - sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, - max_sorted_queue_size, max_round_robin_queue_size); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, - max_retries, max_sorted_queue_size, max_round_robin_queue_size); - } -} - -// static -void LLVOVolume::cleanupClass() -{ - sObjectMediaClient = NULL; - sObjectMediaNavigateClient = NULL; -} - -U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, EObjectUpdateType update_type, - LLDataPacker *dp) -{ - LLColor4U color; - const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); - - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - - LLUUID sculpt_id; - U8 sculpt_type = 0; - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - sculpt_id = sculpt_params->getSculptTexture(); - sculpt_type = sculpt_params->getSculptType(); - } - - if (!dp) - { - if (update_type == OUT_FULL) - { - //////////////////////////////// - // - // Unpack texture animation data - // - // - - if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - mTextureAnimp->unpackTAMessage(mesgsys, block_num); - } - else - { - if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - - // Unpack volume data - LLVolumeParams volume_params; - LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - } - - // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... - //////////////////////////// - // - // Unpack texture entry data - // - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - else - { - // CORY TO DO: Figure out how to get the value here - if (update_type != OUT_TERSE_IMPROVED) - { - LLVolumeParams volume_params; - BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); - if (!res) - { - llwarns << "Bogus volume parameters in object " << getID() << llendl; - llwarns << getRegion()->getOriginGlobal() << llendl; - } - - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - S32 res2 = unpackTEMessage(*dp); - if (TEM_INVALID == res2) - { - // There's something bogus in the data that we're unpacking. - dp->dumpBufferToLog(); - llwarns << "Flushing cache files" << llendl; - - if(LLVOCache::hasInstance() && getRegion()) - { - LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; - } - - llwarns << "Bogus TE data in " << getID() << llendl; - } - else - { - if (res2 & teDirtyBits) - { - updateTEData(); - } - if (res2 & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - - U32 value = dp->getPassFlags(); - - if (value & 0x40) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - mTextureAnimp->unpackTAMessage(*dp); - } - else if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - else - { - S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); - if (texture_length) - { - U8 tdpbuffer[1024]; - LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num); - S32 result = unpackTEMessage(tdp); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - } - } - if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) - { - // If only the media URL changed, and it isn't a media version URL, - // ignore it - if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && - mMedia && ! mMedia->mMediaURL.empty() && - ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) - { - // If the media changed at all, request new media data - LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << - ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); - } - else { - LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << - ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - } - } - // ...and clean up any media impls - cleanUpMediaImpls(); - - return retval; -} - - -void LLVOVolume::animateTextures() -{ - F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; - S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); - - if (result) - { - if (!mTexAnimMode) - { - mFaceMappingChanged = TRUE; - gPipeline.markTextured(mDrawable); - } - mTexAnimMode = result | mTextureAnimp->mMode; - - S32 start=0, end=mDrawable->getNumFaces()-1; - if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) - { - start = end = mTextureAnimp->mFace; - } - - for (S32 i = start; i <= end; i++) - { - LLFace* facep = mDrawable->getFace(i); - if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - - const LLTextureEntry* te = facep->getTextureEntry(); - - if (!te) - { - continue; - } - - if (!(result & LLViewerTextureAnim::ROTATE)) - { - te->getRotation(&rot); - } - if (!(result & LLViewerTextureAnim::TRANSLATE)) - { - te->getOffset(&off_s,&off_t); - } - if (!(result & LLViewerTextureAnim::SCALE)) - { - te->getScale(&scale_s, &scale_t); - } - - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } - - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); - LLVector3 trans ; - - if(facep->isAtlasInUse()) - { - // - //if use atlas for animated texture - //apply the following transform to the animation matrix. - // - - F32 tcoord_xoffset = 0.f ; - F32 tcoord_yoffset = 0.f ; - F32 tcoord_xscale = 1.f ; - F32 tcoord_yscale = 1.f ; - if(facep->isAtlasInUse()) - { - const LLVector2* tmp = facep->getTexCoordOffset() ; - tcoord_xoffset = tmp->mV[0] ; - tcoord_yoffset = tmp->mV[1] ; - - tmp = facep->getTexCoordScale() ; - tcoord_xscale = tmp->mV[0] ; - tcoord_yscale = tmp->mV[1] ; - } - trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); - - tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); - } - else //non atlas - { - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - } - - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - - tex_mat.rotate(quat); - - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; - - tex_mat.translate(trans); - } - } - else - { - if (mTexAnimMode && mTextureAnimp->mRate == 0) - { - U8 start, count; - - if (mTextureAnimp->mFace == -1) - { - start = 0; - count = getNumTEs(); - } - else - { - start = (U8) mTextureAnimp->mFace; - count = 1; - } - - for (S32 i = start; i < start + count; i++) - { - if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) - { - setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); - } - if (mTexAnimMode & LLViewerTextureAnim::SCALE) - { - setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); - } - if (mTexAnimMode & LLViewerTextureAnim::ROTATE) - { - setTERotation(i, mTextureAnimp->mRot); - } - } - - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } -} -BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - LLViewerObject::idleUpdate(agent, world, time); - - static LLFastTimer::DeclareTimer ftm("Volume"); - LLFastTimer t(ftm); - - if (mDead || mDrawable.isNull()) - { - return TRUE; - } - - /////////////////////// - // - // Do texture animation stuff - // - - if (mTextureAnimp && gAnimateTextures) - { - animateTextures(); - } - - // Dispatch to implementation - if (mVolumeImpl) - { - mVolumeImpl->doIdleUpdate(agent, world, time); - } - - const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; - - if (mDrawable->isActive()) - { - if (mDrawable->isRoot() && - mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && - (!mDrawable->getParent() || !mDrawable->getParent()->isActive())) - { - mDrawable->makeStatic(); - } - } - - return TRUE; -} - -void LLVOVolume::updateTextures() -{ - const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) - { - updateTextureVirtualSize(); - } -} - -BOOL LLVOVolume::isVisible() const -{ - if(mDrawable.notNull() && mDrawable->isVisible()) - { - return TRUE ; - } - - if(isAttachment()) - { - LLViewerObject* objp = (LLViewerObject*)getParent() ; - while(objp && !objp->isAvatar()) - { - objp = (LLViewerObject*)objp->getParent() ; - } - - return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; - } - - return FALSE ; -} - -void LLVOVolume::updateTextureVirtualSize() -{ - LLFastTimer ftm(FTM_VOLUME_TEXTURES); - // Update the pixel area of all faces - - if(!isVisible()) - { - return ; - } - - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; - } - - static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); - - if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) - { - return; - } - - mTextureUpdateTimer.reset(); - - F32 old_area = mPixelArea; - mPixelArea = 0.f; - - const S32 num_faces = mDrawable->getNumFaces(); - F32 min_vsize=999999999.f, max_vsize=0.f; - LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - const LLTextureEntry *te = face->getTextureEntry(); - LLViewerTexture *imagep = face->getTexture(); - if (!imagep || !te || - face->mExtents[0].equals3(face->mExtents[1])) - { - continue; - } - - F32 vsize; - F32 old_size = face->getVirtualSize(); - - if (isHUDAttachment()) - { - F32 area = (F32) camera->getScreenPixelArea(); - vsize = area; - imagep->setBoostLevel(LLViewerTexture::BOOST_HUD); - face->setPixelArea(area); // treat as full screen - face->setVirtualSize(vsize); - } - else - { - vsize = face->getTextureVirtualSize(); - } - - mPixelArea = llmax(mPixelArea, face->getPixelArea()); - - if (face->mTextureMatrix != NULL) - { - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - if (vsize < min_vsize) min_vsize = vsize; - if (vsize > max_vsize) max_vsize = vsize; - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; - if(img) - { - F32 pri = img->getDecodePriority(); - pri = llmax(pri, 0.0f); - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - F32 pri = mPixelArea; - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - - updateSculptTexture(); - - - - if (mSculptTexture.notNull()) - { - mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLViewerTexture::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - - if(!mSculptTexture->isCachedRawImageReady()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - - //if the sculpty very close to the view point, load first - { - LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; - mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; - } - } - - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture - S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) - { - setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); - } - } - - } - - if (getLightTextureID().notNull()) - { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id); - if (mLightTexture.notNull()) - { - F32 rad = getLightRadius(); - mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), - LLVector3(rad,rad,rad), - *camera)); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - - if (mPixelArea == 0) - { //flexi phasing issues make this happen - mPixelArea = old_area; - } -} - -BOOL LLVOVolume::isActive() const -{ - return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) || - (mDrawable.notNull() && mDrawable->isActive()); -} - -BOOL LLVOVolume::setMaterial(const U8 material) -{ - BOOL res = LLViewerObject::setMaterial(material); - - return res; -} - -void LLVOVolume::setTexture(const S32 face) -{ - llassert(face < getNumTEs()); - gGL.getTexUnit(0)->bind(getTEImage(face)); -} - -void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) -{ - if (scale != getScale()) - { - // store local radius - LLViewerObject::setScale(scale); - - if (mVolumeImpl) - { - mVolumeImpl->onSetScale(scale, damped); - } - - updateRadius(); - - //since drawable transforms do not include scale, changing volume scale - //requires an immediate rebuild of volume verts. - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); - } -} - -LLFace* LLVOVolume::addFace(S32 f) -{ - const LLTextureEntry* te = getTE(f); - LLViewerTexture* imagep = getTEImage(f); - return mDrawable->addFace(te, imagep); -} - -LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) -{ - pipeline->allocDrawable(this); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - - S32 max_tes_to_set = getNumTEs(); - for (S32 i = 0; i < max_tes_to_set; i++) - { - addFace(i); - } - mNumFaces = max_tes_to_set; - - if (isAttachment()) - { - mDrawable->makeActive(); - } - - if (getIsLight()) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - - updateRadius(); - bool force_update = true; // avoid non-alpha mDistance update being optimized away - mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); - - return mDrawable; -} - -BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) -{ - LLVolumeParams volume_params = params_in; - - S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; - S32 lod = mLOD; - - BOOL is404 = FALSE; - - if (isSculpted()) - { - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { //meshes might not have all LODs, get the force detail to best existing LOD - - LLUUID mesh_id = volume_params.getSculptID(); - - //profile and path params don't matter for meshes - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) - { - is404 = TRUE; - lod = 0; - } - } - } - - // Check if we need to change implementations - bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); - if (is_flexible) - { - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); - if (!mVolumeImpl) - { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - mVolumeImpl = new LLVolumeImplFlexible(this, data); - } - } - else - { - // Mark the parameter not in use - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); - if (mVolumeImpl) - { - delete mVolumeImpl; - mVolumeImpl = NULL; - if (mDrawable.notNull()) - { - // Undo the damage we did to this matrix - mDrawable->updateXform(FALSE); - } - } - } - - if (is404) - { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); - } - - if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) - { - mFaceMappingChanged = TRUE; - - if (mVolumeImpl) - { - mVolumeImpl->onSetVolume(volume_params, mLOD); - } - - updateSculptTexture(); - - - if (isSculpted()) - { - updateSculptTexture(); - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - if (getVolume()->getNumVolumeFaces() == 0 || getVolume()->isTetrahedron()) - { - //load request not yet issued, request pipeline load this mesh - LLUUID asset_id = volume_params.getSculptID(); - S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); - if (available_lod != lod) - { - LLPrimitive::setVolume(volume_params, available_lod); - } - } - - } - else // otherwise is sculptie - { - if (mSculptTexture.notNull()) - { - sculpt(); - } - } - } - - return TRUE; - } - - return FALSE; -} - -void LLVOVolume::updateSculptTexture() -{ - LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture; - - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) - { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - } - else - { - mSculptTexture = NULL; - } - - if (mSculptTexture != old_sculpt) - { - if (old_sculpt.notNull()) - { - old_sculpt->removeVolume(this); - } - if (mSculptTexture.notNull()) - { - mSculptTexture->addVolume(this); - } - } - -} - - - -void LLVOVolume::notifyMeshLoaded() -{ - mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); -} - -// sculpt replaces generate() for sculpted surfaces -void LLVOVolume::sculpt() -{ - if (mSculptTexture.notNull()) - { - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - - S32 discard_level = mSculptTexture->getDiscardLevel() ; - LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; - - S32 max_discard = mSculptTexture->getMaxDiscardLevel(); - if (discard_level > max_discard) - discard_level = max_discard; // clamp to the best we can do - - S32 current_discard = getVolume()->getSculptLevel() ; - if(current_discard < -2) - { - llwarns << "WARNING!!: Current discard of sculpty at " << current_discard - << " is less than -2." << llendl; - - // corrupted volume... don't update the sculpty - return; - } - else if (current_discard > MAX_DISCARD_LEVEL) - { - llwarns << "WARNING!!: Current discard of sculpty at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; - - // corrupted volume... don't update the sculpty - return; - } - - if (current_discard == discard_level) // no work to do here - return; - - if(!raw_image) - { - llassert(discard_level < 0) ; - - sculpt_width = 0; - sculpt_height = 0; - sculpt_data = NULL ; - - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); - } - } - else - { - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - sculpt_data = raw_image->getData(); - - if(LLViewerTextureManager::sTesterp) - { - mSculptTexture->updateBindStatsForTester() ; - } - } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); - - //notify rebuild any other VOVolumes that reference this sculpty volume - for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) - { - LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i]; - if (volume != this && volume->getVolume() == getVolume()) - { - gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); - } - } - } -} - -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) -{ - S32 cur_detail; - if (LLPipeline::sDynamicLOD) - { - // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; - cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f)); - } - else - { - cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3); - } - return cur_detail; -} - -BOOL LLVOVolume::calcLOD() -{ - if (mDrawable.isNull()) - { - return FALSE; - } - - S32 cur_detail = 0; - - F32 radius; - F32 distance; - - if (mDrawable->isState(LLDrawable::RIGGED)) - { - LLVOAvatar* avatar = getAvatar(); - distance = avatar->mDrawable->mDistanceWRTCamera; - radius = avatar->getBinRadius(); - } - else - { - distance = mDrawable->mDistanceWRTCamera; - radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); - } - - //hold onto unmodified distance for debugging - F32 debug_distance = distance; - - distance *= sDistanceFactor; - - F32 rampDist = LLVOVolume::sLODFactor * 2; - - if (distance < rampDist) - { - // Boost LOD when you're REALLY close - distance *= 1.0f/rampDist; - distance *= distance; - distance *= rampDist; - } - - // DON'T Compensate for field of view changing on FOV zoom. - distance *= F_PI/3.f; - - cur_detail = computeLODDetail(llround(distance, 0.01f), - llround(radius, 0.01f)); - - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) - { - setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); - } - - if (cur_detail != mLOD) - { - mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - mLOD = cur_detail; - return TRUE; - } - else - { - return FALSE; - } -} - -BOOL LLVOVolume::updateLOD() -{ - if (mDrawable.isNull()) - { - return FALSE; - } - - BOOL lod_changed = calcLOD(); - - if (lod_changed) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mLODChanged = TRUE; - } - - lod_changed = lod_changed || LLViewerObject::updateLOD(); - - return lod_changed; -} - -BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) -{ - if (!LLViewerObject::setDrawableParent(parentp)) - { - // no change in drawable parent - return FALSE; - } - - if (!mDrawable->isRoot()) - { - // rebuild vertices in parent relative space - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - - if (mDrawable->isActive() && !parentp->isActive()) - { - parentp->makeActive(); - } - else if (mDrawable->isStatic() && parentp->isActive()) - { - mDrawable->makeActive(); - } - } - - return TRUE; -} - -void LLVOVolume::updateFaceFlags() -{ - for (S32 i = 0; i < getVolume()->getNumFaces(); i++) - { - LLFace *face = mDrawable->getFace(i); - if (!face) - { - return; - } - - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); - } - } -} - -BOOL LLVOVolume::setParent(LLViewerObject* parent) -{ - BOOL ret = FALSE ; - if (parent != getParent()) - { - ret = LLViewerObject::setParent(parent); - if (ret && mDrawable) - { - gPipeline.markMoved(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } - } - - return ret ; -} - -// NOTE: regenFaces() MUST be followed by genTriangles()! -void LLVOVolume::regenFaces() -{ - // remove existing faces - BOOL count_changed = mNumFaces != getNumTEs(); - - if (count_changed) - { - deleteFaces(); - // add new faces - mNumFaces = getNumTEs(); - } - - for (S32 i = 0; i < mNumFaces; i++) - { - LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); - facep->setTEOffset(i); - facep->setTexture(getTEImage(i)); - facep->setViewerObject(this); - - // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. - // Re-establish the link. - if((int)mMediaImplList.size() > i) - { - if(mMediaImplList[i]) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - } - } - - if (!count_changed) - { - updateFaceFlags(); - } -} - -BOOL LLVOVolume::genBBoxes(BOOL force_global) -{ - BOOL res = TRUE; - - LLVector4a min,max; - - min.clear(); - max.clear(); - - BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); - -// bool rigged = false; - LLVolume* volume = mRiggedVolume; - if (!volume) - { - volume = getVolume(); - } - - for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++) - { - LLFace *face = mDrawable->getFace(i); - if (!face) - { - continue; - } - res &= face->genVolumeBBoxes(*volume, i, - mRelativeXform, mRelativeXformInvTrans, - (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); - - if (rebuild) - { - if (i == 0) - { - min = face->mExtents[0]; - max = face->mExtents[1]; - } - else - { - min.setMin(min, face->mExtents[0]); - max.setMax(max, face->mExtents[1]); - } - } - } - - if (rebuild) - { - mDrawable->setSpatialExtents(min,max); - min.add(max); - min.mul(0.5f); - mDrawable->setPositionGroup(min); - } - - updateRadius(); - mDrawable->movePartition(); - - return res; -} - -void LLVOVolume::preRebuild() -{ - if (mVolumeImpl != NULL) - { - mVolumeImpl->preRebuild(); - } -} - -void LLVOVolume::updateRelativeXform() -{ - if (mVolumeImpl) - { - mVolumeImpl->updateRelativeXform(); - return; - } - - LLDrawable* drawable = mDrawable; - - if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) - { //rigged volume (which is in agent space) is used for generating bounding boxes etc - //inverse of render matrix should go to partition space - mRelativeXform = getRenderMatrix(); - - F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; - F32* src = (F32*) mRelativeXform.mMatrix; - dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; - dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; - dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; - - mRelativeXform.invert(); - mRelativeXformInvTrans.transpose(); - } - else if (drawable->isActive()) - { - // setup relative transforms - LLQuaternion delta_rot; - LLVector3 delta_pos, delta_scale; - - //matrix from local space to parent relative/global space - delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); - delta_scale = mDrawable->getScale(); - - // Vertex transform (4x4) - LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; - LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(delta_pos, 1.f)); - - - // compute inverse transpose for normals - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // mRelativeXformInvTrans.invert(); - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // grumble - invert is NOT a matrix invert, so we do it by hand: - - LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } - else - { - LLVector3 pos = getPosition(); - LLVector3 scale = getScale(); - LLQuaternion rot = getRotation(); - - if (mParent) - { - pos *= mParent->getRotation(); - pos += mParent->getPosition(); - rot *= mParent->getRotation(); - } - - //LLViewerRegion* region = getRegion(); - //pos += region->getOriginAgent(); - - LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; - LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(pos, 1.f)); - - // compute inverse transpose for normals - LLMatrix3 rot_inverse = LLMatrix3(~rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } -} - -static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies"); -static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); -static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); - -BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) -{ - LLFastTimer t(FTM_UPDATE_PRIMITIVES); - - if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) - { - { - LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME); - updateRiggedVolume(); - } - genBBoxes(FALSE); - mDrawable->clearState(LLDrawable::REBUILD_RIGGED); - } - - if (mVolumeImpl != NULL) - { - BOOL res; - { - LLFastTimer t(FTM_GEN_FLEX); - res = mVolumeImpl->doUpdateGeometry(drawable); - } - updateFaceFlags(); - return res; - } - - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - - BOOL compiled = FALSE; - - updateRelativeXform(); - - if (mDrawable.isNull()) // Not sure why this is happening, but it is... - { - return TRUE; // No update to complete - } - - if (mVolumeChanged || mFaceMappingChanged ) - { - compiled = TRUE; - - if (mVolumeChanged) - { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - drawable->setState(LLDrawable::REBUILD_VOLUME); - } - - { - LLFastTimer t(FTM_GEN_TRIANGLES); - regenFaces(); - genBBoxes(FALSE); - } - } - else if ((mLODChanged) || (mSculptChanged)) - { - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces ; - - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces() ; - old_volumep = NULL ; - - { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } - - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces() ; - new_volumep = NULL ; - - if ((new_lod != old_lod) || mSculptChanged) - { - compiled = TRUE; - sNumLODChanges += new_num_faces ; - - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - - { - LLFastTimer t(FTM_GEN_TRIANGLES); - if (new_num_faces != old_num_faces) - { - regenFaces(); - } - genBBoxes(FALSE); - - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } - } - // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local - else - { - compiled = TRUE; - // All it did was move or we changed the texture coordinate offset - LLFastTimer t(FTM_GEN_TRIANGLES); - genBBoxes(FALSE); - } - - // Update face flags - updateFaceFlags(); - - if(compiled) - { - LLPipeline::sCompiles++; - } - - mVolumeChanged = FALSE; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mFaceMappingChanged = FALSE; - - return LLViewerObject::updateGeometry(drawable); -} - -void LLVOVolume::updateFaceSize(S32 idx) -{ - LLFace* facep = mDrawable->getFace(idx); - if (idx >= getVolume()->getNumVolumeFaces()) - { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment - - } -} - -BOOL LLVOVolume::isRootEdit() const -{ - if (mParent && !((LLViewerObject*)mParent)->isAvatar()) - { - return FALSE; - } - return TRUE; -} - -//virtual -void LLVOVolume::setNumTEs(const U8 num_tes) -{ - const U8 old_num_tes = getNumTEs() ; - - if(old_num_tes && old_num_tes < num_tes) //new faces added - { - LLViewerObject::setNumTEs(num_tes) ; - - if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. - { - mMediaImplList.resize(num_tes) ; - const LLTextureEntry* te = getTE(old_num_tes - 1) ; - for(U8 i = old_num_tes; i < num_tes ; i++) - { - setTE(i, *te) ; - mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; - } - mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; - } - } - else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed - { - U8 end = mMediaImplList.size() ; - for(U8 i = num_tes; i < end ; i++) - { - removeMediaImpl(i) ; - } - mMediaImplList.resize(num_tes) ; - - LLViewerObject::setNumTEs(num_tes) ; - } - else - { - LLViewerObject::setNumTEs(num_tes) ; - } - - return ; -} - -void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) -{ - BOOL changed = (mTEImages[te] != imagep); - LLViewerObject::setTEImage(te, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } -} - -S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) -{ - S32 res = LLViewerObject::setTETexture(te, uuid); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) -{ - return setTEColor(te, LLColor4(color)); -} - -S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (color != tep->getColor()) - { - if (color.mV[3] != tep->getColor().mV[3]) - { - gPipeline.markTextured(mDrawable); - } - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - mDrawable->setState(LLDrawable::REBUILD_COLOR); - dirtyMesh(); - } - } - - return retval; -} - -S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) -{ - S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) -{ - S32 res = LLViewerObject::setTETexGen(te, texgen); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) -{ - S32 res = LLViewerObject::setTEMediaTexGen(te, media); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) -{ - S32 res = LLViewerObject::setTEShiny(te, shiny); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) -{ - S32 res = LLViewerObject::setTEFullbright(te, fullbright); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) -{ - S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) -{ - S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) -{ - S32 res = LLViewerObject::setTEGlow(te, glow); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) -{ - S32 res = LLViewerObject::setTEScale(te, s, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) -{ - S32 res = LLViewerObject::setTEScaleS(te, s); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) -{ - S32 res = LLViewerObject::setTEScaleT(te, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} - -void LLVOVolume::updateTEData() -{ - /*if (mDrawable.notNull()) - { - mFaceMappingChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); - }*/ -} - -bool LLVOVolume::hasMedia() const -{ - bool result = false; - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if(te->hasMedia()) - { - result = true; - break; - } - } - return result; -} - -LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) -{ - LLVolume* volume = getVolume(); - LLVector4a result; - result.clear(); - - LLVector3 ret; - - if (volume && face_id < volume->getNumVolumeFaces()) - { - const LLVolumeFace& face = volume->getVolumeFace(face_id); - for (S32 i = 0; i < (S32)face.mNumVertices; ++i) - { - result.add(face.mNormals[i]); - } - - LLVector3 ret(result.getF32ptr()); - ret = volumeDirectionToAgent(ret); - ret.normVec(); - } - - return ret; -} - -void LLVOVolume::requestMediaDataUpdate(bool isNew) -{ - if (sObjectMediaClient) - sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); -} - -bool LLVOVolume::isMediaDataBeingFetched() const -{ - // I know what I'm doing by const_casting this away: this is just - // a wrapper class that is only going to do a lookup. - return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false; -} - -void LLVOVolume::cleanUpMediaImpls() -{ - // Iterate through our TEs and remove any Impls that are no longer used - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if( ! te->hasMedia()) - { - // Delete the media IMPL! - removeMediaImpl(i) ; - } - } -} - -void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) -{ - // media_data_array is an array of media entry maps - // media_version is the version string in the response. - U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); - - // Only update it if it is newer! - if ( (S32)fetched_version > mLastFetchedMediaVersion) - { - mLastFetchedMediaVersion = fetched_version; - //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; - - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); - U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) - { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); - } - } -} - -void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) -{ - if(mDead) - { - // If the object has been marked dead, don't process media updates. - return; - } - - LLTextureEntry *te = getTE(texture_index); - if(!te) - { - return ; - } - - LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; - - std::string previous_url; - LLMediaEntry* mep = te->getMediaData(); - if(mep) - { - // Save the "current url" from before the update so we can tell if - // it changes. - previous_url = mep->getCurrentURL(); - } - - if (merge) - { - te->mergeIntoMediaData(media_data); - } - else { - // XXX Question: what if the media data is undefined LLSD, but the - // update we got above said that we have media flags?? Here we clobber - // that, assuming the data from the service is more up-to-date. - te->updateMediaData(media_data); - } - - mep = te->getMediaData(); - if(mep) - { - bool update_from_self = false; - if (!ignore_agent) - { - LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); - update_from_self = (updating_agent == gAgent.getID()); - } - viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); - - addMediaImpl(media_impl, texture_index) ; - } - else - { - removeMediaImpl(texture_index); - } - - LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; -} - -void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) -{ - // Find the media entry for this navigate - const LLMediaEntry* mep = NULL; - viewer_media_t impl = getMediaImpl(texture_index); - LLTextureEntry *te = getTE(texture_index); - if(te) - { - mep = te->getMediaData(); - } - - if (mep && impl) - { - std::string url = mep->getCurrentURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - // If the url we're trying to "bounce back" to is either empty or not - // allowed by the whitelist, try the home url. If *that* doesn't work, - // set the media as failed and unload it - if (url.empty() || !mep->checkCandidateUrl(url)) - { - url = mep->getHomeURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - } - if (url.empty() || !mep->checkCandidateUrl(url)) - { - // The url to navigate back to is not good, and we have nowhere else - // to go. - LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; - impl->setMediaFailed(true); - } - else { - // Okay, navigate now - LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; - impl->navigateTo(url, "", false, true); - } - } -} - -bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) -{ - // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). - if (NULL == media_entry ) return false; // XXX should we assert here? - - // The agent has permissions if: - // - world permissions are on, or - // - group permissions are on, and agent_id is in the group, or - // - agent permissions are on, and agent_id is the owner - - // *NOTE: We *used* to check for modify permissions here (i.e. permissions were - // granted if permModify() was true). However, this doesn't make sense in the - // viewer: we don't want to show controls or allow interaction if the author - // has deemed it so. See DEV-42115. - - U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); - - // World permissions - if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) - { - return true; - } - - // Group permissions - else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) - { - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) - { - return true; - } - } - - // Owner permissions - else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) - { - return true; - } - - return false; - -} - -void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) -{ - bool block_navigation = false; - // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed - // to deal with multiple face indices. - int face_index = getFaceIndexWithMediaImpl(impl, -1); - - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getTE(face_index); - if(te) - { - mep = te->getMediaData(); - } - - if(mep) - { - if(!mep->checkCandidateUrl(new_location)) - { - block_navigation = true; - } - if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) - { - block_navigation = true; - } - } - else - { - LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; - } - - if(block_navigation) - { - LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; - - // "bounce back" to the current URL from the media entry - mediaNavigateBounceBack(face_index); - } - else if (sObjectMediaNavigateClient) - { - - LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; - - sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); - } -} - -void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) -{ - switch(event) - { - - case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getLocation()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: - // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // This is a subsequent location-changed due to a redirect. Don't broadcast. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; - break; - } - } - break; - - case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getNavigateURI()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: - // This is the the navigate complete event from a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. - break; - } - } - break; - - default: - break; - } - -} - -void LLVOVolume::sendMediaDataUpdate() -{ - if (sObjectMediaClient) - sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); -} - -void LLVOVolume::removeMediaImpl(S32 texture_index) -{ - if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) - { - return ; - } - - //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. - if(mDrawable && texture_index < mDrawable->getNumFaces()) - { - LLFace* facep = mDrawable->getFace(texture_index) ; - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->removeMediaFromFace(facep) ; - } - } - } - - //check if some other face(s) of this object reference(s)to this media impl. - S32 i ; - S32 end = (S32)mMediaImplList.size() ; - for(i = 0; i < end ; i++) - { - if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) - { - break ; - } - } - - if(i == end) //this object does not need this media impl. - { - mMediaImplList[texture_index]->removeObject(this) ; - } - - mMediaImplList[texture_index] = NULL ; - return ; -} - -void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) -{ - if((S32)mMediaImplList.size() < texture_index + 1) - { - mMediaImplList.resize(texture_index + 1) ; - } - - if(mMediaImplList[texture_index].notNull()) - { - if(mMediaImplList[texture_index] == media_impl) - { - return ; - } - - removeMediaImpl(texture_index) ; - } - - mMediaImplList[texture_index] = media_impl; - media_impl->addObject(this) ; - - //add the face to show the media if it is in playing - if(mDrawable) - { - LLFace* facep = mDrawable->getFace(texture_index) ; - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - else //the face is not available now, start media on this face later. - { - media_impl->setUpdated(TRUE) ; - } - } - return ; -} - -viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const -{ - if(mMediaImplList.size() > face_id) - { - return mMediaImplList[face_id]; - } - return NULL; -} - -F64 LLVOVolume::getTotalMediaInterest() const -{ - // If this object is currently focused, this object has "high" interest - if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) - return F64_MAX; - - F64 interest = (F64)-1.0; // means not interested; - - // If this object is selected, this object has "high" interest, but since - // there can be more than one, we still add in calculated impl interest - // XXX Sadly, 'contains()' doesn't take a const :( - if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this))) - interest = F64_MAX / 2.0; - - int i = 0; - const int end = getNumTEs(); - for ( ; i < end; ++i) - { - const viewer_media_t &impl = getMediaImpl(i); - if (!impl.isNull()) - { - if (interest == (F64)-1.0) interest = (F64)0.0; - interest += impl->getInterest(); - } - } - return interest; -} - -S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) -{ - S32 end = (S32)mMediaImplList.size() ; - for(S32 face_id = start_face_id + 1; face_id < end; face_id++) - { - if(mMediaImplList[face_id] == media_impl) - { - return face_id ; - } - } - return -1 ; -} - -//---------------------------------------------------------------------------- - -void LLVOVolume::setLightTextureID(LLUUID id) -{ - if (id.notNull()) - { - if (!hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); - } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getLightTexture() != id) - { - param_block->setLightTexture(id); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } - } - else - { - if (hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - mLightTexture = NULL; - } - } -} - -void LLVOVolume::setSpotLightParams(LLVector3 params) -{ - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getParams() != params) - { - param_block->setParams(params); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } -} - -void LLVOVolume::setIsLight(BOOL is_light) -{ - if (is_light != getIsLight()) - { - if (is_light) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); - } - else - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); - } - - if (is_light) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - else - { - // Not a light. Remove it from the pipeline's light set. - gPipeline.setLight(mDrawable, FALSE); - } - } -} - -void LLVOVolume::setLightColor(const LLColor3& color) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor() != color) - { - param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - } -} - -void LLVOVolume::setLightIntensity(F32 intensity) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor().mV[3] != intensity) - { - param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } -} - -void LLVOVolume::setLightRadius(F32 radius) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getRadius() != radius) - { - param_block->setRadius(radius); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } -} - -void LLVOVolume::setLightFalloff(F32 falloff) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getFalloff() != falloff) - { - param_block->setFalloff(falloff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } -} - -void LLVOVolume::setLightCutoff(F32 cutoff) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getCutoff() != cutoff) - { - param_block->setCutoff(cutoff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } -} - -//---------------------------------------------------------------------------- - -BOOL LLVOVolume::getIsLight() const -{ - return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); -} - -LLColor3 LLVOVolume::getLightBaseColor() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()); - } - else - { - return LLColor3(1,1,1); - } -} - -LLColor3 LLVOVolume::getLightColor() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; - } - else - { - return LLColor3(1,1,1); - } -} - -LLUUID LLVOVolume::getLightTextureID() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } - } - - return LLUUID::null; -} - - -LLVector3 LLVOVolume::getSpotLightParams() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } - } - - return LLVector3(); -} - -F32 LLVOVolume::getSpotLightPriority() const -{ - return mSpotLightPriority; -} - -void LLVOVolume::updateSpotLightPriority() -{ - LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); - - F32 r = getLightRadius()*0.5f; - - pos += at * r; - - at = LLViewerCamera::getInstance()->getAtAxis(); - - pos -= at * r; - - mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - - if (mLightTexture.notNull()) - { - mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS); - } -} - - -bool LLVOVolume::isLightSpotlight() const -{ - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params) - { - return params->isLightSpotlight(); - } - return false; -} - - -LLViewerTexture* LLVOVolume::getLightTexture() -{ - LLUUID id = getLightTextureID(); - - if (id.notNull()) - { - if (mLightTexture.isNull() || id != mLightTexture->getID()) - { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id); - } - } - else - { - mLightTexture = NULL; - } - - return mLightTexture; -} - -F32 LLVOVolume::getLightIntensity() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getColor().mV[3]; - } - else - { - return 1.f; - } -} - -F32 LLVOVolume::getLightRadius() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getRadius(); - } - else - { - return 0.f; - } -} - -F32 LLVOVolume::getLightFalloff() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getFalloff(); - } - else - { - return 0.f; - } -} - -F32 LLVOVolume::getLightCutoff() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getCutoff(); - } - else - { - return 0.f; - } -} - -U32 LLVOVolume::getVolumeInterfaceID() const -{ - if (mVolumeImpl) - { - return mVolumeImpl->getID(); - } - - return 0; -} - -BOOL LLVOVolume::isFlexible() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) - { - LLVolume* volume = getVolume(); - if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) - { - LLVolumeParams volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - } - return TRUE; - } - else - { - return FALSE; - } -} - -BOOL LLVOVolume::isSculpted() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - return TRUE; - } - - return FALSE; -} - -BOOL LLVOVolume::isMesh() const -{ - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - U8 sculpt_type = sculpt_params->getSculptType(); - - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - return TRUE; - } - } - - return FALSE; -} - -BOOL LLVOVolume::hasLightTexture() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return TRUE; - } - - return FALSE; -} - -BOOL LLVOVolume::isVolumeGlobal() const -{ - if (mVolumeImpl) - { - return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; - } - else if (mRiggedVolume.notNull()) - { - return TRUE; - } - - return FALSE; -} - -BOOL LLVOVolume::canBeFlexible() const -{ - U8 path = getVolume()->getParams().getPathParams().getCurveType(); - return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); -} - -BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) -{ - BOOL res = FALSE; - BOOL was_flexible = isFlexible(); - LLVolumeParams volume_params; - if (is_flexible) - { - if (!was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - res = TRUE; - setFlags(FLAGS_USE_PHYSICS, FALSE); - setFlags(FLAGS_PHANTOM, TRUE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); - if (mDrawable) - { - mDrawable->makeActive(); - } - } - } - else - { - if (was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); - res = TRUE; - setFlags(FLAGS_PHANTOM, FALSE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); - } - } - if (res) - { - res = setVolume(volume_params, 1); - if (res) - { - markForUpdate(TRUE); - } - } - return res; -} - -//---------------------------------------------------------------------------- - -void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) -{ - LLVolume *volume = getVolume(); - - if (volume) - { - LLVector3 view_vector; - view_vector = view_point; - - //transform view vector into volume space - view_vector -= getRenderPosition(); - mDrawable->mDistanceWRTCamera = view_vector.length(); - LLQuaternion worldRot = getRenderRotation(); - view_vector = view_vector * ~worldRot; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - view_vector.scaleVec(invObjScale); - } - - updateRelativeXform(); - LLMatrix4 trans_mat = mRelativeXform; - if (mDrawable->isStatic()) - { - trans_mat.translate(getRegion()->getOriginAgent()); - } - - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); - - nodep->mSilhouetteExists = TRUE; - } -} - -void LLVOVolume::deleteFaces() -{ - S32 face_count = mNumFaces; - if (mDrawable.notNull()) - { - mDrawable->deleteFaces(0, face_count); - } - - mNumFaces = 0; -} - -void LLVOVolume::updateRadius() -{ - if (mDrawable.isNull()) - { - return; - } - - mVObjRadius = getScale().length(); - mDrawable->setRadius(mVObjRadius); -} - - -BOOL LLVOVolume::isAttachment() const -{ - return mState != 0 ; -} - -BOOL LLVOVolume::isHUDAttachment() const -{ - // *NOTE: we assume hud attachment points are in defined range - // since this range is constant for backwards compatibility - // reasons this is probably a reasonable assumption to make - S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mState); - return ( attachment_id >= 31 && attachment_id <= 38 ); -} - - -const LLMatrix4 LLVOVolume::getRenderMatrix() const -{ - if (mDrawable->isActive() && !mDrawable->isRoot()) - { - return mDrawable->getParent()->getWorldMatrix(); - } - return mDrawable->getWorldMatrix(); -} - -// Returns a base cost and adds textures to passed in set. -// total cost is returned value + 5 * size of the resulting set. -// Cannot include cost of textures, as they may be re-used in linked -// children, and cost should only be increased for unique textures -Nyx -U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const -{ - // base cost of each prim should be 10 points - static const U32 ARC_PRIM_COST = 10; - // per-prim costs - static const U32 ARC_INVISI_COST = 1; - static const U32 ARC_SHINY_COST = 1; - static const U32 ARC_GLOW_COST = 1; - static const U32 ARC_FLEXI_COST = 8; - static const U32 ARC_PARTICLE_COST = 16; - static const U32 ARC_BUMP_COST = 4; - - // per-face costs - static const U32 ARC_PLANAR_COST = 1; - static const U32 ARC_ANIM_TEX_COST = 4; - static const U32 ARC_ALPHA_COST = 4; - - U32 shame = ARC_PRIM_COST; - - U32 invisi = 0; - U32 shiny = 0; - U32 glow = 0; - U32 alpha = 0; - U32 flexi = 0; - U32 animtex = 0; - U32 particles = 0; - U32 scale = 0; - U32 bump = 0; - U32 planar = 0; - - if (isFlexible()) - { - flexi = 1; - } - if (isParticleSource()) - { - particles = 1; - } - - const LLVector3& sc = getScale(); - scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2]; - - const LLDrawable* drawablep = mDrawable; - - if (isSculpted()) - { - const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - textures.insert(sculpt_id); - } - - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - const LLFace* face = drawablep->getFace(i); - const LLTextureEntry* te = face->getTextureEntry(); - const LLViewerTexture* img = face->getTexture(); - - if (img) - { - textures.insert(img->getID()); - } - - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - alpha++; - } - else if (img && img->getPrimaryFormat() == GL_ALPHA) - { - invisi = 1; - } - - if (te) - { - if (te->getBumpmap()) - { - bump = 1; - } - if (te->getShiny()) - { - shiny = 1; - } - if (te->getGlow() > 0.f) - { - glow = 1; - } - if (face->mTextureMatrix != NULL) - { - animtex++; - } - if (te->getTexGen()) - { - planar++; - } - } - } - - - shame += invisi * ARC_INVISI_COST; - shame += shiny * ARC_SHINY_COST; - shame += glow * ARC_GLOW_COST; - shame += alpha * ARC_ALPHA_COST; - shame += flexi * ARC_FLEXI_COST; - shame += animtex * ARC_ANIM_TEX_COST; - shame += particles * ARC_PARTICLE_COST; - shame += bump * ARC_BUMP_COST; - shame += planar * ARC_PLANAR_COST; - shame += scale; - - LLViewerObject::const_child_list_t& child_list = getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); - ++iter) - { - const LLViewerObject* child_objectp = *iter; - const LLDrawable* child_drawablep = child_objectp->mDrawable; - if (child_drawablep) - { - const LLVOVolume* child_volumep = child_drawablep->getVOVolume(); - if (child_volumep) - { - shame += child_volumep->getRenderCost(textures); - } - } - } - - return shame; - -} - -F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes) -{ - if (isMesh()) - { - LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); - - F32 radius = getScale().length(); - - return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD); - } - - return 0.f; -} - -U32 LLVOVolume::getTriangleCount() -{ - U32 count = 0; - LLVolume* volume = getVolume(); - if (volume) - { - count = volume->getNumTriangles(); - } - - return count; -} - -U32 LLVOVolume::getHighLODTriangleCount() -{ - U32 ret = 0; - - LLVolume* volume = getVolume(); - - if (!isSculpted()) - { +/** + * @file llvovolume.cpp + * @brief LLVOVolume class implementation + * + * $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$ + */ + +// A "volume" is a box, cylinder, sphere, or other primitive shape. + +#include "llviewerprecompiledheaders.h" + +#include "llvovolume.h" + +#include <sstream> + +#include "llviewercontrol.h" +#include "lldir.h" +#include "llflexibleobject.h" +#include "llfloatertools.h" +#include "llmaterialtable.h" +#include "llprimitive.h" +#include "llvolume.h" +#include "llvolumeoctree.h" +#include "llvolumemgr.h" +#include "llvolumemessage.h" +#include "material_codes.h" +#include "message.h" +#include "llpluginclassmedia.h" // for code in the mediaEvent handler +#include "object_flags.h" +#include "llagentconstants.h" +#include "lldrawable.h" +#include "lldrawpoolavatar.h" +#include "lldrawpoolbump.h" +#include "llface.h" +#include "llspatialpartition.h" +#include "llhudmanager.h" +#include "llflexibleobject.h" +#include "llsky.h" +#include "lltexturefetch.h" +#include "llvector4a.h" +#include "llviewercamera.h" +#include "llviewertexturelist.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewertextureanim.h" +#include "llworld.h" +#include "llselectmgr.h" +#include "pipeline.h" +#include "llsdutil.h" +#include "llmatrix4a.h" +#include "llmediaentry.h" +#include "llmediadataclient.h" +#include "llmeshrepository.h" +#include "llagent.h" +#include "llviewermediafocus.h" +#include "llvoavatar.h" + +const S32 MIN_QUIET_FRAMES_COALESCE = 30; +const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; +const F32 FORCE_CULL_AREA = 8.f; +const F32 MAX_LOD_DISTANCE = 24.f; + + +BOOL gAnimateTextures = TRUE; +//extern BOOL gHideSelectedObjects; + +F32 LLVOVolume::sLODFactor = 1.f; +F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop +F32 LLVOVolume::sDistanceFactor = 1.0f; +S32 LLVOVolume::sNumLODChanges = 0; +LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL; +LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL; + +static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); +static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); +static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); + +// Implementation class of LLMediaDataClientObject. See llmediadataclient.h +class LLMediaDataClientObjectImpl : public LLMediaDataClientObject +{ +public: + LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) + { + mObject->addMDCImpl(); + } + ~LLMediaDataClientObjectImpl() + { + mObject->removeMDCImpl(); + } + + virtual U8 getMediaDataCount() const + { return mObject->getNumTEs(); } + + virtual LLSD getMediaDataLLSD(U8 index) const + { + LLSD result; + LLTextureEntry *te = mObject->getTE(index); + if (NULL != te) + { + llassert((te->getMediaData() != NULL) == te->hasMedia()); + if (te->getMediaData() != NULL) + { + result = te->getMediaData()->asLLSD(); + // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly + // See DEV-41949 + if (!result.has(LLMediaEntry::WHITELIST_KEY)) + { + result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); + } + } + } + return result; + } + virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const + { + LLTextureEntry *te = mObject->getTE(index); + if (te) + { + if (te->getMediaData()) + { + return (te->getMediaData()->getCurrentURL() == url); + } + } + return url.empty(); + } + + virtual LLUUID getID() const + { return mObject->getID(); } + + virtual void mediaNavigateBounceBack(U8 index) + { mObject->mediaNavigateBounceBack(index); } + + virtual bool hasMedia() const + { return mObject->hasMedia(); } + + virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) + { mObject->updateObjectMediaData(data, version_string); } + + virtual F64 getMediaInterest() const + { + F64 interest = mObject->getTotalMediaInterest(); + if (interest < (F64)0.0) + { + // media interest not valid yet, try pixel area + interest = mObject->getPixelArea(); + // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. + if (interest == 1024.f) + { + const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent); + interest = mObject->getPixelArea(); + } + } + return interest; + } + + virtual bool isInterestingEnough() const + { + return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); + } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mObject->getRegion()->getCapability(name); } + + virtual bool isDead() const + { return mObject->isDead(); } + + virtual U32 getMediaVersion() const + { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } + + virtual bool isNew() const + { return mNew; } + +private: + LLPointer<LLVOVolume> mObject; + bool mNew; +}; + + +LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) + : LLViewerObject(id, pcode, regionp), + mVolumeImpl(NULL) +{ + mTexAnimMode = 0; + mRelativeXform.setIdentity(); + mRelativeXformInvTrans.setIdentity(); + + mFaceMappingChanged = FALSE; + mLOD = MIN_LOD; + mTextureAnimp = NULL; + mVolumeChanged = FALSE; + mVObjRadius = LLVector3(1,1,0.5f).length(); + mNumFaces = 0; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mSpotLightPriority = 0.f; + + mMediaImplList.resize(getNumTEs()); + mLastFetchedMediaVersion = -1; + mIndexInTex = 0; + mMDCImplCount = 0; +} + +LLVOVolume::~LLVOVolume() +{ + delete mTextureAnimp; + mTextureAnimp = NULL; + delete mVolumeImpl; + mVolumeImpl = NULL; + + if(!mMediaImplList.empty()) + { + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + if(mMediaImplList[i].notNull()) + { + mMediaImplList[i]->removeObject(this) ; + } + } + } +} + +void LLVOVolume::markDead() +{ + if (!mDead) + { + if(getMDCImplCount() > 0) + { + LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); + if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); + if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); + } + + // Detach all media impls from this object + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + removeMediaImpl(i); + } + + if (mSculptTexture.notNull()) + { + mSculptTexture->removeVolume(this); + } + } + + LLViewerObject::markDead(); +} + + +// static +void LLVOVolume::initClass() +{ + // gSavedSettings better be around + if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) + { + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); + const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, + max_sorted_queue_size, max_round_robin_queue_size); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, + max_retries, max_sorted_queue_size, max_round_robin_queue_size); + } +} + +// static +void LLVOVolume::cleanupClass() +{ + sObjectMediaClient = NULL; + sObjectMediaNavigateClient = NULL; +} + +U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, EObjectUpdateType update_type, + LLDataPacker *dp) +{ + LLColor4U color; + const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); + + // Do base class updates... + U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + + LLUUID sculpt_id; + U8 sculpt_type = 0; + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + sculpt_id = sculpt_params->getSculptTexture(); + sculpt_type = sculpt_params->getSculptType(); + } + + if (!dp) + { + if (update_type == OUT_FULL) + { + //////////////////////////////// + // + // Unpack texture animation data + // + // + + if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(mesgsys, block_num); + } + else + { + if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + + // Unpack volume data + LLVolumeParams volume_params; + LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + } + + // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... + //////////////////////////// + // + // Unpack texture entry data + // + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + else + { + // CORY TO DO: Figure out how to get the value here + if (update_type != OUT_TERSE_IMPROVED) + { + LLVolumeParams volume_params; + BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); + if (!res) + { + llwarns << "Bogus volume parameters in object " << getID() << llendl; + llwarns << getRegion()->getOriginGlobal() << llendl; + } + + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + S32 res2 = unpackTEMessage(*dp); + if (TEM_INVALID == res2) + { + // There's something bogus in the data that we're unpacking. + dp->dumpBufferToLog(); + llwarns << "Flushing cache files" << llendl; + + if(LLVOCache::hasInstance() && getRegion()) + { + LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; + } + + llwarns << "Bogus TE data in " << getID() << llendl; + } + else + { + if (res2 & teDirtyBits) + { + updateTEData(); + } + if (res2 & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + + U32 value = dp->getPassFlags(); + + if (value & 0x40) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(*dp); + } + else if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + else + { + S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); + if (texture_length) + { + U8 tdpbuffer[1024]; + LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num); + S32 result = unpackTEMessage(tdp); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + } + } + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) + { + // If only the media URL changed, and it isn't a media version URL, + // ignore it + if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && + mMedia && ! mMedia->mMediaURL.empty() && + ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) + { + // If the media changed at all, request new media data + LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << + ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; + requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); + } + else { + LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << + ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; + } + } + // ...and clean up any media impls + cleanUpMediaImpls(); + + return retval; +} + + +void LLVOVolume::animateTextures() +{ + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); + + if (result) + { + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; + + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } + + for (S32 i = start; i <= end; i++) + { + LLFace* facep = mDrawable->getFace(i); + if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; + + const LLTextureEntry* te = facep->getTextureEntry(); + + if (!te) + { + continue; + } + + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); + } + + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } + + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + LLVector3 trans ; + + if(facep->isAtlasInUse()) + { + // + //if use atlas for animated texture + //apply the following transform to the animation matrix. + // + + F32 tcoord_xoffset = 0.f ; + F32 tcoord_yoffset = 0.f ; + F32 tcoord_xscale = 1.f ; + F32 tcoord_yscale = 1.f ; + if(facep->isAtlasInUse()) + { + const LLVector2* tmp = facep->getTexCoordOffset() ; + tcoord_xoffset = tmp->mV[0] ; + tcoord_yoffset = tmp->mV[1] ; + + tmp = facep->getTexCoordScale() ; + tcoord_xscale = tmp->mV[0] ; + tcoord_yscale = tmp->mV[1] ; + } + trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); + + tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); + } + else //non atlas + { + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + } + + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + + tex_mat.rotate(quat); + + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + tex_mat.translate(trans); + } + } + else + { + if (mTexAnimMode && mTextureAnimp->mRate == 0) + { + U8 start, count; + + if (mTextureAnimp->mFace == -1) + { + start = 0; + count = getNumTEs(); + } + else + { + start = (U8) mTextureAnimp->mFace; + count = 1; + } + + for (S32 i = start; i < start + count; i++) + { + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + { + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + } + if (mTexAnimMode & LLViewerTextureAnim::SCALE) + { + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + } + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + { + setTERotation(i, mTextureAnimp->mRot); + } + } + + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } +} +BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + LLViewerObject::idleUpdate(agent, world, time); + + static LLFastTimer::DeclareTimer ftm("Volume"); + LLFastTimer t(ftm); + + if (mDead || mDrawable.isNull()) + { + return TRUE; + } + + /////////////////////// + // + // Do texture animation stuff + // + + if (mTextureAnimp && gAnimateTextures) + { + animateTextures(); + } + + // Dispatch to implementation + if (mVolumeImpl) + { + mVolumeImpl->doIdleUpdate(agent, world, time); + } + + const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; + + if (mDrawable->isActive()) + { + if (mDrawable->isRoot() && + mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && + (!mDrawable->getParent() || !mDrawable->getParent()->isActive())) + { + mDrawable->makeStatic(); + } + } + + return TRUE; +} + +void LLVOVolume::updateTextures() +{ + const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + { + updateTextureVirtualSize(); + } +} + +BOOL LLVOVolume::isVisible() const +{ + if(mDrawable.notNull() && mDrawable->isVisible()) + { + return TRUE ; + } + + if(isAttachment()) + { + LLViewerObject* objp = (LLViewerObject*)getParent() ; + while(objp && !objp->isAvatar()) + { + objp = (LLViewerObject*)objp->getParent() ; + } + + return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; + } + + return FALSE ; +} + +void LLVOVolume::updateTextureVirtualSize() +{ + LLFastTimer ftm(FTM_VOLUME_TEXTURES); + // Update the pixel area of all faces + + if(!isVisible()) + { + return ; + } + + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } + + static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); + + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) + { + return; + } + + mTextureUpdateTimer.reset(); + + F32 old_area = mPixelArea; + mPixelArea = 0.f; + + const S32 num_faces = mDrawable->getNumFaces(); + F32 min_vsize=999999999.f, max_vsize=0.f; + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + const LLTextureEntry *te = face->getTextureEntry(); + LLViewerTexture *imagep = face->getTexture(); + if (!imagep || !te || + face->mExtents[0].equals3(face->mExtents[1])) + { + continue; + } + + F32 vsize; + F32 old_size = face->getVirtualSize(); + + if (isHUDAttachment()) + { + F32 area = (F32) camera->getScreenPixelArea(); + vsize = area; + imagep->setBoostLevel(LLViewerTexture::BOOST_HUD); + face->setPixelArea(area); // treat as full screen + face->setVirtualSize(vsize); + } + else + { + vsize = face->getTextureVirtualSize(); + } + + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + + if (face->mTextureMatrix != NULL) + { + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + if (vsize < min_vsize) min_vsize = vsize; + if (vsize > max_vsize) max_vsize = vsize; + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; + if(img) + { + F32 pri = img->getDecodePriority(); + pri = llmax(pri, 0.0f); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + F32 pri = mPixelArea; + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + + updateSculptTexture(); + + + + if (mSculptTexture.notNull()) + { + mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), + (S32)LLViewerTexture::BOOST_SCULPTED)); + mSculptTexture->setForSculpt() ; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + + //if the sculpty very close to the view point, load first + { + LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; + mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; + } + } + + S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture + S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; + + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + { + setDebugText(llformat("T%d C%d V%d\n%dx%d", + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); + } + } + + } + + if (getLightTextureID().notNull()) + { + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *camera)); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + + if (mPixelArea == 0) + { //flexi phasing issues make this happen + mPixelArea = old_area; + } +} + +BOOL LLVOVolume::isActive() const +{ + return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) || + (mDrawable.notNull() && mDrawable->isActive()); +} + +BOOL LLVOVolume::setMaterial(const U8 material) +{ + BOOL res = LLViewerObject::setMaterial(material); + + return res; +} + +void LLVOVolume::setTexture(const S32 face) +{ + llassert(face < getNumTEs()); + gGL.getTexUnit(0)->bind(getTEImage(face)); +} + +void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) +{ + if (scale != getScale()) + { + // store local radius + LLViewerObject::setScale(scale); + + if (mVolumeImpl) + { + mVolumeImpl->onSetScale(scale, damped); + } + + updateRadius(); + + //since drawable transforms do not include scale, changing volume scale + //requires an immediate rebuild of volume verts. + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); + } +} + +LLFace* LLVOVolume::addFace(S32 f) +{ + const LLTextureEntry* te = getTE(f); + LLViewerTexture* imagep = getTEImage(f); + return mDrawable->addFace(te, imagep); +} + +LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) +{ + pipeline->allocDrawable(this); + + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); + + S32 max_tes_to_set = getNumTEs(); + for (S32 i = 0; i < max_tes_to_set; i++) + { + addFace(i); + } + mNumFaces = max_tes_to_set; + + if (isAttachment()) + { + mDrawable->makeActive(); + } + + if (getIsLight()) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + + updateRadius(); + bool force_update = true; // avoid non-alpha mDistance update being optimized away + mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); + + return mDrawable; +} + +BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) +{ + LLVolumeParams volume_params = params_in; + + S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; + S32 lod = mLOD; + + BOOL is404 = FALSE; + + if (isSculpted()) + { + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + + LLUUID mesh_id = volume_params.getSculptID(); + + //profile and path params don't matter for meshes + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } + } + } + + // Check if we need to change implementations + bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); + if (is_flexible) + { + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); + if (!mVolumeImpl) + { + LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + mVolumeImpl = new LLVolumeImplFlexible(this, data); + } + } + else + { + // Mark the parameter not in use + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); + if (mVolumeImpl) + { + delete mVolumeImpl; + mVolumeImpl = NULL; + if (mDrawable.notNull()) + { + // Undo the damage we did to this matrix + mDrawable->updateXform(FALSE); + } + } + } + + if (is404) + { + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); + } + + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) + { + mFaceMappingChanged = TRUE; + + if (mVolumeImpl) + { + mVolumeImpl->onSetVolume(volume_params, mLOD); + } + + updateSculptTexture(); + + + if (isSculpted()) + { + updateSculptTexture(); + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + if (getVolume()->getNumVolumeFaces() == 0 || getVolume()->isTetrahedron()) + { + //load request not yet issued, request pipeline load this mesh + LLUUID asset_id = volume_params.getSculptID(); + S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); + if (available_lod != lod) + { + LLPrimitive::setVolume(volume_params, available_lod); + } + } + + } + else // otherwise is sculptie + { + if (mSculptTexture.notNull()) + { + sculpt(); + } + } + } + + return TRUE; + } + + return FALSE; +} + +void LLVOVolume::updateSculptTexture() +{ + LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture; + + if (isSculpted() && !isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + } + else + { + mSculptTexture = NULL; + } + + if (mSculptTexture != old_sculpt) + { + if (old_sculpt.notNull()) + { + old_sculpt->removeVolume(this); + } + if (mSculptTexture.notNull()) + { + mSculptTexture->addVolume(this); + } + } + +} + + + +void LLVOVolume::notifyMeshLoaded() +{ + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); +} + +// sculpt replaces generate() for sculpted surfaces +void LLVOVolume::sculpt() +{ + if (mSculptTexture.notNull()) + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getDiscardLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; + + S32 max_discard = mSculptTexture->getMaxDiscardLevel(); + if (discard_level > max_discard) + discard_level = max_discard; // clamp to the best we can do + + S32 current_discard = getVolume()->getSculptLevel() ; + if(current_discard < -2) + { + llwarns << "WARNING!!: Current discard of sculpty at " << current_discard + << " is less than -2." << llendl; + + // corrupted volume... don't update the sculpty + return; + } + else if (current_discard > MAX_DISCARD_LEVEL) + { + llwarns << "WARNING!!: Current discard of sculpty at " << current_discard + << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; + + // corrupted volume... don't update the sculpty + return; + } + + if (current_discard == discard_level) // no work to do here + return; + + if(!raw_image) + { + llassert(discard_level < 0) ; + + sculpt_width = 0; + sculpt_height = 0; + sculpt_data = NULL ; + + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); + } + } + else + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); + + sculpt_data = raw_image->getData(); + + if(LLViewerTextureManager::sTesterp) + { + mSculptTexture->updateBindStatsForTester() ; + } + } + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); + + //notify rebuild any other VOVolumes that reference this sculpty volume + for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) + { + LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i]; + if (volume != this && volume->getVolume() == getVolume()) + { + gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); + } + } + } +} + +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) +{ + S32 cur_detail; + if (LLPipeline::sDynamicLOD) + { + // We've got LOD in the profile, and in the twist. Use radius. + F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; + cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f)); + } + else + { + cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3); + } + return cur_detail; +} + +BOOL LLVOVolume::calcLOD() +{ + if (mDrawable.isNull()) + { + return FALSE; + } + + S32 cur_detail = 0; + + F32 radius; + F32 distance; + + if (mDrawable->isState(LLDrawable::RIGGED)) + { + LLVOAvatar* avatar = getAvatar(); + distance = avatar->mDrawable->mDistanceWRTCamera; + radius = avatar->getBinRadius(); + } + else + { + distance = mDrawable->mDistanceWRTCamera; + radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); + } + + //hold onto unmodified distance for debugging + F32 debug_distance = distance; + + distance *= sDistanceFactor; + + F32 rampDist = LLVOVolume::sLODFactor * 2; + + if (distance < rampDist) + { + // Boost LOD when you're REALLY close + distance *= 1.0f/rampDist; + distance *= distance; + distance *= rampDist; + } + + // DON'T Compensate for field of view changing on FOV zoom. + distance *= F_PI/3.f; + + cur_detail = computeLODDetail(llround(distance, 0.01f), + llround(radius, 0.01f)); + + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) + { + setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); + } + + if (cur_detail != mLOD) + { + mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); + mLOD = cur_detail; + return TRUE; + } + else + { + return FALSE; + } +} + +BOOL LLVOVolume::updateLOD() +{ + if (mDrawable.isNull()) + { + return FALSE; + } + + BOOL lod_changed = calcLOD(); + + if (lod_changed) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mLODChanged = TRUE; + } + + lod_changed = lod_changed || LLViewerObject::updateLOD(); + + return lod_changed; +} + +BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) +{ + if (!LLViewerObject::setDrawableParent(parentp)) + { + // no change in drawable parent + return FALSE; + } + + if (!mDrawable->isRoot()) + { + // rebuild vertices in parent relative space + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + + if (mDrawable->isActive() && !parentp->isActive()) + { + parentp->makeActive(); + } + else if (mDrawable->isStatic() && parentp->isActive()) + { + mDrawable->makeActive(); + } + } + + return TRUE; +} + +void LLVOVolume::updateFaceFlags() +{ + for (S32 i = 0; i < getVolume()->getNumFaces(); i++) + { + LLFace *face = mDrawable->getFace(i); + if (!face) + { + return; + } + + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); + + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } + } +} + +BOOL LLVOVolume::setParent(LLViewerObject* parent) +{ + BOOL ret = FALSE ; + if (parent != getParent()) + { + ret = LLViewerObject::setParent(parent); + if (ret && mDrawable) + { + gPipeline.markMoved(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + } + } + + return ret ; +} + +// NOTE: regenFaces() MUST be followed by genTriangles()! +void LLVOVolume::regenFaces() +{ + // remove existing faces + BOOL count_changed = mNumFaces != getNumTEs(); + + if (count_changed) + { + deleteFaces(); + // add new faces + mNumFaces = getNumTEs(); + } + + for (S32 i = 0; i < mNumFaces; i++) + { + LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + facep->setTEOffset(i); + facep->setTexture(getTEImage(i)); + facep->setViewerObject(this); + + // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. + // Re-establish the link. + if((int)mMediaImplList.size() > i) + { + if(mMediaImplList[i]) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + } + } + + if (!count_changed) + { + updateFaceFlags(); + } +} + +BOOL LLVOVolume::genBBoxes(BOOL force_global) +{ + BOOL res = TRUE; + + LLVector4a min,max; + + min.clear(); + max.clear(); + + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + +// bool rigged = false; + LLVolume* volume = mRiggedVolume; + if (!volume) + { + volume = getVolume(); + } + + for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++) + { + LLFace *face = mDrawable->getFace(i); + if (!face) + { + continue; + } + res &= face->genVolumeBBoxes(*volume, i, + mRelativeXform, mRelativeXformInvTrans, + (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); + + if (rebuild) + { + if (i == 0) + { + min = face->mExtents[0]; + max = face->mExtents[1]; + } + else + { + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); + } + } + } + + if (rebuild) + { + mDrawable->setSpatialExtents(min,max); + min.add(max); + min.mul(0.5f); + mDrawable->setPositionGroup(min); + } + + updateRadius(); + mDrawable->movePartition(); + + return res; +} + +void LLVOVolume::preRebuild() +{ + if (mVolumeImpl != NULL) + { + mVolumeImpl->preRebuild(); + } +} + +void LLVOVolume::updateRelativeXform() +{ + if (mVolumeImpl) + { + mVolumeImpl->updateRelativeXform(); + return; + } + + LLDrawable* drawable = mDrawable; + + if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) + { //rigged volume (which is in agent space) is used for generating bounding boxes etc + //inverse of render matrix should go to partition space + mRelativeXform = getRenderMatrix(); + + F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; + F32* src = (F32*) mRelativeXform.mMatrix; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; + dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; + + mRelativeXform.invert(); + mRelativeXformInvTrans.transpose(); + } + else if (drawable->isActive()) + { + // setup relative transforms + LLQuaternion delta_rot; + LLVector3 delta_pos, delta_scale; + + //matrix from local space to parent relative/global space + delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); + delta_scale = mDrawable->getScale(); + + // Vertex transform (4x4) + LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; + LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(delta_pos, 1.f)); + + + // compute inverse transpose for normals + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // mRelativeXformInvTrans.invert(); + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // grumble - invert is NOT a matrix invert, so we do it by hand: + + LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } + else + { + LLVector3 pos = getPosition(); + LLVector3 scale = getScale(); + LLQuaternion rot = getRotation(); + + if (mParent) + { + pos *= mParent->getRotation(); + pos += mParent->getPosition(); + rot *= mParent->getRotation(); + } + + //LLViewerRegion* region = getRegion(); + //pos += region->getOriginAgent(); + + LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; + LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(pos, 1.f)); + + // compute inverse transpose for normals + LLMatrix3 rot_inverse = LLMatrix3(~rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } +} + +static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies"); +static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); +static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); + +BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) +{ + LLFastTimer t(FTM_UPDATE_PRIMITIVES); + + if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) + { + { + LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME); + updateRiggedVolume(); + } + genBBoxes(FALSE); + mDrawable->clearState(LLDrawable::REBUILD_RIGGED); + } + + if (mVolumeImpl != NULL) + { + BOOL res; + { + LLFastTimer t(FTM_GEN_FLEX); + res = mVolumeImpl->doUpdateGeometry(drawable); + } + updateFaceFlags(); + return res; + } + + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + + BOOL compiled = FALSE; + + updateRelativeXform(); + + if (mDrawable.isNull()) // Not sure why this is happening, but it is... + { + return TRUE; // No update to complete + } + + if (mVolumeChanged || mFaceMappingChanged ) + { + compiled = TRUE; + + if (mVolumeChanged) + { + LLFastTimer ftm(FTM_GEN_VOLUME); + LLVolumeParams volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + drawable->setState(LLDrawable::REBUILD_VOLUME); + } + + { + LLFastTimer t(FTM_GEN_TRIANGLES); + regenFaces(); + genBBoxes(FALSE); + } + } + else if ((mLODChanged) || (mSculptChanged)) + { + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces ; + + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces() ; + old_volumep = NULL ; + + { + LLFastTimer ftm(FTM_GEN_VOLUME); + LLVolumeParams volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } + + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces() ; + new_volumep = NULL ; + + if ((new_lod != old_lod) || mSculptChanged) + { + compiled = TRUE; + sNumLODChanges += new_num_faces ; + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + LLFastTimer t(FTM_GEN_TRIANGLES); + if (new_num_faces != old_num_faces) + { + regenFaces(); + } + genBBoxes(FALSE); + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + } + // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local + else + { + compiled = TRUE; + // All it did was move or we changed the texture coordinate offset + LLFastTimer t(FTM_GEN_TRIANGLES); + genBBoxes(FALSE); + } + + // Update face flags + updateFaceFlags(); + + if(compiled) + { + LLPipeline::sCompiles++; + } + + mVolumeChanged = FALSE; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mFaceMappingChanged = FALSE; + + return LLViewerObject::updateGeometry(drawable); +} + +void LLVOVolume::updateFaceSize(S32 idx) +{ + LLFace* facep = mDrawable->getFace(idx); + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + + } +} + +BOOL LLVOVolume::isRootEdit() const +{ + if (mParent && !((LLViewerObject*)mParent)->isAvatar()) + { + return FALSE; + } + return TRUE; +} + +//virtual +void LLVOVolume::setNumTEs(const U8 num_tes) +{ + const U8 old_num_tes = getNumTEs() ; + + if(old_num_tes && old_num_tes < num_tes) //new faces added + { + LLViewerObject::setNumTEs(num_tes) ; + + if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. + { + mMediaImplList.resize(num_tes) ; + const LLTextureEntry* te = getTE(old_num_tes - 1) ; + for(U8 i = old_num_tes; i < num_tes ; i++) + { + setTE(i, *te) ; + mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; + } + mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; + } + } + else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed + { + U8 end = mMediaImplList.size() ; + for(U8 i = num_tes; i < end ; i++) + { + removeMediaImpl(i) ; + } + mMediaImplList.resize(num_tes) ; + + LLViewerObject::setNumTEs(num_tes) ; + } + else + { + LLViewerObject::setNumTEs(num_tes) ; + } + + return ; +} + +void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) +{ + BOOL changed = (mTEImages[te] != imagep); + LLViewerObject::setTEImage(te, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } +} + +S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) +{ + S32 res = LLViewerObject::setTETexture(te, uuid); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) +{ + return setTEColor(te, LLColor4(color)); +} + +S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + } + else if (color != tep->getColor()) + { + if (color.mV[3] != tep->getColor().mV[3]) + { + gPipeline.markTextured(mDrawable); + } + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + } + } + + return retval; +} + +S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) +{ + S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) +{ + S32 res = LLViewerObject::setTETexGen(te, texgen); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) +{ + S32 res = LLViewerObject::setTEMediaTexGen(te, media); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) +{ + S32 res = LLViewerObject::setTEShiny(te, shiny); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) +{ + S32 res = LLViewerObject::setTEFullbright(te, fullbright); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) +{ + S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) +{ + S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) +{ + S32 res = LLViewerObject::setTEGlow(te, glow); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) +{ + S32 res = LLViewerObject::setTEScale(te, s, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) +{ + S32 res = LLViewerObject::setTEScaleS(te, s); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) +{ + S32 res = LLViewerObject::setTEScaleT(te, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +void LLVOVolume::updateTEData() +{ + /*if (mDrawable.notNull()) + { + mFaceMappingChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); + }*/ +} + +bool LLVOVolume::hasMedia() const +{ + bool result = false; + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if(te->hasMedia()) + { + result = true; + break; + } + } + return result; +} + +LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) +{ + LLVolume* volume = getVolume(); + LLVector4a result; + result.clear(); + + LLVector3 ret; + + if (volume && face_id < volume->getNumVolumeFaces()) + { + const LLVolumeFace& face = volume->getVolumeFace(face_id); + for (S32 i = 0; i < (S32)face.mNumVertices; ++i) + { + result.add(face.mNormals[i]); + } + + LLVector3 ret(result.getF32ptr()); + ret = volumeDirectionToAgent(ret); + ret.normVec(); + } + + return ret; +} + +void LLVOVolume::requestMediaDataUpdate(bool isNew) +{ + if (sObjectMediaClient) + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); +} + +bool LLVOVolume::isMediaDataBeingFetched() const +{ + // I know what I'm doing by const_casting this away: this is just + // a wrapper class that is only going to do a lookup. + return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false; +} + +void LLVOVolume::cleanUpMediaImpls() +{ + // Iterate through our TEs and remove any Impls that are no longer used + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if( ! te->hasMedia()) + { + // Delete the media IMPL! + removeMediaImpl(i) ; + } + } +} + +void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) +{ + // media_data_array is an array of media entry maps + // media_version is the version string in the response. + U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); + + // Only update it if it is newer! + if ( (S32)fetched_version > mLastFetchedMediaVersion) + { + mLastFetchedMediaVersion = fetched_version; + //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } + } +} + +void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) +{ + if(mDead) + { + // If the object has been marked dead, don't process media updates. + return; + } + + LLTextureEntry *te = getTE(texture_index); + if(!te) + { + return ; + } + + LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; + + std::string previous_url; + LLMediaEntry* mep = te->getMediaData(); + if(mep) + { + // Save the "current url" from before the update so we can tell if + // it changes. + previous_url = mep->getCurrentURL(); + } + + if (merge) + { + te->mergeIntoMediaData(media_data); + } + else { + // XXX Question: what if the media data is undefined LLSD, but the + // update we got above said that we have media flags?? Here we clobber + // that, assuming the data from the service is more up-to-date. + te->updateMediaData(media_data); + } + + mep = te->getMediaData(); + if(mep) + { + bool update_from_self = false; + if (!ignore_agent) + { + LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); + update_from_self = (updating_agent == gAgent.getID()); + } + viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); + + addMediaImpl(media_impl, texture_index) ; + } + else + { + removeMediaImpl(texture_index); + } + + LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; +} + +void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) +{ + // Find the media entry for this navigate + const LLMediaEntry* mep = NULL; + viewer_media_t impl = getMediaImpl(texture_index); + LLTextureEntry *te = getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { + std::string url = mep->getCurrentURL(); + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + // If the url we're trying to "bounce back" to is either empty or not + // allowed by the whitelist, try the home url. If *that* doesn't work, + // set the media as failed and unload it + if (url.empty() || !mep->checkCandidateUrl(url)) + { + url = mep->getHomeURL(); + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + } + if (url.empty() || !mep->checkCandidateUrl(url)) + { + // The url to navigate back to is not good, and we have nowhere else + // to go. + LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; + impl->setMediaFailed(true); + } + else { + // Okay, navigate now + LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; + impl->navigateTo(url, "", false, true); + } + } +} + +bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) +{ + // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). + if (NULL == media_entry ) return false; // XXX should we assert here? + + // The agent has permissions if: + // - world permissions are on, or + // - group permissions are on, and agent_id is in the group, or + // - agent permissions are on, and agent_id is the owner + + // *NOTE: We *used* to check for modify permissions here (i.e. permissions were + // granted if permModify() was true). However, this doesn't make sense in the + // viewer: we don't want to show controls or allow interaction if the author + // has deemed it so. See DEV-42115. + + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); + + // World permissions + if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) + { + return true; + } + + // Group permissions + else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) + { + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); + if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) + { + return true; + } + } + + // Owner permissions + else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) + { + return true; + } + + return false; + +} + +void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) +{ + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) + { + block_navigation = true; + } + } + else + { + LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; + } + + if(block_navigation) + { + LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; + + // "bounce back" to the current URL from the media entry + mediaNavigateBounceBack(face_index); + } + else if (sObjectMediaNavigateClient) + { + + LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; + + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); + } +} + +void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) +{ + switch(event) + { + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getLocation()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: + // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // This is a subsequent location-changed due to a redirect. Don't broadcast. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; + break; + } + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getNavigateURI()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: + // This is the the navigate complete event from a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. + break; + } + } + break; + + default: + break; + } + +} + +void LLVOVolume::sendMediaDataUpdate() +{ + if (sObjectMediaClient) + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); +} + +void LLVOVolume::removeMediaImpl(S32 texture_index) +{ + if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) + { + return ; + } + + //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. + if(mDrawable && texture_index < mDrawable->getNumFaces()) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->removeMediaFromFace(facep) ; + } + } + } + + //check if some other face(s) of this object reference(s)to this media impl. + S32 i ; + S32 end = (S32)mMediaImplList.size() ; + for(i = 0; i < end ; i++) + { + if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) + { + break ; + } + } + + if(i == end) //this object does not need this media impl. + { + mMediaImplList[texture_index]->removeObject(this) ; + } + + mMediaImplList[texture_index] = NULL ; + return ; +} + +void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) +{ + if((S32)mMediaImplList.size() < texture_index + 1) + { + mMediaImplList.resize(texture_index + 1) ; + } + + if(mMediaImplList[texture_index].notNull()) + { + if(mMediaImplList[texture_index] == media_impl) + { + return ; + } + + removeMediaImpl(texture_index) ; + } + + mMediaImplList[texture_index] = media_impl; + media_impl->addObject(this) ; + + //add the face to show the media if it is in playing + if(mDrawable) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + else //the face is not available now, start media on this face later. + { + media_impl->setUpdated(TRUE) ; + } + } + return ; +} + +viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const +{ + if(mMediaImplList.size() > face_id) + { + return mMediaImplList[face_id]; + } + return NULL; +} + +F64 LLVOVolume::getTotalMediaInterest() const +{ + // If this object is currently focused, this object has "high" interest + if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) + return F64_MAX; + + F64 interest = (F64)-1.0; // means not interested; + + // If this object is selected, this object has "high" interest, but since + // there can be more than one, we still add in calculated impl interest + // XXX Sadly, 'contains()' doesn't take a const :( + if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this))) + interest = F64_MAX / 2.0; + + int i = 0; + const int end = getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = getMediaImpl(i); + if (!impl.isNull()) + { + if (interest == (F64)-1.0) interest = (F64)0.0; + interest += impl->getInterest(); + } + } + return interest; +} + +S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) +{ + S32 end = (S32)mMediaImplList.size() ; + for(S32 face_id = start_face_id + 1; face_id < end; face_id++) + { + if(mMediaImplList[face_id] == media_impl) + { + return face_id ; + } + } + return -1 ; +} + +//---------------------------------------------------------------------------- + +void LLVOVolume::setLightTextureID(LLUUID id) +{ + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + } + else + { + if (hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + mLightTexture = NULL; + } + } +} + +void LLVOVolume::setSpotLightParams(LLVector3 params) +{ + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } +} + +void LLVOVolume::setIsLight(BOOL is_light) +{ + if (is_light != getIsLight()) + { + if (is_light) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); + } + + if (is_light) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + else + { + // Not a light. Remove it from the pipeline's light set. + gPipeline.setLight(mDrawable, FALSE); + } + } +} + +void LLVOVolume::setLightColor(const LLColor3& color) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor() != color) + { + param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + } +} + +void LLVOVolume::setLightIntensity(F32 intensity) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor().mV[3] != intensity) + { + param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightRadius(F32 radius) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getRadius() != radius) + { + param_block->setRadius(radius); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightFalloff(F32 falloff) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getFalloff() != falloff) + { + param_block->setFalloff(falloff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightCutoff(F32 cutoff) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getCutoff() != cutoff) + { + param_block->setCutoff(cutoff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +//---------------------------------------------------------------------------- + +BOOL LLVOVolume::getIsLight() const +{ + return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); +} + +LLColor3 LLVOVolume::getLightBaseColor() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()); + } + else + { + return LLColor3(1,1,1); + } +} + +LLColor3 LLVOVolume::getLightColor() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; + } + else + { + return LLColor3(1,1,1); + } +} + +LLUUID LLVOVolume::getLightTextureID() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + } + + return LLUUID::null; +} + + +LLVector3 LLVOVolume::getSpotLightParams() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + } + + return LLVector3(); +} + +F32 LLVOVolume::getSpotLightPriority() const +{ + return mSpotLightPriority; +} + +void LLVOVolume::updateSpotLightPriority() +{ + LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 at(0,0,-1); + at *= getRenderRotation(); + + F32 r = getLightRadius()*0.5f; + + pos += at * r; + + at = LLViewerCamera::getInstance()->getAtAxis(); + + pos -= at * r; + + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS); + } +} + + +bool LLVOVolume::isLightSpotlight() const +{ + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params) + { + return params->isLightSpotlight(); + } + return false; +} + + +LLViewerTexture* LLVOVolume::getLightTexture() +{ + LLUUID id = getLightTextureID(); + + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + } + } + else + { + mLightTexture = NULL; + } + + return mLightTexture; +} + +F32 LLVOVolume::getLightIntensity() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getColor().mV[3]; + } + else + { + return 1.f; + } +} + +F32 LLVOVolume::getLightRadius() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getRadius(); + } + else + { + return 0.f; + } +} + +F32 LLVOVolume::getLightFalloff() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getFalloff(); + } + else + { + return 0.f; + } +} + +F32 LLVOVolume::getLightCutoff() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getCutoff(); + } + else + { + return 0.f; + } +} + +U32 LLVOVolume::getVolumeInterfaceID() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->getID(); + } + + return 0; +} + +BOOL LLVOVolume::isFlexible() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + { + LLVolume* volume = getVolume(); + if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) + { + LLVolumeParams volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + } + return TRUE; + } + else + { + return FALSE; + } +} + +BOOL LLVOVolume::isSculpted() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::isMesh() const +{ + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } + + return FALSE; +} + +BOOL LLVOVolume::hasLightTexture() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::isVolumeGlobal() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; + } + else if (mRiggedVolume.notNull()) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::canBeFlexible() const +{ + U8 path = getVolume()->getParams().getPathParams().getCurveType(); + return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); +} + +BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) +{ + BOOL res = FALSE; + BOOL was_flexible = isFlexible(); + LLVolumeParams volume_params; + if (is_flexible) + { + if (!was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + res = TRUE; + setFlags(FLAGS_USE_PHYSICS, FALSE); + setFlags(FLAGS_PHANTOM, TRUE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + if (mDrawable) + { + mDrawable->makeActive(); + } + } + } + else + { + if (was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); + res = TRUE; + setFlags(FLAGS_PHANTOM, FALSE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + } + } + if (res) + { + res = setVolume(volume_params, 1); + if (res) + { + markForUpdate(TRUE); + } + } + return res; +} + +//---------------------------------------------------------------------------- + +void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) +{ + LLVolume *volume = getVolume(); + + if (volume) + { + LLVector3 view_vector; + view_vector = view_point; + + //transform view vector into volume space + view_vector -= getRenderPosition(); + mDrawable->mDistanceWRTCamera = view_vector.length(); + LLQuaternion worldRot = getRenderRotation(); + view_vector = view_vector * ~worldRot; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + view_vector.scaleVec(invObjScale); + } + + updateRelativeXform(); + LLMatrix4 trans_mat = mRelativeXform; + if (mDrawable->isStatic()) + { + trans_mat.translate(getRegion()->getOriginAgent()); + } + + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); + + nodep->mSilhouetteExists = TRUE; + } +} + +void LLVOVolume::deleteFaces() +{ + S32 face_count = mNumFaces; + if (mDrawable.notNull()) + { + mDrawable->deleteFaces(0, face_count); + } + + mNumFaces = 0; +} + +void LLVOVolume::updateRadius() +{ + if (mDrawable.isNull()) + { + return; + } + + mVObjRadius = getScale().length(); + mDrawable->setRadius(mVObjRadius); +} + + +BOOL LLVOVolume::isAttachment() const +{ + return mState != 0 ; +} + +BOOL LLVOVolume::isHUDAttachment() const +{ + // *NOTE: we assume hud attachment points are in defined range + // since this range is constant for backwards compatibility + // reasons this is probably a reasonable assumption to make + S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mState); + return ( attachment_id >= 31 && attachment_id <= 38 ); +} + + +const LLMatrix4 LLVOVolume::getRenderMatrix() const +{ + if (mDrawable->isActive() && !mDrawable->isRoot()) + { + return mDrawable->getParent()->getWorldMatrix(); + } + return mDrawable->getWorldMatrix(); +} + +// Returns a base cost and adds textures to passed in set. +// total cost is returned value + 5 * size of the resulting set. +// Cannot include cost of textures, as they may be re-used in linked +// children, and cost should only be increased for unique textures -Nyx +U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const +{ + // base cost of each prim should be 10 points + static const U32 ARC_PRIM_COST = 10; + // per-prim costs + static const U32 ARC_INVISI_COST = 1; + static const U32 ARC_SHINY_COST = 1; + static const U32 ARC_GLOW_COST = 1; + static const U32 ARC_FLEXI_COST = 8; + static const U32 ARC_PARTICLE_COST = 16; + static const U32 ARC_BUMP_COST = 4; + + // per-face costs + static const U32 ARC_PLANAR_COST = 1; + static const U32 ARC_ANIM_TEX_COST = 4; + static const U32 ARC_ALPHA_COST = 4; + + U32 shame = ARC_PRIM_COST; + + U32 invisi = 0; + U32 shiny = 0; + U32 glow = 0; + U32 alpha = 0; + U32 flexi = 0; + U32 animtex = 0; + U32 particles = 0; + U32 scale = 0; + U32 bump = 0; + U32 planar = 0; + + if (isFlexible()) + { + flexi = 1; + } + if (isParticleSource()) + { + particles = 1; + } + + const LLVector3& sc = getScale(); + scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2]; + + const LLDrawable* drawablep = mDrawable; + + if (isSculpted()) + { + const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + textures.insert(sculpt_id); + } + + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + const LLFace* face = drawablep->getFace(i); + const LLTextureEntry* te = face->getTextureEntry(); + const LLViewerTexture* img = face->getTexture(); + + if (img) + { + textures.insert(img->getID()); + } + + if (face->getPoolType() == LLDrawPool::POOL_ALPHA) + { + alpha++; + } + else if (img && img->getPrimaryFormat() == GL_ALPHA) + { + invisi = 1; + } + + if (te) + { + if (te->getBumpmap()) + { + bump = 1; + } + if (te->getShiny()) + { + shiny = 1; + } + if (te->getGlow() > 0.f) + { + glow = 1; + } + if (face->mTextureMatrix != NULL) + { + animtex++; + } + if (te->getTexGen()) + { + planar++; + } + } + } + + + shame += invisi * ARC_INVISI_COST; + shame += shiny * ARC_SHINY_COST; + shame += glow * ARC_GLOW_COST; + shame += alpha * ARC_ALPHA_COST; + shame += flexi * ARC_FLEXI_COST; + shame += animtex * ARC_ANIM_TEX_COST; + shame += particles * ARC_PARTICLE_COST; + shame += bump * ARC_BUMP_COST; + shame += planar * ARC_PLANAR_COST; + shame += scale; + + LLViewerObject::const_child_list_t& child_list = getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); + ++iter) + { + const LLViewerObject* child_objectp = *iter; + const LLDrawable* child_drawablep = child_objectp->mDrawable; + if (child_drawablep) + { + const LLVOVolume* child_volumep = child_drawablep->getVOVolume(); + if (child_volumep) + { + shame += child_volumep->getRenderCost(textures); + } + } + } + + return shame; + +} + +F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes) +{ + if (isMesh()) + { + LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); + + F32 radius = getScale().length(); + + return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD); + } + + return 0.f; +} + +U32 LLVOVolume::getTriangleCount() +{ + U32 count = 0; + LLVolume* volume = getVolume(); + if (volume) + { + count = volume->getNumTriangles(); + } + + return count; +} + +U32 LLVOVolume::getHighLODTriangleCount() +{ + U32 ret = 0; + + LLVolume* volume = getVolume(); + + if (!isSculpted()) + { LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else if (isMesh()) - { + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else if (isMesh()) + { LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); if (ref->isTetrahedron() || ref->getNumVolumeFaces() == 0) { gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); } ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else - { //default sculpts have a constant number of triangles - ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch - } - - return ret; -} - -//static -void LLVOVolume::preUpdateGeom() -{ - sNumLODChanges = 0; -} - -void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) -{ - LLViewerObject::parameterChanged(param_type, local_origin); -} - -void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) -{ - LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); - if (mVolumeImpl) - { - mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); - } - if (mDrawable.notNull()) - { - BOOL is_light = getIsLight(); - if (is_light != mDrawable->isState(LLDrawable::LIGHT)) - { - gPipeline.setLight(mDrawable, is_light); - } - } -} - -void LLVOVolume::setSelected(BOOL sel) -{ - LLViewerObject::setSelected(sel); - if (mDrawable.notNull()) - { - markForUpdate(TRUE); - } -} - -void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ -} - -F32 LLVOVolume::getBinRadius() -{ - F32 radius; - - F32 scale = 1.f; - - const LLVector4a* ext = mDrawable->getSpatialExtents(); - - BOOL shrink_wrap = mDrawable->isAnimating(); - BOOL alpha_wrap = FALSE; - - if (!isHUDAttachment()) - { - for (S32 i = 0; i < mDrawable->getNumFaces(); i++) - { - LLFace* face = mDrawable->getFace(i); - if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - !face->canRenderAsMask()) - { - alpha_wrap = TRUE; - break; - } - } - } - else - { - shrink_wrap = FALSE; - } - - if (alpha_wrap) - { - LLVector3 bounds = getScale(); - radius = llmin(bounds.mV[1], bounds.mV[2]); - radius = llmin(radius, bounds.mV[0]); - radius *= 0.5f; - } - else if (shrink_wrap) - { - LLVector4a rad; - rad.setSub(ext[1], ext[0]); - - radius = rad.getLength3().getF32()*0.5f; - } - else if (mDrawable->isStatic()) - { - /*if (mDrawable->getRadius() < 2.0f) - { - radius = 16.f; - } - else - { - radius = llmax(mDrawable->getRadius(), 32.f); - }*/ - - radius = (((S32) mDrawable->getRadius())/2+1)*8; - } - else if (mDrawable->getVObj()->isAttachment()) - { - radius = (((S32) (mDrawable->getRadius()*4)+1))*2; - } - else - { - radius = 8.f; - } - - return llclamp(radius*scale, 0.5f, 256.f); -} - -const LLVector3 LLVOVolume::getPivotPositionAgent() const -{ - if (mVolumeImpl) - { - return mVolumeImpl->getPivotPosition(); - } - return LLViewerObject::getPivotPositionAgent(); -} - -void LLVOVolume::onShift(const LLVector4a &shift_vector) -{ - if (mVolumeImpl) - { - mVolumeImpl->onShift(shift_vector); - } - - updateRelativeXform(); -} - -const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const -{ - if (mVolumeImpl) - { - return mVolumeImpl->getWorldMatrix(xform); - } - return xform->getWorldMatrix(); -} - -LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const -{ - LLVector3 ret = pos - getRenderPosition(); - ret = ret * ~getRenderRotation(); - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - - return ret; -} - -LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const -{ - LLVector3 ret = dir * ~getRenderRotation(); - - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); - - return ret; -} - -LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const -{ - LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); - ret = ret * getRenderRotation(); - ret += getRenderPosition(); - - return ret; -} - -LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const -{ - LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - ret = ret * getRenderRotation(); - - return ret; -} - - -BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp, - LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) - -{ - if (!mbCanSelect - || mDrawable->isDead() - || !gPipeline.hasRenderType(mDrawable->getRenderType())) - { - return FALSE; - } - - BOOL ret = FALSE; - - LLVolume* volume = getVolume(); - - bool transform = true; - - if (mDrawable->isState(LLDrawable::RIGGED)) - { - if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf()) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE); - volume = mRiggedVolume; - transform = false; - } - else - { //cannot pick rigged attachments on other avatars or when not in build mode - return FALSE; - } - } - - if (volume) - { - LLVector3 v_start, v_end, v_dir; - - if (transform) - { - v_start = agentPositionToVolume(start); - v_end = agentPositionToVolume(end); - } - else - { - v_start = start; - v_end = end; - } - - LLVector3 p; - LLVector3 n; - LLVector2 tc; - LLVector3 bn; - - if (intersection != NULL) - { - p = *intersection; - } - - if (tex_coord != NULL) - { - tc = *tex_coord; - } - - if (normal != NULL) - { - n = *normal; - } - - if (bi_normal != NULL) - { - bn = *bi_normal; - } - - S32 face_hit = -1; - - S32 start_face, end_face; - if (face == -1) - { - start_face = 0; - end_face = volume->getNumVolumeFaces(); - } - else - { - start_face = face; - end_face = face+1; - } - - bool special_cursor = specialHoverCursor(); - for (S32 i = start_face; i < end_face; ++i) - { - if (!special_cursor && !pick_transparent && getTE(i)->getColor().mV[3] == 0.f) - { //don't attempt to pick completely transparent faces unless - //pick_transparent is true - continue; - } - - face_hit = volume->lineSegmentIntersect(v_start, v_end, i, - &p, &tc, &n, &bn); - - if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) - { - LLFace* face = mDrawable->getFace(face_hit); - - if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) - { - v_end = p; - if (face_hitp != NULL) - { - *face_hitp = face_hit; - } - - if (intersection != NULL) - { - if (transform) - { - *intersection = volumePositionToAgent(p); // must map back to agent space - } - else - { - *intersection = p; - } - } - - if (normal != NULL) - { - if (transform) - { - *normal = volumeDirectionToAgent(n); - } - else - { - *normal = n; - } - - (*normal).normVec(); - } - - if (bi_normal != NULL) - { - if (transform) - { - *bi_normal = volumeDirectionToAgent(bn); - } - else - { - *bi_normal = bn; - } - (*bi_normal).normVec(); - } - - if (tex_coord != NULL) - { - *tex_coord = tc; - } - - ret = TRUE; - } - } - } - } - - return ret; -} - -bool LLVOVolume::treatAsRigged() -{ - return LLFloater::isVisible(gFloaterTools) && - isAttachment() && - getAvatar() && - getAvatar()->isSelf() && - mDrawable.notNull() && - mDrawable->isState(LLDrawable::RIGGED); -} - -LLRiggedVolume* LLVOVolume::getRiggedVolume() -{ - return mRiggedVolume; -} - -void LLVOVolume::clearRiggedVolume() -{ - if (mRiggedVolume.notNull()) - { - mRiggedVolume = NULL; - updateRelativeXform(); - } -} - -void LLVOVolume::updateRiggedVolume() -{ - //Update mRiggedVolume to match current animation frame of avatar. - //Also update position/size in octree. - - if (!treatAsRigged()) - { - clearRiggedVolume(); - - return; - } - - LLVolume* volume = getVolume(); - - const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID()); - - if (!skin) - { - clearRiggedVolume(); - return; - } - - LLVOAvatar* avatar = getAvatar(); - - if (!avatar) - { - clearRiggedVolume(); - return; - } - - if (!mRiggedVolume) - { - LLVolumeParams p; - mRiggedVolume = new LLRiggedVolume(p); - updateRelativeXform(); - } - - mRiggedVolume->update(skin, avatar, volume); - -} - -static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin"); -static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree"); - -void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) -{ - bool copy = false; - if (volume->getNumVolumeFaces() != getNumVolumeFaces()) - { - copy = true; - } - - for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) - { - const LLVolumeFace& src_face = volume->getVolumeFace(i); - const LLVolumeFace& dst_face = getVolumeFace(i); - - if (src_face.mNumIndices != dst_face.mNumIndices || - src_face.mNumVertices != dst_face.mNumVertices) - { - copy = true; - } - } - - if (copy) - { - copyVolumeFaces(volume); - } - - //build matrix palette - LLMatrix4a mp[64]; - LLMatrix4* mat = (LLMatrix4*) mp; - - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - if (joint) - { - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } - - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& vol_face = volume->getVolumeFace(i); - - LLVolumeFace& dst_face = mVolumeFaces[i]; - - LLVector4a* weight = vol_face.mWeights; - - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); - - LLVector4a* pos = dst_face.mPositions; - - { - LLFastTimer t(FTM_SKIN_RIGGED); - - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - idx[k] = (S32) floorf(w); - wght[k] = w - floorf(w); - scale += wght[k]; - } - - wght *= 1.f/scale; - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - src.setMul(mp[idx[k]], w); - - final_mat.add(src); - } - - - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } - - //update bounding box - LLVector4a& min = dst_face.mExtents[0]; - LLVector4a& max = dst_face.mExtents[1]; - - min = pos[0]; - max = pos[1]; - - for (U32 j = 1; j < dst_face.mNumVertices; ++j) - { - min.setMin(min, pos[j]); - max.setMax(max, pos[j]); - } - - dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); - dst_face.mCenter->mul(0.5f); - - } - - { - LLFastTimer t(FTM_RIGGED_OCTREE); - delete dst_face.mOctree; - dst_face.mOctree = NULL; - - LLVector4a size; - size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); - size.splat(size.getLength3().getF32()*0.5f); - - dst_face.createOctree(1.f); - } - } -} - -U32 LLVOVolume::getPartitionType() const -{ - if (isHUDAttachment()) - { - return LLViewerRegion::PARTITION_HUD; - } - - return LLViewerRegion::PARTITION_VOLUME; -} - -LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) -{ - mLODPeriod = 32; - mDepthMask = FALSE; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_VOLUME; - mSlopRatio = 0.25f; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; -} - -LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) -{ - mDepthMask = FALSE; - mLODPeriod = 32; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_BRIDGE; - - mBufferUsage = GL_DYNAMIC_DRAW_ARB; - - mSlopRatio = 0.25f; -} - -void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) -{ - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - - if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) - { - return; - } - - //add face to drawmap - LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; - - S32 idx = draw_vec.size()-1; - - BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || - (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)); - - if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - llwarns << "Non fullbright face has no normals!" << llendl; - return; - } - - const LLMatrix4* tex_mat = NULL; - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { - tex_mat = facep->mTextureMatrix; - } - - const LLMatrix4* model_mat = NULL; - - LLDrawable* drawable = facep->getDrawable(); - if (drawable->isActive()) - { - model_mat = &(drawable->getRenderMatrix()); - } - else - { - model_mat = &(drawable->getRegion()->mRenderMatrix); - if (model_mat->isIdentity()) - { - model_mat = NULL; - } - } - - U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; - - LLViewerTexture* tex = facep->getTexture(); - - U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255); - - if (idx >= 0 && - draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && - draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) && -#if LL_DARWIN - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && - draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && -#endif - draw_vec[idx]->mGlowColor.mV[3] == glow && - draw_vec[idx]->mFullbright == fullbright && - draw_vec[idx]->mBump == bump && - draw_vec[idx]->mTextureMatrix == tex_mat && - draw_vec[idx]->mModelMatrix == model_mat) - { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); - draw_vec[idx]->validate(); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); - } - else - { - U32 start = facep->getGeomIndex(); - U32 end = start + facep->getGeomCount()-1; - U32 offset = facep->getIndicesStart(); - U32 count = facep->getIndicesCount(); - LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex, - facep->getVertexBuffer(), fullbright, bump); - draw_info->mGroup = group; - draw_info->mVSize = facep->getVirtualSize(); - draw_vec.push_back(draw_info); - draw_info->mTextureMatrix = tex_mat; - draw_info->mModelMatrix = model_mat; - draw_info->mGlowColor.setVec(0,0,0,glow); - if (type == LLRenderPass::PASS_ALPHA) - { //for alpha sorting - facep->setDrawInfo(draw_info); - } - draw_info->mExtents[0] = facep->mExtents[0]; - draw_info->mExtents[1] = facep->mExtents[1]; - - if (LLPipeline::sUseTriStrips) - { - draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; - } - - draw_info->validate(); - } -} - -void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) -{ - -} - -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); - -static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) -{ - LLVOAvatar* avatar = vobj->getAvatar(); - - if (avatar) - { - LLDrawable* drawable = avatar->mDrawable; - if (drawable && drawable->getNumFaces() > 0) - { - LLFace* face = drawable->getFace(0); - if (face) - { - LLDrawPool* drawpool = face->getPool(); - if (drawpool) - { - if (drawpool->getType() == LLDrawPool::POOL_AVATAR) - { - return (LLDrawPoolAvatar*) drawpool; - } - } - } - } - } - - return NULL; -} - -void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) -{ - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - } - - group->mLastUpdateViewAngle = group->mViewAngle; - - if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) - { - if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) - { - LLFastTimer ftm(FTM_REBUILD_VBO); - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - - rebuildMesh(group); - } - return; - } - - group->mBuilt = 1.f; - LLFastTimer ftm(FTM_REBUILD_VBO); - - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - - group->clearDrawMap(); - - mFaceList.clear(); - - std::vector<LLFace*> fullbright_faces; - std::vector<LLFace*> bump_faces; - std::vector<LLFace*> simple_faces; - - std::vector<LLFace*> alpha_faces; - U32 useage = group->mSpatialPartition->mBufferUsage; - - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); - U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); - - U32 cur_total = 0; - - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } - - LLVOVolume* vobj = drawablep->getVOVolume(); - - if (vobj->getVolume() && vobj->getVolume()->isTetrahedron()) - { - continue; - } - - llassert_always(vobj); - vobj->updateTextureVirtualSize(); - vobj->preRebuild(); - - drawablep->clearState(LLDrawable::HAS_ALPHA); - - bool rigged = vobj->isAttachment() && - vobj->isMesh() && - gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); - - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - - bool is_rigged = false; - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); - - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); - - //sum up face verts and indices - drawablep->updateFaceSize(i); - - - - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } - - facep->setState(LLFace::RIGGED); - is_rigged = true; - - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - LLVOAvatar* pAvatarVO = vobj->getAvatar(); - bool pelvisGotSet = false; - - if ( pAvatarVO ) - { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId ); - - if ( pSkinData ) - { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; i<jointCnt; ++i ) - { - std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); - //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; - LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { - pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; - } - } - } - } - } - } - } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) - { - pAvatarVO->postPelvisSetRecalc(); - } - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) - { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); - } - - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - if (type == LLDrawPool::POOL_ALPHA) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } - - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); - } - facep->clearState(LLFace::RIGGED); - } - } - - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } - - cur_total += facep->getGeomCount(); - - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); - - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } - - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) - { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); - - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } - - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) - { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) - { - drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); - } - } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) - { - drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); - } - } - - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - simple_faces.push_back(facep); - } - else - { - drawablep->setState(LLDrawable::HAS_ALPHA); - alpha_faces.push_back(facep); - } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - facep->mLastUpdateTime = gFrameTimeSeconds; - } - - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) - { - if (te->getBumpmap()) - { //needs normal + binormal - bump_faces.push_back(facep); - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal - simple_faces.push_back(facep); - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); - } - } - else - { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + binormal - bump_faces.push_back(facep); - } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - simple_faces.push_back(facep); - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); - } - } - } - } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - - if (is_rigged) - { - drawablep->setState(LLDrawable::RIGGED); - } - else - { - drawablep->clearState(LLDrawable::RIGGED); - } - } - - group->mBufferUsage = useage; - - //PROCESS NON-ALPHA FACES - U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO - U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - - if (LLPipeline::sRenderDeferred) - { - bump_mask |= LLVertexBuffer::MAP_BINORMAL; - } - - genDrawInfo(group, simple_mask, simple_faces); - genDrawInfo(group, bump_mask, bump_faces); - genDrawInfo(group, fullbright_mask, fullbright_faces); - genDrawInfo(group, alpha_mask, alpha_faces, TRUE); - - if (!LLPipeline::sDelayVBUpdate) - { - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); - - if (LLPipeline::sDelayVBUpdate) - { - group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - - mFaceList.clear(); -} - -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); - -void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) -{ - llassert(group); - if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) - { - LLFastTimer tm(FTM_VOLUME_GEOM); - S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; - - group->mBuilt = 1.f; - - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); - LLDrawable* drawablep = *drawable_iter; - - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) - { - LLVOVolume* vobj = drawablep->getVOVolume(); - vobj->preRebuild(); - - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face && face->getVertexBuffer()) - { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); - } - - if (!face) - { - llerrs << "WTF?" << llendl; - } - } - - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - //unmap all the buffers - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) - { - LLSpatialGroup::buffer_texture_map_t& map = i->second; - for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j) - { - LLSpatialGroup::buffer_list_t& list = j->second; - for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k) - { - LLVertexBuffer* buffer = *k; - if (buffer->isLocked()) - { - buffer->setBuffer(0); - } - } - } - } - - // don't forget alpha - if(group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->setBuffer(0); - } - - //if not all buffers are unmapped - if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) - { - llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - LLVertexBuffer* buff = face->getVertexBuffer(); - if (face && buff && buff->isLocked()) - { - buff->setBuffer(0) ; - } - } - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - - if (group && group->isState(LLSpatialGroup::NEW_DRAWINFO)) - { - llerrs << "WTF?" << llendl; - } -} - -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) -{ - //calculate maximum number of vertices to store in a single buffer - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); - - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker()); - } - else - { - //sort faces by distance - std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); - } - - std::vector<LLFace*>::iterator face_iter = faces.begin(); - - LLSpatialGroup::buffer_map_t buffer_map; - - LLViewerTexture* last_tex = NULL; - S32 buffer_index = 0; - - if (distance_sort) - { - buffer_index = -1; - } - - while (face_iter != faces.end()) - { - //pull off next face - LLFace* facep = *face_iter; - LLViewerTexture* tex = facep->getTexture(); - - if (distance_sort) - { - tex = NULL; - } - - if (last_tex == tex) - { - buffer_index++; - } - else - { - last_tex = tex; - buffer_index = 0; - } - - bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); - - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); - - //sum up vertices needed for this render batch - std::vector<LLFace*>::iterator i = face_iter; - ++i; - - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) - { - facep = *i; - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - } - - //create/delete/resize vertex buffer if needed - LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex); - - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) - { - buffer = found_iter->second[buffer_index]; - } - } - - if (!buffer) - { //create new buffer if needed - buffer = createVertexBuffer(mask, - group->mBufferUsage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { //resize pre-existing buffer - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage || - buffer->getTypeMask() != mask) - { - buffer = createVertexBuffer(mask, - group->mBufferUsage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } - } - - buffer_map[mask][tex].push_back(buffer); - - //add face geometry - - U32 indices_index = 0; - U16 index_offset = 0; - - while (face_iter < i) - { //update face indices for new buffer - facep = *face_iter; - facep->setIndicesIndex(indices_index); - facep->setGeomIndex(index_offset); - facep->setVertexBuffer(buffer); - - { - //for debugging, set last time face was updated vs moved - facep->updateRebuildFlags(); - - if (!LLPipeline::sDelayVBUpdate) - { //copy face geometry into vertex buffer - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - U32 te_idx = facep->getTEOffset(); - - if (facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) - { - buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), - facep->getIndicesStart(), facep->getIndicesCount()); - } - } - } - - index_offset += facep->getGeomCount(); - indices_index += facep->getIndicesCount(); - - - //append face to appropriate render batch - - BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) - { //paranoia check to make sure GL doesn't try to read non-existant normals - fullbright = TRUE; - } - - const LLTextureEntry* te = facep->getTextureEntry(); - - BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; - - if (is_alpha) - { - // can we safely treat this as an alpha mask? - if (facep->canRenderAsMask()) - { - if (te->getFullbright() || LLPipeline::sNoAlpha) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - - if (LLPipeline::sRenderDeferred) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA_SHADOW); - } - } - else if (gPipeline.canUseVertexShaders() - && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD - && LLPipeline::sRenderBump - && te->getShiny()) - { //shiny - if (tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (LLPipeline::sRenderDeferred) - { //deferred rendering - if (te->getFullbright()) - { //register in post deferred fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - if (te->getBumpmap()) - { //register in post deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else if (te->getBumpmap()) - { //register in deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //register in deferred simple pass (deferred simple includes shiny) - llassert(mask & LLVertexBuffer::MAP_NORMAL); - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - else if (fullbright) - { //not deferred, register in standard fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - } - else - { //not deferred or fullbright, register in standard shiny pass - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - else - { //not alpha and not shiny - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright || bake_sunlight) - { //fullbright - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) - { //if this is the deferred render and a bump map is present, register in post deferred bump - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else - { - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) - { //non-shiny or fullbright deferred bump - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //all around simple - llassert(mask & LLVertexBuffer::MAP_NORMAL); - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - - //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 - if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) - { - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - - //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && !LLPipeline::sRenderDeferred) - { - llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - - if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump) - { - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - } - - if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) - { - registerFace(group, facep, LLRenderPass::PASS_GLOW); - } - - ++face_iter; - } - - buffer->setBuffer(0); - } - - group->mBufferMap[mask].clear(); - for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) - { - group->mBufferMap[mask][i->first] = i->second; - } -} - -void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) -{ - //initialize to default usage for this partition - U32 usage = group->mSpatialPartition->mBufferUsage; - - //clear off any old faces - mFaceList.clear(); - - //for each drawable - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead()) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - usage = GL_STREAM_DRAW_ARB; - } - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - //sum up face verts and indices - drawablep->updateFaceSize(i); - LLFace* facep = drawablep->getFace(i); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); - } - } - } - - group->mBufferUsage = usage; -} - -LLHUDPartition::LLHUDPartition() -{ - mPartitionType = LLViewerRegion::PARTITION_HUD; - mDrawableType = LLPipeline::RENDER_TYPE_HUD; - mSlopRatio = 0.f; - mLODPeriod = 1; -} - -void LLHUDPartition::shift(const LLVector4a &offset) -{ - //HUD objects don't shift with region crossing. That would be silly. -} - - + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else + { //default sculpts have a constant number of triangles + ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch + } + + return ret; +} + +//static +void LLVOVolume::preUpdateGeom() +{ + sNumLODChanges = 0; +} + +void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) +{ + LLViewerObject::parameterChanged(param_type, local_origin); +} + +void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) +{ + LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); + if (mVolumeImpl) + { + mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); + } + if (mDrawable.notNull()) + { + BOOL is_light = getIsLight(); + if (is_light != mDrawable->isState(LLDrawable::LIGHT)) + { + gPipeline.setLight(mDrawable, is_light); + } + } +} + +void LLVOVolume::setSelected(BOOL sel) +{ + LLViewerObject::setSelected(sel); + if (mDrawable.notNull()) + { + markForUpdate(TRUE); + } +} + +void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) +{ +} + +F32 LLVOVolume::getBinRadius() +{ + F32 radius; + + F32 scale = 1.f; + + const LLVector4a* ext = mDrawable->getSpatialExtents(); + + BOOL shrink_wrap = mDrawable->isAnimating(); + BOOL alpha_wrap = FALSE; + + if (!isHUDAttachment()) + { + for (S32 i = 0; i < mDrawable->getNumFaces(); i++) + { + LLFace* face = mDrawable->getFace(i); + if (face->getPoolType() == LLDrawPool::POOL_ALPHA && + !face->canRenderAsMask()) + { + alpha_wrap = TRUE; + break; + } + } + } + else + { + shrink_wrap = FALSE; + } + + if (alpha_wrap) + { + LLVector3 bounds = getScale(); + radius = llmin(bounds.mV[1], bounds.mV[2]); + radius = llmin(radius, bounds.mV[0]); + radius *= 0.5f; + } + else if (shrink_wrap) + { + LLVector4a rad; + rad.setSub(ext[1], ext[0]); + + radius = rad.getLength3().getF32()*0.5f; + } + else if (mDrawable->isStatic()) + { + /*if (mDrawable->getRadius() < 2.0f) + { + radius = 16.f; + } + else + { + radius = llmax(mDrawable->getRadius(), 32.f); + }*/ + + radius = (((S32) mDrawable->getRadius())/2+1)*8; + } + else if (mDrawable->getVObj()->isAttachment()) + { + radius = (((S32) (mDrawable->getRadius()*4)+1))*2; + } + else + { + radius = 8.f; + } + + return llclamp(radius*scale, 0.5f, 256.f); +} + +const LLVector3 LLVOVolume::getPivotPositionAgent() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->getPivotPosition(); + } + return LLViewerObject::getPivotPositionAgent(); +} + +void LLVOVolume::onShift(const LLVector4a &shift_vector) +{ + if (mVolumeImpl) + { + mVolumeImpl->onShift(shift_vector); + } + + updateRelativeXform(); +} + +const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const +{ + if (mVolumeImpl) + { + return mVolumeImpl->getWorldMatrix(xform); + } + return xform->getWorldMatrix(); +} + +LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const +{ + LLVector3 ret = pos - getRenderPosition(); + ret = ret * ~getRenderRotation(); + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + + return ret; +} + +LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const +{ + LLVector3 ret = dir * ~getRenderRotation(); + + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); + + return ret; +} + +LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const +{ + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); + ret = ret * getRenderRotation(); + ret += getRenderPosition(); + + return ret; +} + +LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const +{ + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + ret = ret * getRenderRotation(); + + return ret; +} + + +BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) + +{ + if (!mbCanSelect + || mDrawable->isDead() + || !gPipeline.hasRenderType(mDrawable->getRenderType())) + { + return FALSE; + } + + BOOL ret = FALSE; + + LLVolume* volume = getVolume(); + + bool transform = true; + + if (mDrawable->isState(LLDrawable::RIGGED)) + { + if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE); + volume = mRiggedVolume; + transform = false; + } + else + { //cannot pick rigged attachments on other avatars or when not in build mode + return FALSE; + } + } + + if (volume) + { + LLVector3 v_start, v_end, v_dir; + + if (transform) + { + v_start = agentPositionToVolume(start); + v_end = agentPositionToVolume(end); + } + else + { + v_start = start; + v_end = end; + } + + LLVector3 p; + LLVector3 n; + LLVector2 tc; + LLVector3 bn; + + if (intersection != NULL) + { + p = *intersection; + } + + if (tex_coord != NULL) + { + tc = *tex_coord; + } + + if (normal != NULL) + { + n = *normal; + } + + if (bi_normal != NULL) + { + bn = *bi_normal; + } + + S32 face_hit = -1; + + S32 start_face, end_face; + if (face == -1) + { + start_face = 0; + end_face = volume->getNumVolumeFaces(); + } + else + { + start_face = face; + end_face = face+1; + } + + bool special_cursor = specialHoverCursor(); + for (S32 i = start_face; i < end_face; ++i) + { + if (!special_cursor && !pick_transparent && getTE(i)->getColor().mV[3] == 0.f) + { //don't attempt to pick completely transparent faces unless + //pick_transparent is true + continue; + } + + face_hit = volume->lineSegmentIntersect(v_start, v_end, i, + &p, &tc, &n, &bn); + + if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) + { + LLFace* face = mDrawable->getFace(face_hit); + + if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) + { + v_end = p; + if (face_hitp != NULL) + { + *face_hitp = face_hit; + } + + if (intersection != NULL) + { + if (transform) + { + *intersection = volumePositionToAgent(p); // must map back to agent space + } + else + { + *intersection = p; + } + } + + if (normal != NULL) + { + if (transform) + { + *normal = volumeDirectionToAgent(n); + } + else + { + *normal = n; + } + + (*normal).normVec(); + } + + if (bi_normal != NULL) + { + if (transform) + { + *bi_normal = volumeDirectionToAgent(bn); + } + else + { + *bi_normal = bn; + } + (*bi_normal).normVec(); + } + + if (tex_coord != NULL) + { + *tex_coord = tc; + } + + ret = TRUE; + } + } + } + } + + return ret; +} + +bool LLVOVolume::treatAsRigged() +{ + return LLFloater::isVisible(gFloaterTools) && + isAttachment() && + getAvatar() && + getAvatar()->isSelf() && + mDrawable.notNull() && + mDrawable->isState(LLDrawable::RIGGED); +} + +LLRiggedVolume* LLVOVolume::getRiggedVolume() +{ + return mRiggedVolume; +} + +void LLVOVolume::clearRiggedVolume() +{ + if (mRiggedVolume.notNull()) + { + mRiggedVolume = NULL; + updateRelativeXform(); + } +} + +void LLVOVolume::updateRiggedVolume() +{ + //Update mRiggedVolume to match current animation frame of avatar. + //Also update position/size in octree. + + if (!treatAsRigged()) + { + clearRiggedVolume(); + + return; + } + + LLVolume* volume = getVolume(); + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID()); + + if (!skin) + { + clearRiggedVolume(); + return; + } + + LLVOAvatar* avatar = getAvatar(); + + if (!avatar) + { + clearRiggedVolume(); + return; + } + + if (!mRiggedVolume) + { + LLVolumeParams p; + mRiggedVolume = new LLRiggedVolume(p); + updateRelativeXform(); + } + + mRiggedVolume->update(skin, avatar, volume); + +} + +static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin"); +static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree"); + +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) +{ + bool copy = false; + if (volume->getNumVolumeFaces() != getNumVolumeFaces()) + { + copy = true; + } + + for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) + { + const LLVolumeFace& src_face = volume->getVolumeFace(i); + const LLVolumeFace& dst_face = getVolumeFace(i); + + if (src_face.mNumIndices != dst_face.mNumIndices || + src_face.mNumVertices != dst_face.mNumVertices) + { + copy = true; + } + } + + if (copy) + { + copyVolumeFaces(volume); + } + + //build matrix palette + LLMatrix4a mp[64]; + LLMatrix4* mat = (LLMatrix4*) mp; + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (joint) + { + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + LLVolumeFace& dst_face = mVolumeFaces[i]; + + LLVector4a* weight = vol_face.mWeights; + + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); + + LLVector4a* pos = dst_face.mPositions; + + { + LLFastTimer t(FTM_SKIN_RIGGED); + + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + final_mat.clear(); + + S32 idx[4]; + + LLVector4 wght; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j][k]; + + idx[k] = (S32) floorf(w); + wght[k] = w - floorf(w); + scale += wght[k]; + } + + wght *= 1.f/scale; + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mp[idx[k]], w); + + final_mat.add(src); + } + + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + + //update bounding box + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; + + min = pos[0]; + max = pos[1]; + + for (U32 j = 1; j < dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } + + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); + + } + + { + LLFastTimer t(FTM_RIGGED_OCTREE); + delete dst_face.mOctree; + dst_face.mOctree = NULL; + + LLVector4a size; + size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); + size.splat(size.getLength3().getF32()*0.5f); + + dst_face.createOctree(1.f); + } + } +} + +U32 LLVOVolume::getPartitionType() const +{ + if (isHUDAttachment()) + { + return LLViewerRegion::PARTITION_HUD; + } + + return LLViewerRegion::PARTITION_VOLUME; +} + +LLVolumePartition::LLVolumePartition() +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) +{ + mLODPeriod = 32; + mDepthMask = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_VOLUME; + mSlopRatio = 0.25f; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; +} + +LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) +{ + mDepthMask = FALSE; + mLODPeriod = 32; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_BRIDGE; + + mBufferUsage = GL_DYNAMIC_DRAW_ARB; + + mSlopRatio = 0.25f; +} + +void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) + { + return; + } + + //add face to drawmap + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || + (type == LLRenderPass::PASS_INVISIBLE) || + (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)); + + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + llwarns << "Non fullbright face has no normals!" << llendl; + return; + } + + const LLMatrix4* tex_mat = NULL; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { + tex_mat = facep->mTextureMatrix; + } + + const LLMatrix4* model_mat = NULL; + + LLDrawable* drawable = facep->getDrawable(); + if (drawable->isActive()) + { + model_mat = &(drawable->getRenderMatrix()); + } + else + { + model_mat = &(drawable->getRegion()->mRenderMatrix); + if (model_mat->isIdentity()) + { + model_mat = NULL; + } + } + + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; + + LLViewerTexture* tex = facep->getTexture(); + + U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255); + + if (idx >= 0 && + draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && + draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) && +#if LL_DARWIN + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && +#endif + draw_vec[idx]->mGlowColor.mV[3] == glow && + draw_vec[idx]->mFullbright == fullbright && + draw_vec[idx]->mBump == bump && + draw_vec[idx]->mTextureMatrix == tex_mat && + draw_vec[idx]->mModelMatrix == model_mat) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); + draw_vec[idx]->validate(); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex, + facep->getVertexBuffer(), fullbright, bump); + draw_info->mGroup = group; + draw_info->mVSize = facep->getVirtualSize(); + draw_vec.push_back(draw_info); + draw_info->mTextureMatrix = tex_mat; + draw_info->mModelMatrix = model_mat; + draw_info->mGlowColor.setVec(0,0,0,glow); + if (type == LLRenderPass::PASS_ALPHA) + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + draw_info->mExtents[0] = facep->mExtents[0]; + draw_info->mExtents[1] = facep->mExtents[1]; + + if (LLPipeline::sUseTriStrips) + { + draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; + } + + draw_info->validate(); + } +} + +void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) +{ + +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); + +static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) +{ + LLVOAvatar* avatar = vobj->getAvatar(); + + if (avatar) + { + LLDrawable* drawable = avatar->mDrawable; + if (drawable && drawable->getNumFaces() > 0) + { + LLFace* face = drawable->getFace(0); + if (face) + { + LLDrawPool* drawpool = face->getPool(); + if (drawpool) + { + if (drawpool->getType() == LLDrawPool::POOL_AVATAR) + { + return (LLDrawPoolAvatar*) drawpool; + } + } + } + } + } + + return NULL; +} + +void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +{ + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + } + + group->mLastUpdateViewAngle = group->mViewAngle; + + if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) + { + if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) + { + LLFastTimer ftm(FTM_REBUILD_VBO); + LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); + + rebuildMesh(group); + } + return; + } + + group->mBuilt = 1.f; + LLFastTimer ftm(FTM_REBUILD_VBO); + + LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); + + group->clearDrawMap(); + + mFaceList.clear(); + + std::vector<LLFace*> fullbright_faces; + std::vector<LLFace*> bump_faces; + std::vector<LLFace*> simple_faces; + + std::vector<LLFace*> alpha_faces; + U32 useage = group->mSpatialPartition->mBufferUsage; + + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + U32 cur_total = 0; + + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } + + LLVOVolume* vobj = drawablep->getVOVolume(); + + if (vobj->getVolume() && vobj->getVolume()->isTetrahedron()) + { + continue; + } + + llassert_always(vobj); + vobj->updateTextureVirtualSize(); + vobj->preRebuild(); + + drawablep->clearState(LLDrawable::HAS_ALPHA); + + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); + + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + + bool is_rigged = false; + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); + + //sum up face verts and indices + drawablep->updateFaceSize(i); + + + + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + + facep->setState(LLFace::RIGGED); + is_rigged = true; + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. + LLVOAvatar* pAvatarVO = vobj->getAvatar(); + bool pelvisGotSet = false; + + if ( pAvatarVO ) + { + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId ); + + if ( pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + bool fullRig = (jointCnt>=20) ? true : false; + if ( fullRig ) + { + for ( int i=0; i<jointCnt; ++i ) + { + std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); + //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; + LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position + pJoint->storeCurrentXform( jointPos ); + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pJoint->storeCurrentXform( jointPos ); + if ( !pAvatarVO->hasPelvisOffset() ) + { + pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); + //Trigger to rebuild viewer AV + pelvisGotSet = true; + } + } + } + } + } + } + } + } + //If we've set the pelvis to a new position we need to also rebuild some information that the + //viewer does at launch (e.g. body size etc.) + if ( pelvisGotSet ) + { + pAvatarVO->postPelvisSetRecalc(); + } + + if (pool) + { + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } + + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } + + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) + { + facep->clearVertexBuffer(); + continue; + } + + cur_total += facep->getGeomCount(); + + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + { + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); + + if (facep->isState(LLFace::TEXTURE_ANIM)) + { + if (!vobj->mTexAnimMode) + { + facep->clearState(LLFace::TEXTURE_ANIM); + } + } + + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); + + if (vobj->isHUDAttachment()) + { + facep->setState(LLFace::FULLBRIGHT); + } + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); + } + } + + if (type == LLDrawPool::POOL_ALPHA) + { + if (facep->canRenderAsMask()) + { //can be treated as alpha mask + simple_faces.push_back(facep); + } + else + { + drawablep->setState(LLDrawable::HAS_ALPHA); + alpha_faces.push_back(facep); + } + } + else + { + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; + } + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } + } + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } + } + } + } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } + } + + if (is_rigged) + { + drawablep->setState(LLDrawable::RIGGED); + } + else + { + drawablep->clearState(LLDrawable::RIGGED); + } + } + + group->mBufferUsage = useage; + + //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + if (LLPipeline::sRenderDeferred) + { + bump_mask |= LLVertexBuffer::MAP_BINORMAL; + } + + genDrawInfo(group, simple_mask, simple_faces); + genDrawInfo(group, bump_mask, bump_faces); + genDrawInfo(group, fullbright_mask, fullbright_faces); + genDrawInfo(group, alpha_mask, alpha_faces, TRUE); + + if (!LLPipeline::sDelayVBUpdate) + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + + if (LLPipeline::sDelayVBUpdate) + { + group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + + mFaceList.clear(); +} + +static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); +static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); + +void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) +{ + llassert(group); + if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + LLFastTimer tm(FTM_VOLUME_GEOM); + S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; + + group->mBuilt = 1.f; + + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); + LLDrawable* drawablep = *drawable_iter; + + if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) + { + LLVOVolume* vobj = drawablep->getVOVolume(); + vobj->preRebuild(); + + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face && face->getVertexBuffer()) + { + face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + } + + if (!face) + { + llerrs << "WTF?" << llendl; + } + } + + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } + + //unmap all the buffers + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + { + LLSpatialGroup::buffer_texture_map_t& map = i->second; + for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j) + { + LLSpatialGroup::buffer_list_t& list = j->second; + for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k) + { + LLVertexBuffer* buffer = *k; + if (buffer->isLocked()) + { + buffer->setBuffer(0); + } + } + } + } + + // don't forget alpha + if(group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->setBuffer(0); + } + + //if not all buffers are unmapped + if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) + { + llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (face && buff && buff->isLocked()) + { + buff->setBuffer(0) ; + } + } + } + } + + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + + if (group && group->isState(LLSpatialGroup::NEW_DRAWINFO)) + { + llerrs << "WTF?" << llendl; + } +} + +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) +{ + //calculate maximum number of vertices to store in a single buffer + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } + + std::vector<LLFace*>::iterator face_iter = faces.begin(); + + LLSpatialGroup::buffer_map_t buffer_map; + + LLViewerTexture* last_tex = NULL; + S32 buffer_index = 0; + + if (distance_sort) + { + buffer_index = -1; + } + + while (face_iter != faces.end()) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerTexture* tex = facep->getTexture(); + + if (distance_sort) + { + tex = NULL; + } + + if (last_tex == tex) + { + buffer_index++; + } + else + { + last_tex = tex; + buffer_index = 0; + } + + bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); + + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); + + //sum up vertices needed for this render batch + std::vector<LLFace*>::iterator i = face_iter; + ++i; + + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } + + //create/delete/resize vertex buffer if needed + LLVertexBuffer* buffer = NULL; + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex); + + if (found_iter != group->mBufferMap[mask].end()) + { + if ((U32) buffer_index < found_iter->second.size()) + { + buffer = found_iter->second[buffer_index]; + } + } + + if (!buffer) + { //create new buffer if needed + buffer = createVertexBuffer(mask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { //resize pre-existing buffer + if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage || + buffer->getTypeMask() != mask) + { + buffer = createVertexBuffer(mask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { + buffer->resizeBuffer(geom_count, index_count); + } + } + + buffer_map[mask][tex].push_back(buffer); + + //add face geometry + + U32 indices_index = 0; + U16 index_offset = 0; + + while (face_iter < i) + { //update face indices for new buffer + facep = *face_iter; + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + + { + //for debugging, set last time face was updated vs moved + facep->updateRebuildFlags(); + + if (!LLPipeline::sDelayVBUpdate) + { //copy face geometry into vertex buffer + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + U32 te_idx = facep->getTEOffset(); + + if (facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) + { + buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), + facep->getIndicesStart(), facep->getIndicesCount()); + } + } + } + + index_offset += facep->getGeomCount(); + indices_index += facep->getIndicesCount(); + + + //append face to appropriate render batch + + BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) + { //paranoia check to make sure GL doesn't try to read non-existant normals + fullbright = TRUE; + } + + const LLTextureEntry* te = facep->getTextureEntry(); + + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; + + if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (facep->canRenderAsMask()) + { + if (te->getFullbright() || LLPipeline::sNoAlpha) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + + if (LLPipeline::sRenderDeferred) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_SHADOW); + } + } + else if (gPipeline.canUseVertexShaders() + && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD + && LLPipeline::sRenderBump + && te->getShiny()) + { //shiny + if (tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim+shiny + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (LLPipeline::sRenderDeferred) + { //deferred rendering + if (te->getFullbright()) + { //register in post deferred fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else if (te->getBumpmap()) + { //register in deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //register in deferred simple pass (deferred simple includes shiny) + llassert(mask & LLVertexBuffer::MAP_NORMAL); + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + else if (fullbright) + { //not deferred, register in standard fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else + { //not deferred or fullbright, register in standard shiny pass + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { //not alpha and not shiny + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright || bake_sunlight) + { //fullbright + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else + { + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //non-shiny or fullbright deferred bump + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //all around simple + llassert(mask & LLVertexBuffer::MAP_NORMAL); + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + + //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 + if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) + { + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 + if (!is_alpha && !LLPipeline::sRenderDeferred) + { + llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + + if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + } + + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + { + registerFace(group, facep, LLRenderPass::PASS_GLOW); + } + + ++face_iter; + } + + buffer->setBuffer(0); + } + + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) + { + group->mBufferMap[mask][i->first] = i->second; + } +} + +void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) +{ + //initialize to default usage for this partition + U32 usage = group->mSpatialPartition->mBufferUsage; + + //clear off any old faces + mFaceList.clear(); + + //for each drawable + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead()) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + usage = GL_STREAM_DRAW_ARB; + } + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } + } + } + + group->mBufferUsage = usage; +} + +LLHUDPartition::LLHUDPartition() +{ + mPartitionType = LLViewerRegion::PARTITION_HUD; + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mSlopRatio = 0.f; + mLODPeriod = 1; +} + +void LLHUDPartition::shift(const LLVector4a &offset) +{ + //HUD objects don't shift with region crossing. That would be silly. +} + + diff --git a/indra/newview/llwearabletype.cpp b/indra/newview/llwearabletype.cpp index 9e95604712f168ee8878ab66e3954b37ad009168..c090ab5c3dedeef17ec052b3c85eb810a54204f6 100644 --- a/indra/newview/llwearabletype.cpp +++ b/indra/newview/llwearabletype.cpp @@ -80,7 +80,7 @@ LLWearableDictionary::LLWearableDictionary() 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, FALSE)); + 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)); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 2d67786c015ed39ce23306d796c84f43b468f7e3..23594e74b6917c34b06f1fefda3b50e7ca9a312e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1266,6 +1266,8 @@ static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3 void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const { + F32 radius_squared = radius * radius; + if(avatar_ids != NULL) { avatar_ids->clear(); @@ -1286,7 +1288,7 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi if(!uuid.isNull()) { LLVector3d pos_global = pVOAvatar->getPositionGlobal(); - if(dist_vec(pos_global, relative_to) <= radius) + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { if(positions != NULL) { @@ -1310,7 +1312,7 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi for (S32 i = 0; i < count; i++) { LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); - if(dist_vec(pos_global, relative_to) <= radius) + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { LLUUID uuid = regionp->mMapAvatarIDs.get(i); // if this avatar doesn't already exist in the list, add it diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index bd3b5d05f6ca7c7f5b7e47169da68d97a5a03ba5..21fbe52ccd26fee1418e069c1903e4b504701f48 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5019,9 +5019,17 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) light_state->setDiffuse(light_color); light_state->setAmbient(LLColor4::black); light_state->setConstantAttenuation(0.f); - light_state->setLinearAttenuation(linatten); - light_state->setQuadraticAttenuation(0.f); - + if (sRenderDeferred) + { + light_state->setLinearAttenuation(light_radius*1.5f); + light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); + } + else + { + light_state->setLinearAttenuation(linatten); + light_state->setQuadraticAttenuation(0.f); + } + if (light->isLightSpotlight() // directional (spot-)light && (LLPipeline::sRenderDeferred || gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"))) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on { diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 731bd7454745b698b2a2dc013f257bfe470d7024..d02662681b5d4f6011a18e62b3320ea49de7231f 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -760,10 +760,29 @@ <color name="MenuBarProjectBgColor" reference="MdBlue" /> + <color name="MeshImportTableNormalColor" value="1 1 1 1"/> <color name="MeshImportTableHighlightColor" value="0.2 0.8 1 1"/> + + + <!-- Generic color names (legacy) --> + <color + name="white" + value="1 1 1 1"/> + <color + name="black" + value="0 0 0 1"/> + <color + name="red" + value="1 0 0 1"/> + <color + name="green" + value="0 1 0 1"/> + <color + name="blue" + value="0 0 1 1"/> </colors> diff --git a/indra/newview/skins/default/xui/de/floater_beacons.xml b/indra/newview/skins/default/xui/de/floater_beacons.xml index 6e83e0419bd63d335300f447c72863a19230840f..1a052bd8149926a77f5001b58af0ff258097d2d7 100644 --- a/indra/newview/skins/default/xui/de/floater_beacons.xml +++ b/indra/newview/skins/default/xui/de/floater_beacons.xml @@ -17,5 +17,6 @@ <check_box label="Nur berühren" name="touch_only"/> <check_box label="Soundquellen" name="sounds"/> <check_box label="Partikelquellen" name="particles"/> + <check_box label="Medienquellen" name="moapbeacon"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/de/menu_avatar_self.xml b/indra/newview/skins/default/xui/de/menu_avatar_self.xml index 40557b7ad83ecb4b6f413eca325f561e01c345b7..c49f4b198bf83b34e7af127a6c4f2066d8689397 100644 --- a/indra/newview/skins/default/xui/de/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/de/menu_avatar_self.xml @@ -14,6 +14,7 @@ <menu_item_call label="Unterhemd" name="Self Undershirt"/> <menu_item_call label="Unterhose" name="Self Underpants"/> <menu_item_call label="Tätowierung" name="Self Tattoo"/> + <menu_item_call label="Physik" name="Self Physics"/> <menu_item_call label="Alpha" name="Self Alpha"/> <menu_item_call label="Alle Kleider" name="All Clothes"/> </context_menu> diff --git a/indra/newview/skins/default/xui/de/menu_bottomtray.xml b/indra/newview/skins/default/xui/de/menu_bottomtray.xml index 660cd2eaf346f15233f2f74ecc83ebfd1ec989e0..da36be59d026eda0b281813bbaf35e3c257ec99b 100644 --- a/indra/newview/skins/default/xui/de/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/de/menu_bottomtray.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="hide_camera_move_controls_menu"> - <menu_item_check label="Voice aktiviert" name="EnableVoiceChat"/> + <menu_item_check label="Schaltfläche „Sprechen“" name="EnableVoiceChat"/> <menu_item_check label="Schaltfläche Gesten" name="ShowGestureButton"/> <menu_item_check label="Schaltfläche Bewegungssteuerung" name="ShowMoveButton"/> <menu_item_check label="Schaltfläche Ansicht" name="ShowCameraButton"/> diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml index 43722e0dcf692bfb667dbc391a11aa2636077829..9fcd41e62ab07610df038baad6345475c0c70fb7 100644 --- a/indra/newview/skins/default/xui/de/menu_inventory.xml +++ b/indra/newview/skins/default/xui/de/menu_inventory.xml @@ -25,6 +25,7 @@ <menu_item_call label="Neue Unterhose" name="New Underpants"/> <menu_item_call label="Neue Alpha-Maske" name="New Alpha Mask"/> <menu_item_call label="Neue Tätowierung" name="New Tattoo"/> + <menu_item_call label="Neue Physik" name="New Physics"/> </menu> <menu label="Neue Körperteile" name="New Body Parts"> <menu_item_call label="Neue Form/Gestalt" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/de/menu_inventory_add.xml b/indra/newview/skins/default/xui/de/menu_inventory_add.xml index dccee6712da5c2743e22f68615d2ebee3e3c348d..165e9a9264eb32d2fe00e857d0455bfdd8d701a7 100644 --- a/indra/newview/skins/default/xui/de/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/de/menu_inventory_add.xml @@ -23,6 +23,7 @@ <menu_item_call label="Neue Unterhose" name="New Underpants"/> <menu_item_call label="Neues Alpha" name="New Alpha"/> <menu_item_call label="Neue Tätowierung" name="New Tattoo"/> + <menu_item_call label="Neue Physik" name="New Physics"/> </menu> <menu label="Neue Körperteile" name="New Body Parts"> <menu_item_call label="Neue Form/Gestalt" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/de/menu_media_ctrl.xml b/indra/newview/skins/default/xui/de/menu_media_ctrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..781796670afb0f43ac1157eb29e538083dc20036 --- /dev/null +++ b/indra/newview/skins/default/xui/de/menu_media_ctrl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="media ctrl context menu"> + <menu_item_call label="Ausschneiden" name="Cut"/> + <menu_item_call label="Kopieren" name="Copy"/> + <menu_item_call label="Einfügen" name="Paste"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/de/menu_outfit_gear.xml b/indra/newview/skins/default/xui/de/menu_outfit_gear.xml index 897154ec5626adfabcc1876e52633533cf29087b..d56c93533cf24fa3c2dbcbf829add06d584bb07f 100644 --- a/indra/newview/skins/default/xui/de/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/de/menu_outfit_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="Gear Outfit"> +<toggleable_menu name="Gear Outfit"> <menu_item_call label="Anziehen - Aktuelles Outfit ersetzen" name="wear"/> <menu_item_call label="Anziehen - Aktuelles Outfit hinzufügen" name="wear_add"/> <menu_item_call label="Ausziehen - Aus aktuellem Outfit entfernen" name="take_off"/> @@ -14,6 +14,7 @@ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/> <menu_item_call label="Neue Unterhose" name="New Underpants"/> <menu_item_call label="Neues Alpha" name="New Alpha"/> + <menu_item_call label="Neue Physik" name="New Physics"/> <menu_item_call label="Neue Tätowierung" name="New Tattoo"/> </menu> <menu label="Neue Körperteile" name="New Body Parts"> @@ -24,4 +25,4 @@ </menu> <menu_item_call label="Outfit neu benennen" name="rename"/> <menu_item_call label="Outfit löschen" name="delete_outfit"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index 17bcb013cc9e208389ad4a931c29a68374e5c457..9d5a69105d8374291ab86eef03fdea1877a4776f 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -413,6 +413,7 @@ <menu_item_call label="Rock" name="Skirt"/> <menu_item_call label="Alpha" name="Alpha"/> <menu_item_call label="Tätowierung" name="Tattoo"/> + <menu_item_call label="Physik" name="Physics"/> <menu_item_call label="Alle Kleider" name="All Clothes"/> </menu> <menu label="Hilfe" name="Help"> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 3c63c093d28731c3c3d02d550f0a7edc1cc227f8..c172f7ea2dbc363d4086b81764c1d41e3837082b 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2853,6 +2853,13 @@ Alle stummschalten? <notification label="Stehen" name="HintSit"> Um aufzustehen, klicken Sie auf die Schaltfläche „Stehen“. </notification> + <notification label="Sprechen" name="HintSpeak"> + Auf Schaltfläche „Sprechen“ klicken, um das Mikrofon ein- und auszuschalten. + +Auf den Pfeil nach oben klicken, um die Sprachsteuerung zu sehen. + +Durch Ausblenden der Schaltfläche „Sprechen“ wird die Sprechfunktion deaktiviert. + </notification> <notification label="Welt erkunden" name="HintDestinationGuide"> Im Reiseführer finden Sie Tausende von interessanten Orten. Wählen Sie einfach einen Ort aus und klicken Sie auf „Teleportieren“. </notification> @@ -2862,12 +2869,14 @@ Alle stummschalten? <notification label="Bewegen" name="HintMove"> Um zu gehen oder zu rennen, öffnen Sie das Bedienfeld „Bewegen“ und klicken Sie auf die Pfeile. Sie können auch die Pfeiltasten auf Ihrer Tastatur verwenden. </notification> + <notification label="" name="HintMoveClick"> + 1. Zum Gehen klicken: Auf beliebige Stelle am Boden klicken, um zu dieser Stelle zu gehen. + +2. Zum Drehen der Anzeige klicken und ziehen: Auf beliebige Stelle in der Welt klicken und ziehen, um Ihre Ansicht zu ändern. + </notification> <notification label="Anzeigename" name="HintDisplayName"> Hier können Sie Ihren anpassbaren Anzeigenamen festlegen. Der Anzeigename unterscheidet sich von Ihrem eindeutigen Benutzernamen, der nicht geändert werden kann. In den Einstellungen können Sie festlegen, welcher Name von anderen Einwohnern angezeigt wird. </notification> - <notification label="Bewegen" name="HintMoveArrows"> - Verwenden Sie zum Gehen die Pfeiltasten auf Ihrer Tastatur. Drücken Sie die Nach-oben-Taste zweimal, um zu rennen. - </notification> <notification label="Ansicht" name="HintView"> Um die Kameraansicht zu ändern, verwenden Sie die Schwenk- und Kreissteuerungen. Um die Ansicht zurückzusetzen, drücken Sie die Esc-Taste oder laufen Sie einfach. </notification> diff --git a/indra/newview/skins/default/xui/de/panel_edit_physics.xml b/indra/newview/skins/default/xui/de/panel_edit_physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd9c84577af0a54b90d110190ffd18bdc1a4c0b7 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_edit_physics.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="edit_physics_panel"> + <panel label="" name="accordion_panel"> + <accordion name="physics_accordion"> + <accordion_tab name="physics_breasts_updown_tab" title="Brust – Hüpfen"/> + <accordion_tab name="physics_breasts_inout_tab" title="Brust – Dekolleté"/> + <accordion_tab name="physics_breasts_leftright_tab" title="Brust – Schwingen"/> + <accordion_tab name="physics_belly_tab" title="Bauch – Hüpfen"/> + <accordion_tab name="physics_butt_tab" title="Po – Hüpfen"/> + <accordion_tab name="physics_butt_leftright_tab" title="Po – Wiegen"/> + <accordion_tab name="physics_advanced_tab" title="Erweiterte Parameter"/> + </accordion> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_edit_wearable.xml b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml index 271db4c15c2cb8619f5f5fb1c1b9956403535cd1..94a79a0bbd929b68fdb4935df8edd90af48e9a91 100644 --- a/indra/newview/skins/default/xui/de/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml @@ -45,6 +45,9 @@ <string name="edit_tattoo_title"> Tätowierung bearbeiten </string> + <string name="edit_physics_title"> + Physik bearbeiten + </string> <string name="shape_desc_text"> Form: </string> @@ -90,6 +93,9 @@ <string name="tattoo_desc_text"> Tätowierung: </string> + <string name="physics_desc_text"> + Physik: + </string> <labeled_back_button label="Speichern" name="back_btn" tool_tip="Zurück zu Outfit bearbeiten"/> <text name="edit_wearable_title" value="Form bearbeiten"/> <panel label="Hemd" name="wearable_type_panel"> diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml index 8c8cdd31fed7cf9614e3dede81a5d2eb60f81f2b..ca8af27f58c628bea79c015b47f9cb5784d3855e 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml @@ -30,7 +30,9 @@ <spinner label="Lebenszeit von Toasts für Chat in der Nähe:" name="nearby_toasts_lifetime"/> <spinner label="Ein-/Ausblenddauer von Toasts für Chat in der Nähe:" name="nearby_toasts_fadingtime"/> <check_box name="translate_chat_checkbox"/> - <text name="translate_chb_label" >Bei Chat Maschinenübersetzung verwenden (Service von Google)</text> + <text name="translate_chb_label"> + Beim Chatten Maschinenübersetzung verwenden (von Google bereitgestellt) + </text> <text name="translate_language_text"> Chat übersetzen in: </text> diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml index 63161c954eaf4c71d5b8e8a90efceba8cf915f2b..78cb03a50a0b11ca1756bf8a7c15b61c13c01b71 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml @@ -39,6 +39,10 @@ <combo_box.item label="Alle Avatare und Objekte" name="3"/> <combo_box.item label="Alles" name="4"/> </combo_box> + <slider label="Avatar-Physik:" name="AvatarPhysicsDetail"/> + <text name="AvatarPhysicsDetailText"> + Niedrig + </text> <slider label="Sichtweite:" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> m diff --git a/indra/newview/skins/default/xui/de/panel_preferences_sound.xml b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml index 07631b6a91146b3b09c22904cb9b190ee73e3fad..c118e4e4dd21a51f7935749b3931b0acfe91cb50 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml @@ -5,7 +5,9 @@ </panel.string> <slider label="Master-Lautstärke" name="System Volume"/> <check_box initial_value="true" name="mute_when_minimized"/> - <text name="mute_chb_label">Stummschalten, wenn minimiert</text> + <text name="mute_chb_label"> + Stummschalten, wenn minimiert + </text> <slider label="Schaltflächen" name="UI Volume"/> <slider label="Umgebung" name="Wind Volume"/> <slider label="Soundeffekte" name="SFX Volume"/> diff --git a/indra/newview/skins/default/xui/de/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/de/panel_scrolling_param_base.xml new file mode 100644 index 0000000000000000000000000000000000000000..990193574e5f4aff2fac6462ddf1a587a74be247 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_scrolling_param_base.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="LLScrollingPanelParamBase"> + <slider label="[BESCHR]" name="param slider"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 0c621db6b0d448a8cf7178717c7fdaf17e4ced30..f32eb21dd3dff1f01f70068f8f13c55507e87556 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -876,6 +876,9 @@ <string name="tattoo"> Tätowierung </string> + <string name="physics"> + Physik + </string> <string name="invalid"> ungültig </string> @@ -915,6 +918,9 @@ <string name="tattoo_not_worn"> Tätowierung nicht getragen </string> + <string name="physics_not_worn"> + Physik nicht getragen + </string> <string name="invalid_not_worn"> ungültig </string> @@ -963,6 +969,9 @@ <string name="create_new_tattoo"> Neue Tätowierung erstellen </string> + <string name="create_new_physics"> + Neue Physik erstellen + </string> <string name="create_new_invalid"> ungültig </string> @@ -2247,6 +2256,114 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ <string name="Bulbous Nose"> Knollennase </string> + <string name="Breast Physics Mass"> + Brust – Masse + </string> + <string name="Breast Physics Smoothing"> + Brust – Glättung + </string> + <string name="Breast Physics Gravity"> + Brust – Schwerkraft + </string> + <string name="Breast Physics Drag"> + Brust – Luftwiderstand + </string> + <string name="Breast Physics InOut Max Effect"> + Max. Effekt + </string> + <string name="Breast Physics InOut Spring"> + Federn + </string> + <string name="Breast Physics InOut Gain"> + Verstärkung + </string> + <string name="Breast Physics InOut Damping"> + Dämpfung + </string> + <string name="Breast Physics UpDown Max Effect"> + Max. Effekt + </string> + <string name="Breast Physics UpDown Spring"> + Federn + </string> + <string name="Breast Physics UpDown Gain"> + Verstärkung + </string> + <string name="Breast Physics UpDown Damping"> + Dämpfung + </string> + <string name="Breast Physics LeftRight Max Effect"> + Max. Effekt + </string> + <string name="Breast Physics LeftRight Spring"> + Federn + </string> + <string name="Breast Physics LeftRight Gain"> + Verstärkung + </string> + <string name="Breast Physics LeftRight Damping"> + Dämpfung + </string> + <string name="Belly Physics Mass"> + Bauch – Masse + </string> + <string name="Belly Physics Smoothing"> + Bauch – Glättung + </string> + <string name="Belly Physics Gravity"> + Bauch – Schwerkraft + </string> + <string name="Belly Physics Drag"> + Bauch – Luftwiderstand + </string> + <string name="Belly Physics UpDown Max Effect"> + Max. Effekt + </string> + <string name="Belly Physics UpDown Spring"> + Federn + </string> + <string name="Belly Physics UpDown Gain"> + Verstärkung + </string> + <string name="Belly Physics UpDown Damping"> + Dämpfung + </string> + <string name="Butt Physics Mass"> + Po – Masse + </string> + <string name="Butt Physics Smoothing"> + Po – Glättung + </string> + <string name="Butt Physics Gravity"> + Po – Schwerkraft + </string> + <string name="Butt Physics Drag"> + Po – Luftwiderstand + </string> + <string name="Butt Physics UpDown Max Effect"> + Max. Effekt + </string> + <string name="Butt Physics UpDown Spring"> + Federn + </string> + <string name="Butt Physics UpDown Gain"> + Verstärkung + </string> + <string name="Butt Physics UpDown Damping"> + Dämpfung + </string> + <string name="Butt Physics LeftRight Max Effect"> + Max. Effekt + </string> + <string name="Butt Physics LeftRight Spring"> + Federn + </string> + <string name="Butt Physics LeftRight Gain"> + Verstärkung + </string> + <string name="Butt Physics LeftRight Damping"> + Dämpfung + </string> <string name="Bushy Eyebrows"> Buschige Augenbrauen </string> @@ -2256,6 +2373,9 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ <string name="Butt Size"> Hintern, Größe </string> + <string name="Butt Gravity"> + Po – Schwerkraft + </string> <string name="bustle skirt"> Tournürenrock </string> @@ -3764,6 +3884,9 @@ Missbrauchsbericht <string name="New Tattoo"> Neue Tätowierung </string> + <string name="New Physics"> + Neue Physik + </string> <string name="Invalid Wearable"> Ungültiges Objekt </string> diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml index babbf0f5ca4c9a80d00aaf0b7b5e0550e84f4fa4..92001534e7e349d0586788069eb061fe5191c27d 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml @@ -34,7 +34,7 @@ layout="topleft" name="contains_text" width="276"> - [NAME] contains: + <nolink>[NAME]</nolink> contains: </text> <scroll_list background_visible="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index ed7de6a19f1de075bd83a04304253185c3f7ca50..2335ab3c11378865d7dce904c6e767c176807a66 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7232,6 +7232,49 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' yestext="Quit" notext="Don't Quit"/> </notification> + + <notification + name="NoInventory" + label="" + type="alertmodal" + unique="true"> + <tag>fail</tag> + <tag>confirm</tag> + Viewing inventory is only available in Advanced mode. Would you like to logout and change modes? + <usetemplate + name="okcancelbuttons" + yestext="Quit" + notext="Don't Quit"/> + </notification> + + <notification + name="NoAppearance" + label="" + type="alertmodal" + unique="true"> + <tag>fail</tag> + <tag>confirm</tag> + The appearance editor is only available in Advanced mode. Would you like to logout and change modes? + <usetemplate + name="okcancelbuttons" + yestext="Quit" + notext="Don't Quit"/> + </notification> + + <notification + name="NoSearch" + label="" + type="alertmodal" + unique="true"> + <tag>fail</tag> + <tag>confirm</tag> + Search is only available in Advanced mode. Would you like to logout and change modes? + <usetemplate + name="okcancelbuttons" + yestext="Quit" + notext="Don't Quit"/> + </notification> + </global> <global name="UnsupportedGLRequirements"> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index a92cc886e733563922160887dd8e1d1278ce0744..a6e5e7a219495e5906a385a953bc5dd4969ad57f 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -5,121 +5,121 @@ bg_opaque_color="DkGray" chrome="true" follows="left|bottom|right" - focus_root="true" + focus_root="true" height="33" layout="topleft" left="0" name="bottom_tray" top="28" width="1310"> - <string + <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off" /> - <string + <string name="SpeakBtnToolTip" value="Turns microphone on/off" /> - <string + <string name="VoiceControlBtnToolTip" value="Shows/hides voice control panel" /> - <layout_stack + <layout_stack border_size="0" clip="false" follows="all" height="28" - layout="topleft" - left="0" + layout="topleft" + left="0" mouse_opaque="false" name="toolbar_stack" orientation="horizontal" top="0" width="1310"> - <layout_panel + <layout_panel auto_resize="false" - user_resize="false" + user_resize="false" min_width="2" width="2" /> - <layout_panel + <layout_panel auto_resize="false" layout="topleft" max_width="320" min_width="214" - height="28" + height="28" mouse_opaque="false" - name="chat_bar_layout_panel" + name="chat_bar_layout_panel" user_resize="true" - width="310" > + width="250" > <panel name="chat_bar" filename="panel_nearby_chat_bar.xml" left="0" height="28" - width="308" + width="248" top="0" mouse_opaque="false" follows="left|right" /> - </layout_panel> - <!-- + </layout_panel> + <!-- This 5px Panel is an indicator of where the resize handle is. The panel provides a gap between the resize handle icon and a button to the right. --> - <layout_panel - auto_resize="false" - layout="topleft" - max_width="5" - min_width="5" - name="chat_bar_resize_handle_panel" - user_resize="false" - width="5"> - <icon - follows="top|right" - height="25" - image_name="ChatBarHandle" - layout="topleft" - left="-7" - name="resize_handle" - top="4" - width="5" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="left|right" - height="28" - layout="topleft" - min_height="28" - min_width="59" - mouse_opaque="false" - name="speak_panel" - top_delta="0" - user_resize="false" - width="108"> - <talk_button - follows="left|right" - height="23" - layout="topleft" - left="0" - name="talk" - top="5" - width="105"> - <show_button - tab_stop="true"> - <init_callback - function="Button.SetDockableFloaterToggle" - parameter="voice_controls" /> - </show_button> - <!-- do not remove halign attribute with default value. otherwise it can't be overridden in other locales. + <layout_panel + auto_resize="false" + layout="topleft" + max_width="5" + min_width="5" + name="chat_bar_resize_handle_panel" + user_resize="false" + width="5"> + <icon + follows="top|right" + height="25" + image_name="ChatBarHandle" + layout="topleft" + left="-7" + name="resize_handle" + top="4" + width="5" /> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="59" + mouse_opaque="false" + name="speak_panel" + top_delta="0" + user_resize="false" + width="108"> + <talk_button + follows="left|right" + height="23" + layout="topleft" + left="0" + name="talk" + top="5" + width="105"> + <show_button + tab_stop="true"> + <init_callback + function="Button.SetDockableFloaterToggle" + parameter="voice_controls" /> + </show_button> + <!-- do not remove halign attribute with default value. otherwise it can't be overridden in other locales. & pad_right is default value for long label which can be right aligned. See EXT-6318 --> - <speak_button - halign="center" - label="Speak" - label_selected="Speak" - name="speak_btn" - pad_right="20" - tab_stop="true" - use_ellipses="true" /> - </talk_button> - </layout_panel> - <layout_panel + <speak_button + halign="center" + label="Speak" + label_selected="Speak" + name="speak_btn" + pad_right="20" + tab_stop="true" + use_ellipses="true" /> + </talk_button> + </layout_panel> + <layout_panel auto_resize="false" follows="right" height="28" @@ -131,7 +131,7 @@ top_delta="0" user_resize="false" width="85"> - <gesture_combo_list + <gesture_combo_list follows="left|right" height="23" label="Gesture" @@ -141,46 +141,46 @@ tool_tip="Shows/hides gestures" top="5" width="82"> - <combo_button + <combo_button pad_right="10" use_ellipses="true" /> - <combo_list + <combo_list page_lines="17" /> - </gesture_combo_list> - </layout_panel> - <layout_panel + </gesture_combo_list> + </layout_panel> + <layout_panel auto_resize="false" - follows="right" - height="28" - layout="topleft" - min_height="28" - min_width="52" - mouse_opaque="false" - name="movement_panel" - user_resize="false" - width="83"> - <bottomtray_button - follows="left|right" - height="23" - image_pressed="PushButton_Press" - image_pressed_selected="PushButton_Selected_Press" - image_selected="PushButton_Selected_Press" - is_toggle="true" - label="Move" - layout="topleft" - name="movement_btn" - tool_tip="Shows/hides movement controls" - top="5" - use_ellipses="true" - width="80"> - <init_callback - function="Button.SetDockableFloaterToggle" - parameter="moveview" /> - </bottomtray_button> + follows="right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="movement_panel" + user_resize="false" + width="83"> + <bottomtray_button + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Move" + layout="topleft" + name="movement_btn" + tool_tip="Shows/hides movement controls" + top="5" + use_ellipses="true" + width="80"> + <init_callback + function="Button.SetDockableFloaterToggle" + parameter="moveview" /> + </bottomtray_button> - </layout_panel> - <layout_panel - auto_resize="false" + </layout_panel> + <layout_panel + auto_resize="false" follows="left|right" height="28" layout="topleft" @@ -190,7 +190,7 @@ name="cam_panel" user_resize="false" width="83"> - <bottomtray_button + <bottomtray_button follows="left|right" height="23" image_pressed="PushButton_Press" @@ -205,83 +205,83 @@ top="5" use_ellipses="true" width="80"> - <init_callback + <init_callback function="Button.SetDockableFloaterToggle" parameter="camera" /> - </bottomtray_button> - </layout_panel> - <layout_panel + </bottomtray_button> + </layout_panel> + <layout_panel auto_resize="false" follows="left|right" height="28" layout="topleft" - min_width="40" - mouse_opaque="false" - name="snapshot_panel" - user_resize="false" - width="39"> - <bottomtray_button - follows="left|right" - height="23" - image_overlay="Snapshot_Off" - image_pressed="PushButton_Press" - image_pressed_selected="PushButton_Selected_Press" - image_selected="PushButton_Selected_Press" - is_toggle="true" - layout="topleft" - left="0" - name="snapshots" - tool_tip="Take snapshot" - top="5" - width="36"> - <init_callback - function="Button.SetFloaterToggle" - parameter="snapshot" /> - </bottomtray_button> - </layout_panel> - <layout_panel - auto_resize="false" - follows="left|right" - height="28" - layout="topleft" - min_height="28" - min_width="52" - mouse_opaque="false" - name="build_btn_panel" - user_resize="false" - width="83"> -<!--*FIX: Build Floater is not opened with default registration. Will be fixed soon. + min_width="40" + mouse_opaque="false" + name="snapshot_panel" + user_resize="false" + width="39"> + <bottomtray_button + follows="left|right" + height="23" + image_overlay="Snapshot_Off" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + layout="topleft" + left="0" + name="snapshots" + tool_tip="Take snapshot" + top="5" + width="36"> + <init_callback + function="Button.SetFloaterToggle" + parameter="snapshot" /> + </bottomtray_button> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="build_btn_panel" + user_resize="false" + width="83"> + <!--*FIX: Build Floater is not opened with default registration. Will be fixed soon. Disabled for now. --> - <bottomtray_button - follows="left|right" - height="23" - image_pressed="PushButton_Press" - image_pressed_selected="PushButton_Selected_Press" - image_selected="PushButton_Selected_Press" - is_toggle="true" - label="Build" - layout="topleft" - left="0" - name="build_btn" - tool_tip="Shows/hides Build Tools" - top="5" - use_ellipses="true" - width="80"> - <commit_callback - function="Build.Toggle" - parameter="build" /> - </bottomtray_button> - </layout_panel> - <layout_panel - auto_resize="false" - follows="left|right" - height="28" - layout="topleft" + <bottomtray_button + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Build" + layout="topleft" + left="0" + name="build_btn" + tool_tip="Shows/hides Build Tools" + top="5" + use_ellipses="true" + width="80"> + <commit_callback + function="Build.Toggle" + parameter="build" /> + </bottomtray_button> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" min_height="28" - min_width="52" + min_width="52" mouse_opaque="false" - name="search_btn_panel" + name="search_btn_panel" user_resize="false" width="83"> <bottomtray_button @@ -341,7 +341,7 @@ Disabled for now. height="28" layout="topleft" min_height="28" - min_width="52" + min_width="62" mouse_opaque="false" name="mini_map_btn_panel" user_resize="false" @@ -378,7 +378,7 @@ Disabled for now. width="189"> <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. EXT-991--> - <chiclet_panel + <chiclet_panel chiclet_padding="4" follows="left|right" height="24" @@ -389,7 +389,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. name="chiclet_list" top="7" width="189"> - <button + <button auto_resize="true" follows="right" height="29" @@ -406,7 +406,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. top="-28" visible="false" width="7" /> - <button + <button auto_resize="true" follows="right" height="29" @@ -423,13 +423,13 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. top="-28" visible="false" width="7" /> - </chiclet_panel> - </layout_panel> - <layout_panel auto_resize="false" - user_resize="false" + </chiclet_panel> + </layout_panel> + <layout_panel auto_resize="false" + user_resize="false" width="4" min_width="4"/> - <layout_panel + <layout_panel auto_resize="false" follows="right" height="28" @@ -440,7 +440,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. top="0" user_resize="false" width="37"> - <chiclet_im_well + <chiclet_im_well follows="right" height="28" layout="topleft" @@ -449,7 +449,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. name="im_well" top="0" width="35"> - <!-- + <!-- Emulate 4 states of button by background images, see details in EXT-3147. The same should be for notification_well button xml attribute Description image_unselected "Unlit" - there are no new messages @@ -457,7 +457,7 @@ image_selected "Unlit" + "Selected" - there are no new messages and the image_pressed "Lit" - there are new messages image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open --> - <button + <button auto_resize="true" follows="right" halign="center" @@ -472,13 +472,13 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well name="Unread IM messages" tool_tip="Conversations" width="34"> - <init_callback + <init_callback function="Button.SetDockableFloaterToggle" parameter="im_well_window" /> - </button> - </chiclet_im_well> - </layout_panel> - <layout_panel + </button> + </chiclet_im_well> + </layout_panel> + <layout_panel auto_resize="false" follows="right" height="28" @@ -489,7 +489,7 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well top="0" user_resize="false" width="37"> - <chiclet_notification + <chiclet_notification follows="right" height="23" layout="topleft" @@ -498,7 +498,7 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well name="notification_well" top="5" width="35"> - <button + <button auto_resize="true" bottom_pad="3" follows="right" @@ -514,17 +514,17 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well name="Unread" tool_tip="Notifications" width="34"> - <init_callback + <init_callback function="Button.SetDockableFloaterToggle" parameter="notification_well_window" /> - </button> - </chiclet_notification> - </layout_panel> - <layout_panel - auto_resize="false" - user_resize="false" - min_width="4" - name="DUMMY2" - width="8" /> - </layout_stack> + </button> + </chiclet_notification> + </layout_panel> + <layout_panel + auto_resize="false" + user_resize="false" + min_width="4" + name="DUMMY2" + width="8" /> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2175db649cca4192424ffe6d64c66d9a1b0acc63..2eb3cd73974e990eb185fe815d294ad93502f18c 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3216,6 +3216,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. The session initialization is timed out </string> + <string name="Home position set.">Home position set.</string> + <string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string> <!-- Financial operations strings --> diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml index a1e32e44de6deaf02472939d0b6843685466c1f2..4d69dda7eb4457d0cd3793744ef3691502097fb8 100644 --- a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml +++ b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <avatar_icon + name="avatar_icon" default_icon_name="Generic_Person_Large" use_draw_context_alpha="false"> </avatar_icon> diff --git a/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml b/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml index 6040d2412851b2ee21fd593dd4fcfc4afa024983..ea1d89c975c4eaed5802c8b93e46c75285193fb0 100644 --- a/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml +++ b/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml @@ -3,6 +3,20 @@ follows="left|top" mouse_opaque="false" name="loading_indicator" - rotations_per_sec="1.0" - tab_stop="false" -/> + images_per_sec="1.0" + tab_stop="false"> + <images> + <image name="Progress_1"/> + <image name="Progress_2"/> + <image name="Progress_3"/> + <image name="Progress_4"/> + <image name="Progress_5"/> + <image name="Progress_6"/> + <image name="Progress_7"/> + <image name="Progress_8"/> + <image name="Progress_9"/> + <image name="Progress_10"/> + <image name="Progress_11"/> + <image name="Progress_12"/> + </images> +</loading_indicator> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml index 830ea12e414b415e78ab31cba10230b36e5cc061..e6d4bff8b57521b3bd0b4ebf65753607cb369b8b 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml @@ -6,20 +6,24 @@ track_color="ScrollbarTrackColor" thumb_color="ScrollbarThumbColor" thickness="15"> - <up_button image_unselected="ScrollArrow_Up" + <up_button name="up_button" + image_unselected="ScrollArrow_Up" image_selected="ScrollArrow_Up" scale_image="true" hover_glow_amount="0.35"/> - <down_button image_unselected="ScrollArrow_Down" + <down_button name="down_button" + image_unselected="ScrollArrow_Down" image_selected="ScrollArrow_Down" scale_image="true" hover_glow_amount="0.35"/> - <left_button image_unselected="ScrollArrow_Left" + <left_button name="left_button" + image_unselected="ScrollArrow_Left" image_selected="ScrollArrow_Left" scale_image="true" hover_glow_amount="0.35"/> - <right_button image_unselected="ScrollArrow_Right" - image_selected="ScrollArrow_Right" - scale_image="true" - hover_glow_amount="0.35"/> + <right_button name="right_button" + image_unselected="ScrollArrow_Right" + image_selected="ScrollArrow_Right" + scale_image="true" + hover_glow_amount="0.35"/> </scroll_bar> diff --git a/indra/newview/skins/default/xui/es/floater_beacons.xml b/indra/newview/skins/default/xui/es/floater_beacons.xml index b86967755cbfd95c5e5c28fb22c86904b3e9637e..49f990c84d9764783c2dab29d952d436c7a1a907 100644 --- a/indra/newview/skins/default/xui/es/floater_beacons.xml +++ b/indra/newview/skins/default/xui/es/floater_beacons.xml @@ -17,5 +17,6 @@ <check_box label="Sólo tocar" name="touch_only"/> <check_box label="Origen de sonidos" name="sounds"/> <check_box label="Origen de partÃculas" name="particles"/> + <check_box label="Fuentes de media" name="moapbeacon"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/es/menu_avatar_self.xml b/indra/newview/skins/default/xui/es/menu_avatar_self.xml index a2d86d78c13bb6b465492aa166b186d18808df2b..268d6f70ab434317a4de4d26e01ac7657ceec631 100644 --- a/indra/newview/skins/default/xui/es/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/es/menu_avatar_self.xml @@ -14,6 +14,7 @@ <menu_item_call label="Camiseta" name="Self Undershirt"/> <menu_item_call label="Ropa interior" name="Self Underpants"/> <menu_item_call label="Tatuaje" name="Self Tattoo"/> + <menu_item_call label="FÃsica" name="Self Physics"/> <menu_item_call label="Alfa" name="Self Alpha"/> <menu_item_call label="Toda la ropa" name="All Clothes"/> </context_menu> diff --git a/indra/newview/skins/default/xui/es/menu_bottomtray.xml b/indra/newview/skins/default/xui/es/menu_bottomtray.xml index a16da5ae9e2555243a57d8f74c9128fbfc9a753c..40058a17499996be245b2525737476ff21591896 100644 --- a/indra/newview/skins/default/xui/es/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/es/menu_bottomtray.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="hide_camera_move_controls_menu"> - <menu_item_check label="Voz activada" name="EnableVoiceChat"/> + <menu_item_check label="Botón Hablar" name="EnableVoiceChat"/> <menu_item_check label="Botón Gestos" name="ShowGestureButton"/> <menu_item_check label="Botón Moverse" name="ShowMoveButton"/> <menu_item_check label="Botón Vista" name="ShowCameraButton"/> diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml index 94ee162bbce5d671111c5360368bea4cde4d5280..e873d3158039f5dc706f7ac87ccf832848611d96 100644 --- a/indra/newview/skins/default/xui/es/menu_inventory.xml +++ b/indra/newview/skins/default/xui/es/menu_inventory.xml @@ -25,6 +25,7 @@ <menu_item_call label="Ropa interior nueva" name="New Underpants"/> <menu_item_call label="Nueva capa Alpha" name="New Alpha Mask"/> <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/> + <menu_item_call label="Nueva fÃsica" name="New Physics"/> </menu> <menu label="Nuevas partes del cuerpo" name="New Body Parts"> <menu_item_call label="Forma nueva" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/es/menu_inventory_add.xml b/indra/newview/skins/default/xui/es/menu_inventory_add.xml index ba106e8335d9133911b3d6e15c0a3c408fdf0338..615a1a09b7e61728a128749460a8c83b945d03c7 100644 --- a/indra/newview/skins/default/xui/es/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/es/menu_inventory_add.xml @@ -23,6 +23,7 @@ <menu_item_call label="Ropa interior nueva" name="New Underpants"/> <menu_item_call label="Nueva Alfa" name="New Alpha"/> <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/> + <menu_item_call label="Nueva fÃsica" name="New Physics"/> </menu> <menu label="Nuevas partes del cuerpo" name="New Body Parts"> <menu_item_call label="Forma nueva" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/es/menu_media_ctrl.xml b/indra/newview/skins/default/xui/es/menu_media_ctrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ea9286d8e9e0bf6ba34e66cab1fd3baa301bea5 --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_media_ctrl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="media ctrl context menu"> + <menu_item_call label="Cortar" name="Cut"/> + <menu_item_call label="Copiar" name="Copy"/> + <menu_item_call label="Pegar" name="Paste"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/es/menu_outfit_gear.xml b/indra/newview/skins/default/xui/es/menu_outfit_gear.xml index 3b11bceecf6b7be459843d09a04ba63a3205df93..558ff6afd3cea6701e51c9f2e909dfec28a0b366 100644 --- a/indra/newview/skins/default/xui/es/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/es/menu_outfit_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="Gear Outfit"> +<toggleable_menu name="Gear Outfit"> <menu_item_call label="Ponerme - Reemplazar el vestuario actual" name="wear"/> <menu_item_call label="Ponerme - Añadir al vestuario actual" name="wear_add"/> <menu_item_call label="Quitarme - Quitar del vestuario actual" name="take_off"/> @@ -14,6 +14,7 @@ <menu_item_call label="Camiseta nueva" name="New Undershirt"/> <menu_item_call label="Ropa interior nueva" name="New Underpants"/> <menu_item_call label="Nueva Alfa" name="New Alpha"/> + <menu_item_call label="Nueva fÃsica" name="New Physics"/> <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/> </menu> <menu label="Nuevas partes del cuerpo" name="New Body Parts"> @@ -24,4 +25,4 @@ </menu> <menu_item_call label="Renombrar el vestuario" name="rename"/> <menu_item_call label="Borrar el vestuario" name="delete_outfit"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index c48203f95c93b9a40ba2ca162feffed569fa6633..138bbd941214774c9d1225bb59ca2a26e83fedb8 100644 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -336,4 +336,9 @@ </menu> <menu_item_call label="God Tools" name="God Tools"/> </menu> + <menu label="Admin" name="Deprecated"> + <menu label="Take Off Clothing" name="Take Off Clothing"> + <menu_item_call label="FÃsica" name="Physics"/> + </menu> + </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 1379f710c31fac20d37d369fca82784fc88b823b..91a03023a1bc6e0dc0c78b9eeaff980fbeec7731 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2841,6 +2841,13 @@ Si lo haces, todos los residentes que se unan posteriormente a la llamada tambi <notification label="Levantarme" name="HintSit"> Para levantarte y salir de la posición de sentado, haz clic en el botón Levantarme. </notification> + <notification label="Hablar" name="HintSpeak"> + Pulsa en el botón: Hablar para conectar y desconectar el micrófono. + +Pulsa en el cursor arriba para ver el panel de control de voz. + +Al ocultar el botón Hablar se desactiva la función de voz. + </notification> <notification label="Explora el mundo" name="HintDestinationGuide"> La GuÃa de destinos contiene miles de nuevos lugares por descubrir. Selecciona una ubicación y elige Teleportarme para iniciar la exploración. </notification> @@ -2850,12 +2857,14 @@ Si lo haces, todos los residentes que se unan posteriormente a la llamada tambi <notification label="Mover" name="HintMove"> Si deseas caminar o correr, abre el panel Mover y utiliza las flechas de dirección para navegar. También puedes utilizar las flechas de dirección del teclado. </notification> + <notification label="" name="HintMoveClick"> + 1. Pulsa para caminar: Pulsa en cualquier punto del terreno para ir a él. + +2. Pulsa y arrastra para girar la vista: Pulsa y arrastra el cursor a cualquier parte del mundo para girar la vista. + </notification> <notification label="Nombre mostrado" name="HintDisplayName"> Configura y personaliza aquà tu nombre mostrado. Esto se añadirá a tu nombre de usuario personal, que no puedes modificar. Puedes cambiar la manera en que ves los nombres de otras personas en tus preferencias. </notification> - <notification label="Mover" name="HintMoveArrows"> - Para caminar, utiliza las flechas de dirección del teclado. Para correr, pulsa dos veces la flecha hacia arriba. - </notification> <notification label="Visión" name="HintView"> Para cambiar la vista de la cámara, utiliza los controles Orbital y Panorámica. Para restablecer tu vista, pulsa Esc o camina. </notification> diff --git a/indra/newview/skins/default/xui/es/panel_edit_physics.xml b/indra/newview/skins/default/xui/es/panel_edit_physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfb5ab330a4cd639e1fa5927d6d6262c41ee2d3d --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_edit_physics.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="edit_physics_panel"> + <panel label="" name="accordion_panel"> + <accordion name="physics_accordion"> + <accordion_tab name="physics_breasts_updown_tab" title="Rebote de los senos"/> + <accordion_tab name="physics_breasts_inout_tab" title="Canalillo de los senos"/> + <accordion_tab name="physics_breasts_leftright_tab" title="Bamboleo de los senos"/> + <accordion_tab name="physics_belly_tab" title="Rebote de la barriga"/> + <accordion_tab name="physics_butt_tab" title="Rebote del culo"/> + <accordion_tab name="physics_butt_leftright_tab" title="Bamboleo del culo"/> + <accordion_tab name="physics_advanced_tab" title="Parámetros avanzados"/> + </accordion> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_edit_wearable.xml b/indra/newview/skins/default/xui/es/panel_edit_wearable.xml index 15c683f3756ad90a240e7837a8670a790d42a2c5..799512968d13c357cce453ec854f45e8f13b3793 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_wearable.xml @@ -45,6 +45,9 @@ <string name="edit_tattoo_title"> Modificando los tatuajes </string> + <string name="edit_physics_title"> + Modificar la fÃsica + </string> <string name="shape_desc_text"> AnatomÃa: </string> @@ -90,6 +93,9 @@ <string name="tattoo_desc_text"> Tatuaje: </string> + <string name="physics_desc_text"> + FÃsica: + </string> <labeled_back_button label="Guardar" name="back_btn" tool_tip="Regresar a Editar el vestuario"/> <text name="edit_wearable_title" value="Modificando la anatomÃa"/> <panel label="Camisa" name="wearable_type_panel"> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml index aba85f9ff1a37c2ee454995a49ee7d4246b5eccc..f7bc1f6aadc0675afd8f19d2155d388e6628a339 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml @@ -30,7 +30,9 @@ <spinner label="Duración de los interlocutores favoritos:" name="nearby_toasts_lifetime"/> <spinner label="Tiempo de los otros interlocutores:" name="nearby_toasts_fadingtime"/> <check_box name="translate_chat_checkbox"/> - <text name="translate_chb_label" >Usar la traducción automática (con Google) en el chat</text> + <text name="translate_chb_label"> + Utiliza la herramienta de traducción automática mientras utilizas el chat (mediante Google) + </text> <text name="translate_language_text"> Traducir el chat al: </text> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_colors.xml b/indra/newview/skins/default/xui/es/panel_preferences_colors.xml index edd417d564463ddcd4e2b967c3a75b3e42d0e883..a7fb2d9af858d00003d2d6561ab9eb22280fd1a5 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_colors.xml @@ -26,13 +26,13 @@ Propietario </text> <text name="text_box9"> - URL + URLs </text> <text name="bubble_chat"> - Color de fondo de la etiqueta del nombre (afectará también a los bocadillos del chat): + Color de fondo de las etiquetas de nombre (también se aplica a los bocadillos del chat): </text> - <color_swatch name="background" tool_tip="Seleccionar el color de la etiqueta del nombre"/> - <slider label="Opacidad:" name="bubble_chat_opacity" tool_tip="Seleccionar opacidad de la etiqueta del nombre"/> + <color_swatch name="background" tool_tip="Elige el color de las etiquetas de nombre"/> + <slider label="Opacidad:" name="bubble_chat_opacity" tool_tip="Elige la opacidad de las etiquetas de nombre"/> <text name="floater_opacity"> Opacidad de la ventana: </text> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml index c569db33762c20a79cfdfe936485abdf6ebbc2be..1ae5d63acedba190ef0923e45b0a4f1a86334bec 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml @@ -39,6 +39,10 @@ <combo_box.item label="Todos los avatares y objetos" name="3"/> <combo_box.item label="Todo" name="4"/> </combo_box> + <slider label="FÃsica del avatar:" name="AvatarPhysicsDetail"/> + <text name="AvatarPhysicsDetailText"> + Bajo + </text> <slider label="Distancia de dibujo:" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> m diff --git a/indra/newview/skins/default/xui/es/panel_preferences_sound.xml b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml index 2bc82307a8f26eaf963f1cf061b3719626d05ae8..8ce8e23138485e5a0930d7ec60e0fa2851c8edd5 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml @@ -5,7 +5,9 @@ </panel.string> <slider label="Volumen general" name="System Volume"/> <check_box initial_value="true" name="mute_when_minimized"/> - <text name="mute_chb_label">Silenciar cuando minimice</text> + <text name="mute_chb_label"> + Silenciar cuando minimice + </text> <slider label="Botones" name="UI Volume"/> <slider label="Ambiental" name="Wind Volume"/> <slider label="Efectos de sonido" name="SFX Volume"/> diff --git a/indra/newview/skins/default/xui/es/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/es/panel_scrolling_param_base.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa659040eaa57c1c5e325093dcc427058ea160b3 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_scrolling_param_base.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="LLScrollingPanelParamBase"> + <slider label="[DESC]" name="param slider"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index cd1fb767c860adcf05f895d4cb58d0a3a60b6829..75126e74c569a16fc8c1017a027667723e219bc6 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -855,6 +855,9 @@ <string name="tattoo"> Tatuaje </string> + <string name="physics"> + FÃsica + </string> <string name="invalid"> inválido/a </string> @@ -894,6 +897,9 @@ <string name="tattoo_not_worn"> Tatuaje no puesto </string> + <string name="physics_not_worn"> + FÃsica no puesta + </string> <string name="invalid_not_worn"> no válido/a </string> @@ -942,6 +948,9 @@ <string name="create_new_tattoo"> Crear un tatuaje nuevo </string> + <string name="create_new_physics"> + Crear nueva fÃsica + </string> <string name="create_new_invalid"> no válido/a </string> @@ -2178,6 +2187,114 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. <string name="Bulbous Nose"> Nariz de porra </string> + <string name="Breast Physics Mass"> + Masa del busto + </string> + <string name="Breast Physics Smoothing"> + Suavizado del busto + </string> + <string name="Breast Physics Gravity"> + Gravedad del busto + </string> + <string name="Breast Physics Drag"> + Aerodinámica del busto + </string> + <string name="Breast Physics InOut Max Effect"> + Efecto máx. + </string> + <string name="Breast Physics InOut Spring"> + Elasticidad + </string> + <string name="Breast Physics InOut Gain"> + Ganancia + </string> + <string name="Breast Physics InOut Damping"> + Amortiguación + </string> + <string name="Breast Physics UpDown Max Effect"> + Efecto máx. + </string> + <string name="Breast Physics UpDown Spring"> + Elasticidad + </string> + <string name="Breast Physics UpDown Gain"> + Ganancia + </string> + <string name="Breast Physics UpDown Damping"> + Amortiguación + </string> + <string name="Breast Physics LeftRight Max Effect"> + Efecto máx. + </string> + <string name="Breast Physics LeftRight Spring"> + Elasticidad + </string> + <string name="Breast Physics LeftRight Gain"> + Ganancia + </string> + <string name="Breast Physics LeftRight Damping"> + Amortiguación + </string> + <string name="Belly Physics Mass"> + Masa de la barriga + </string> + <string name="Belly Physics Smoothing"> + Suavizado de la barriga + </string> + <string name="Belly Physics Gravity"> + Gravedad de la barriga + </string> + <string name="Belly Physics Drag"> + Aerodinámica de la barriga + </string> + <string name="Belly Physics UpDown Max Effect"> + Efecto máx. + </string> + <string name="Belly Physics UpDown Spring"> + Elasticidad + </string> + <string name="Belly Physics UpDown Gain"> + Ganancia + </string> + <string name="Belly Physics UpDown Damping"> + Amortiguación + </string> + <string name="Butt Physics Mass"> + Masa del culo + </string> + <string name="Butt Physics Smoothing"> + Suavizado del culo + </string> + <string name="Butt Physics Gravity"> + Gravedad del culo + </string> + <string name="Butt Physics Drag"> + Aerodinámica del culo + </string> + <string name="Butt Physics UpDown Max Effect"> + Efecto máx. + </string> + <string name="Butt Physics UpDown Spring"> + Elasticidad + </string> + <string name="Butt Physics UpDown Gain"> + Ganancia + </string> + <string name="Butt Physics UpDown Damping"> + Amortiguación + </string> + <string name="Butt Physics LeftRight Max Effect"> + Efecto máx. + </string> + <string name="Butt Physics LeftRight Spring"> + Elasticidad + </string> + <string name="Butt Physics LeftRight Gain"> + Ganancia + </string> + <string name="Butt Physics LeftRight Damping"> + Amortiguación + </string> <string name="Bushy Eyebrows"> Cejijuntas </string> @@ -2187,6 +2304,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. <string name="Butt Size"> Culo: tamaño </string> + <string name="Butt Gravity"> + Gravedad del culo + </string> <string name="bustle skirt"> Polisón </string> @@ -3662,6 +3782,9 @@ Denuncia de infracción <string name="New Tattoo"> Tatuaje nuevo </string> + <string name="New Physics"> + Nueva fÃsica + </string> <string name="Invalid Wearable"> No se puede poner </string> diff --git a/indra/newview/skins/default/xui/fr/floater_beacons.xml b/indra/newview/skins/default/xui/fr/floater_beacons.xml index d61115a2db42e147d197b6a324c6ab1dda55bb74..ebd4dab683ccd2fc13ed814362d58ab987670419 100644 --- a/indra/newview/skins/default/xui/fr/floater_beacons.xml +++ b/indra/newview/skins/default/xui/fr/floater_beacons.xml @@ -17,5 +17,6 @@ <check_box label="Toucher uniquement" name="touch_only"/> <check_box label="Sources sonores" name="sounds"/> <check_box label="Sources des particules" name="particles"/> + <check_box label="Sources des médias" name="moapbeacon"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/fr/menu_avatar_self.xml b/indra/newview/skins/default/xui/fr/menu_avatar_self.xml index 21528cd43b5cce2e6fad10f45ce1d38a632d1864..6310a2177a8bbbd703cc56db791f59f631157cd4 100644 --- a/indra/newview/skins/default/xui/fr/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/fr/menu_avatar_self.xml @@ -14,6 +14,7 @@ <menu_item_call label="Débardeur" name="Self Undershirt"/> <menu_item_call label="Caleçon" name="Self Underpants"/> <menu_item_call label="Tatouage" name="Self Tattoo"/> + <menu_item_call label="Propriétés physiques" name="Self Physics"/> <menu_item_call label="Alpha" name="Self Alpha"/> <menu_item_call label="Tous les habits" name="All Clothes"/> </context_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_bottomtray.xml b/indra/newview/skins/default/xui/fr/menu_bottomtray.xml index ddaea517fce639e6c34e88b510afb61829e1b5cf..d0d245b2869e126e3f6d40ce6e7a214822bff1db 100644 --- a/indra/newview/skins/default/xui/fr/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/fr/menu_bottomtray.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="hide_camera_move_controls_menu"> - <menu_item_check label="Voix activée" name="EnableVoiceChat"/> + <menu_item_check label="Bouton Parler" name="EnableVoiceChat"/> <menu_item_check label="Bouton Geste" name="ShowGestureButton"/> <menu_item_check label="Bouton Bouger" name="ShowMoveButton"/> <menu_item_check label="Bouton Affichage" name="ShowCameraButton"/> diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml index a2279cf0ac4d91bed37ec79746a998c2042a46ca..fa0e264d14ff052028c83ed80ae8b669daf675ac 100644 --- a/indra/newview/skins/default/xui/fr/menu_inventory.xml +++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml @@ -25,6 +25,7 @@ <menu_item_call label="Nouveau caleçon" name="New Underpants"/> <menu_item_call label="Nouveau masque alpha" name="New Alpha Mask"/> <menu_item_call label="Nouveau tatouage" name="New Tattoo"/> + <menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/> </menu> <menu label="Nouvelles parties du corps" name="New Body Parts"> <menu_item_call label="Nouvelle silhouette" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/fr/menu_inventory_add.xml b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml index fe096b4a7e1d3ab0287787a7e70a60be241e443b..5d2b554dc352f89394bf96a5034e15ebba246224 100644 --- a/indra/newview/skins/default/xui/fr/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml @@ -23,6 +23,7 @@ <menu_item_call label="Nouveau caleçon" name="New Underpants"/> <menu_item_call label="Nouvel alpha" name="New Alpha"/> <menu_item_call label="Nouveau tatouage" name="New Tattoo"/> + <menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/> </menu> <menu label="Nouvelles parties du corps" name="New Body Parts"> <menu_item_call label="Nouvelle silhouette" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/fr/menu_media_ctrl.xml b/indra/newview/skins/default/xui/fr/menu_media_ctrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..787a5b3af2f1ac52d97826aebd08a6285ceed908 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_media_ctrl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="media ctrl context menu"> + <menu_item_call label="Couper" name="Cut"/> + <menu_item_call label="Copier" name="Copy"/> + <menu_item_call label="Coller" name="Paste"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml b/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml index 5db7f176b544ea9c137fb2d9ef559b394f389def..b5181f4f82efcb5213ebb781525cff7e1c83855c 100644 --- a/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="Gear Outfit"> +<toggleable_menu name="Gear Outfit"> <menu_item_call label="Porter - Remplacer la tenue actuelle" name="wear"/> <menu_item_call label="Porter - Ajouter à la tenue actuelle" name="wear_add"/> <menu_item_call label="Enlever - Supprimer de la tenue actuelle" name="take_off"/> @@ -14,6 +14,7 @@ <menu_item_call label="Nouveau débardeur" name="New Undershirt"/> <menu_item_call label="Nouveau caleçon" name="New Underpants"/> <menu_item_call label="Nouvel alpha" name="New Alpha"/> + <menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/> <menu_item_call label="Nouveau tatouage" name="New Tattoo"/> </menu> <menu label="Nouvelles parties du corps" name="New Body Parts"> @@ -24,4 +25,4 @@ </menu> <menu_item_call label="Renommer la tenue" name="rename"/> <menu_item_call label="Supprimer la tenue" name="delete_outfit"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index ee1ab8c60181afd649de7f21dfd6570fd816cd0b..1dd6da9d6fe4c3df8e4b3ca529ce7aa68c4bf502 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -412,6 +412,7 @@ <menu_item_call label="Jupe" name="Skirt"/> <menu_item_call label="Alpha" name="Alpha"/> <menu_item_call label="Tatouage" name="Tattoo"/> + <menu_item_call label="Propriétés physiques" name="Physics"/> <menu_item_call label="Tous les habits" name="All Clothes"/> </menu> <menu label="Aide" name="Help"> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index e984ea66ed2070ba90791d8addec90ce4fb98355..78890caabb1baacd2a9693261c160373a8a4e1ac 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2838,6 +2838,13 @@ Ignorer les autres ? <notification label="Se lever" name="HintSit"> Pour passer d'une position assise à une position debout, cliquez sur le bouton Me lever. </notification> + <notification label="Parler" name="HintSpeak"> + Cliquez sur le bouton Parler pour activer/désactiver le micro. + +Cliquez sur la flèche vers le haut pour afficher le panneau de contrôle de la voix. + +Si vous masquez le bouton Parler, la fonction Voix sera désactivée. + </notification> <notification label="Explorer le monde" name="HintDestinationGuide"> Le Guide des destinations comprend des milliers d'endroits nouveaux à découvrir. Sélectionnez-en un, puis cliquez sur Téléporter pour commencer à l'explorer. </notification> @@ -2847,12 +2854,16 @@ Ignorer les autres ? <notification label="Bouger" name="HintMove"> Pour marcher ou courir, cliquez sur le bouton Bouger, puis naviguez à l'aide des flèches directionnelles. Vous pouvez également utiliser les touches fléchées de votre clavier. </notification> + <notification label="" name="HintMoveClick"> + 1. Cliquer pour marcher +Cliquez n'importe où sur le sol pour vous diriger vers ce point en marchant. + +2. Cliquer et faire glisser pour faire pivoter la vue +Cliquez sur un point dans le monde et faites glisser votre souris pour faire tourner la caméra. + </notification> <notification label="Nom d'affichage" name="HintDisplayName"> Définissez ici votre nom d'affichage personnalisable. Cette fonctionnalité vous est fournie en plus de votre nom d'utilisateur unique qui, lui, ne peut être changé. Vous pouvez modifier l'apparence des noms des autres résidents dans vos préférences. </notification> - <notification label="Bouger" name="HintMoveArrows"> - Pour marcher, utilisez les touches fléchées de votre clavier. Pour courir, appuyez deux fois sur la flèche vers le haut. - </notification> <notification label="Affichage" name="HintView"> Pour changer d'angle de vision, utilisez les contrôles Faire tourner et Faire un panoramique. Pour réinitialiser la vue, appuyez sur Échap ou marchez. </notification> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_physics.xml b/indra/newview/skins/default/xui/fr/panel_edit_physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..d79f7df90aa5f2344fe7335b343f5e3f6377aa71 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_edit_physics.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="edit_physics_panel"> + <panel label="" name="accordion_panel"> + <accordion name="physics_accordion"> + <accordion_tab name="physics_breasts_updown_tab" title="Rebond des seins"/> + <accordion_tab name="physics_breasts_inout_tab" title="Décolleté"/> + <accordion_tab name="physics_breasts_leftright_tab" title="Balancement des seins"/> + <accordion_tab name="physics_belly_tab" title="Rebond du ventre"/> + <accordion_tab name="physics_butt_tab" title="Rebond des fesses"/> + <accordion_tab name="physics_butt_leftright_tab" title="Balancement des fesses"/> + <accordion_tab name="physics_advanced_tab" title="Paramètres avancés"/> + </accordion> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml index d7a3d3bd852bedc6110c6751fa9cc8ea446b62c3..def158cf68446090f05a2fa0afdfb56af91111c3 100644 --- a/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml @@ -45,6 +45,9 @@ <string name="edit_tattoo_title"> Modification du tatouage </string> + <string name="edit_physics_title"> + Modification des propriétés physiques + </string> <string name="shape_desc_text"> Silhouette : </string> @@ -90,6 +93,9 @@ <string name="tattoo_desc_text"> Tatouage : </string> + <string name="physics_desc_text"> + Propriétés physiques : + </string> <labeled_back_button label="Enregistrer" name="back_btn" tool_tip="Revenir à Modifier la tenue"/> <text name="edit_wearable_title" value="Modification de la silhouette"/> <panel label="Chemise" name="wearable_type_panel"> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml index d5cecfc6982e103165dd72e3e5def7ff84f99eef..e9e6e6350fe759cef0115161879eb96073c350a0 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml @@ -30,7 +30,9 @@ <spinner label="Durée de vie du popup Chat près de moi :" name="nearby_toasts_lifetime"/> <spinner label="Disparition progressive du popup Chat près de moi :" name="nearby_toasts_fadingtime"/> <check_box name="translate_chat_checkbox"/> - <text name="translate_chb_label" >Utiliser la traduction automatique lors des chats (fournie par Google)</text> + <text name="translate_chb_label"> + Utiliser la traduction automatique lors des chats (fournie par Google) + </text> <text name="translate_language_text"> Traduire le chat en : </text> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_colors.xml b/indra/newview/skins/default/xui/fr/panel_preferences_colors.xml index 4e7d75e1b9d00b598dd48505e17905e8c2749226..abdffd232a3531ee8fb8617a0724b03ee55a464c 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_colors.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Couleurs" name="colors_panel"> <text name="effects_color_textbox"> - Mes effets (faisceau de sélection lumineux) : + Mes effets (faisceau de sélection) : </text> <color_swatch name="effect_color_swatch" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs."/> <text name="font_colors"> - Couleurs de la police du chat : + Couleurs pour le chat : </text> <text name="text_box1"> Moi diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml index c90edd443e6def6f434ac83c6c433bc27e734c3f..025a72a1d21454f6459620edc45c74d28f1d407d 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml @@ -39,6 +39,10 @@ <combo_box.item label="Tous les objets et avatars" name="3"/> <combo_box.item label="Tout" name="4"/> </combo_box> + <slider label="Propriétés physiques de l'avatar :" name="AvatarPhysicsDetail"/> + <text name="AvatarPhysicsDetailText"> + Faible + </text> <slider label="Limite d'affichage :" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> m @@ -77,7 +81,7 @@ Faible </text> <text name="AvatarRenderingText"> - Rendu de l'avatar : + Rendu de l'avatar : </text> <check_box initial_value="true" label="Avatars éloignés en 2D" name="AvatarImpostors"/> <check_box initial_value="true" label="Accélération du rendu" name="AvatarVertexProgram"/> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml b/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml index ac7f72d367db60fc82fcc6bdf69b8430ac9d223c..a404aae483f16c4fb303ec670332c0b317235fa4 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml @@ -5,7 +5,9 @@ </panel.string> <slider label="Volume principal" name="System Volume"/> <check_box initial_value="true" name="mute_when_minimized"/> - <text name="mute_chb_label">Couper quand minimisé</text> + <text name="mute_chb_label"> + Couper lorsque minimisé + </text> <slider label="Boutons" name="UI Volume"/> <slider label="Ambiant" name="Wind Volume"/> <slider label="Effets sonores" name="SFX Volume"/> diff --git a/indra/newview/skins/default/xui/fr/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/fr/panel_scrolling_param_base.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa659040eaa57c1c5e325093dcc427058ea160b3 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_scrolling_param_base.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="LLScrollingPanelParamBase"> + <slider label="[DESC]" name="param slider"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index a7c71dc0f0b00df328133549ba4dc7b63e15957c..a3369e6730fbde0c4bff6f02e8bf686a8337a2e9 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -876,6 +876,9 @@ <string name="tattoo"> Tatouage </string> + <string name="physics"> + Propriétés physiques + </string> <string name="invalid"> non valide </string> @@ -915,6 +918,9 @@ <string name="tattoo_not_worn"> Tatouage non porté </string> + <string name="physics_not_worn"> + Propriétés physiques non portées + </string> <string name="invalid_not_worn"> non valide </string> @@ -963,6 +969,9 @@ <string name="create_new_tattoo"> Créer un nouveau tatouage </string> + <string name="create_new_physics"> + Créer de nouvelles propriétés physiques + </string> <string name="create_new_invalid"> non valide </string> @@ -2247,6 +2256,114 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. <string name="Bulbous Nose"> Nez en bulbe </string> + <string name="Breast Physics Mass"> + Masse des seins + </string> + <string name="Breast Physics Smoothing"> + Lissage des seins + </string> + <string name="Breast Physics Gravity"> + Gravité des seins + </string> + <string name="Breast Physics Drag"> + Résistance de l'air sur les seins + </string> + <string name="Breast Physics InOut Max Effect"> + Effet max. + </string> + <string name="Breast Physics InOut Spring"> + Vibration + </string> + <string name="Breast Physics InOut Gain"> + Amplification + </string> + <string name="Breast Physics InOut Damping"> + Amortissement + </string> + <string name="Breast Physics UpDown Max Effect"> + Effet max. + </string> + <string name="Breast Physics UpDown Spring"> + Vibration + </string> + <string name="Breast Physics UpDown Gain"> + Amplification + </string> + <string name="Breast Physics UpDown Damping"> + Amortissement + </string> + <string name="Breast Physics LeftRight Max Effect"> + Effet max. + </string> + <string name="Breast Physics LeftRight Spring"> + Vibration + </string> + <string name="Breast Physics LeftRight Gain"> + Amplification + </string> + <string name="Breast Physics LeftRight Damping"> + Amortissement + </string> + <string name="Belly Physics Mass"> + Masse du ventre + </string> + <string name="Belly Physics Smoothing"> + Lissage du ventre + </string> + <string name="Belly Physics Gravity"> + Gravité du ventre + </string> + <string name="Belly Physics Drag"> + Résistance de l'air sur le ventre + </string> + <string name="Belly Physics UpDown Max Effect"> + Effet max. + </string> + <string name="Belly Physics UpDown Spring"> + Vibration + </string> + <string name="Belly Physics UpDown Gain"> + Amplification + </string> + <string name="Belly Physics UpDown Damping"> + Amortissement + </string> + <string name="Butt Physics Mass"> + Masse des fesses + </string> + <string name="Butt Physics Smoothing"> + Lissage des fesses + </string> + <string name="Butt Physics Gravity"> + Gravité des fesses + </string> + <string name="Butt Physics Drag"> + Résistance de l'air sur les fesses + </string> + <string name="Butt Physics UpDown Max Effect"> + Effet max. + </string> + <string name="Butt Physics UpDown Spring"> + Vibration + </string> + <string name="Butt Physics UpDown Gain"> + Amplification + </string> + <string name="Butt Physics UpDown Damping"> + Amortissement + </string> + <string name="Butt Physics LeftRight Max Effect"> + Effet max. + </string> + <string name="Butt Physics LeftRight Spring"> + Vibration + </string> + <string name="Butt Physics LeftRight Gain"> + Amplification + </string> + <string name="Butt Physics LeftRight Damping"> + Amortissement + </string> <string name="Bushy Eyebrows"> Sourcils touffus </string> @@ -2256,6 +2373,9 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. <string name="Butt Size"> Taille des fesses </string> + <string name="Butt Gravity"> + Gravité des fesses + </string> <string name="bustle skirt"> Jupe gonflante </string> @@ -3764,6 +3884,9 @@ de l'infraction signalée <string name="New Tattoo"> Nouveau tatouage </string> + <string name="New Physics"> + Nouvelles propriétés physiques + </string> <string name="Invalid Wearable"> Objet à porter non valide </string> diff --git a/indra/newview/skins/default/xui/pl/floater_about_land.xml b/indra/newview/skins/default/xui/pl/floater_about_land.xml index b935615fcb4034e9b7e806e65aff77a7c67baba4..badff11a5924367d15b7b04af81be3937f8da9f2 100644 --- a/indra/newview/skins/default/xui/pl/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pl/floater_about_land.xml @@ -349,6 +349,7 @@ Jedynie wiÄ™ksze posiadÅ‚oÅ›ci mogÄ… być umieszczone w bazie wyszukiwarki. <combo_box.item label="Park i natura" name="item9"/> <combo_box.item label="Mieszkalna" name="item10"/> <combo_box.item label="Zakupy" name="item11"/> + <combo_box.item label="OpÅ‚ata za wynajÄ™cie" name="item13"/> <combo_box.item label="Inna" name="item12"/> </combo_box> <combo_box name="land category"> @@ -363,6 +364,7 @@ Jedynie wiÄ™ksze posiadÅ‚oÅ›ci mogÄ… być umieszczone w bazie wyszukiwarki. <combo_box.item label="Parki i natura" name="item9"/> <combo_box.item label="Mieszkalna" name="item10"/> <combo_box.item label="Zakupy" name="item11"/> + <combo_box.item label="OpÅ‚ata za wynajÄ™cie" name="item13"/> <combo_box.item label="Inna" name="item12"/> </combo_box> <check_box label="Treść 'Mature'" name="MatureCheck" tool_tip=""/> @@ -430,7 +432,7 @@ Mediów: (Zdefiniowane przez MajÄ…tek) </panel.string> <panel.string name="allow_public_access"> - UdostÄ™pnij publicznie ([MATURITY]) + UdostÄ™pniaj publicznie ([MATURITY]) (PamiÄ™taj: w przypadku braku zaznaczenia tej opcji widoczne bÄ™dÄ… linie bana.) </panel.string> <panel.string name="estate_override"> Jedna lub wiÄ™cej z tych opcji ustawiona jest z poziomu PosiadÅ‚oÅ›ci diff --git a/indra/newview/skins/default/xui/pl/floater_beacons.xml b/indra/newview/skins/default/xui/pl/floater_beacons.xml index 547db2b3517c670b6a99854fd80065b8be0d0323..e6286a6ac129d76b2f54c7930fc211f8da6d73cb 100644 --- a/indra/newview/skins/default/xui/pl/floater_beacons.xml +++ b/indra/newview/skins/default/xui/pl/floater_beacons.xml @@ -17,5 +17,6 @@ <check_box label="Obiekty dotykalne" name="touch_only"/> <check_box label="ŹródÅ‚a dźwiÄ™ku" name="sounds"/> <check_box label="ŹródÅ‚a czÄ…steczek" name="particles"/> + <check_box label="ŹródÅ‚a mediów" name="moapbeacon"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_map.xml b/indra/newview/skins/default/xui/pl/floater_map.xml index fd151e91adfc6fe371a19edc2f61538d3d9b0f45..e01c4c8a82cfec069c409b44cc178b720f43ece2 100644 --- a/indra/newview/skins/default/xui/pl/floater_map.xml +++ b/indra/newview/skins/default/xui/pl/floater_map.xml @@ -3,6 +3,9 @@ <floater.string name="ToolTipMsg"> [REGION](Podwójne klikniÄ™cie otwiera MapÄ™, Shift i przeciÄ…gniÄ™cie kursorem zmienia skalÄ™) </floater.string> + <floater.string name="AltToolTipMsg"> + [REGION](Podwójne klikniÄ™cie aktywuje teleportacjÄ™, wciÅ›nij Shift i przeciÄ…gnij aby przesunąć) + </floater.string> <floater.string name="mini_map_caption"> MINIMAPA </floater.string> diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml index 337998efc989bfaf01679650c1bb165e040c19a4..9e6fed838764667ce242b701813c3d0d59c2adb3 100644 --- a/indra/newview/skins/default/xui/pl/floater_tools.xml +++ b/indra/newview/skins/default/xui/pl/floater_tools.xml @@ -64,6 +64,8 @@ <radio_item label="Wybierz teksturÄ™" name="radio select face"/> </radio_group> <check_box label="Edytuj poÅ‚Ä…czone części" name="checkbox edit linked parts"/> + <button label="Linkuj" name="link_btn"/> + <button label="Rozlinkuj" name="unlink_btn"/> <text name="RenderingCost" tool_tip="Pokazuje koszt renderowania tego obiektu"> þ: [COUNT] </text> @@ -301,7 +303,7 @@ <combo_box.item label="Kwadrat" name="Square"/> <combo_box.item label="TrójkÄ…t" name="Triangle"/> </combo_box> - <text name="text twist" left_delta="-5" width="160"> + <text left_delta="-5" name="text twist" width="160"> SkrÄ™cenie (poczÄ…tek/koniec) </text> <spinner label="P" name="Twist Begin"/> diff --git a/indra/newview/skins/default/xui/pl/menu_attachment_self.xml b/indra/newview/skins/default/xui/pl/menu_attachment_self.xml index c19b0a1c2e2aeeb08f1a14ddb473a93dfc5c7dc6..163b3a231e266d7dbc4b77d765932f973d38273c 100644 --- a/indra/newview/skins/default/xui/pl/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/pl/menu_attachment_self.xml @@ -5,7 +5,7 @@ <menu_item_call label="OdÅ‚Ä…cz" name="Detach"/> <menu_item_call label="UsiÄ…dź tutaj" name="Sit Down Here"/> <menu_item_call label="WstaÅ„" name="Stand Up"/> - <menu_item_call label="ZmieÅ„ strój" name="Change Outfit"/> + <menu_item_call label="Mój wyglÄ…d" name="Change Outfit"/> <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> <menu_item_call label="Moi znajomi" name="Friends..."/> diff --git a/indra/newview/skins/default/xui/pl/menu_avatar_self.xml b/indra/newview/skins/default/xui/pl/menu_avatar_self.xml index ea151788c6b9e4df020ed80e708e73b64d30b44e..8eb501c5b8b48a02104499b7c80d85a930583f25 100644 --- a/indra/newview/skins/default/xui/pl/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pl/menu_avatar_self.xml @@ -14,6 +14,7 @@ <menu_item_call label="Podkoszulek" name="Self Undershirt"/> <menu_item_call label="BieliznÄ™" name="Self Underpants"/> <menu_item_call label="Tatuaż" name="Self Tattoo"/> + <menu_item_call label="Fizyka" name="Self Physics"/> <menu_item_call label="Ubranie alpha" name="Self Alpha"/> <menu_item_call label="Wszystko" name="All Clothes"/> </context_menu> @@ -21,7 +22,7 @@ <context_menu label="OdÅ‚Ä…cz" name="Object Detach"/> <menu_item_call label="OdÅ‚Ä…cz wszystko" name="Detach All"/> </context_menu> - <menu_item_call label="ZmieÅ„ strój" name="Chenge Outfit"/> + <menu_item_call label="Mój wyglÄ…d" name="Chenge Outfit"/> <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> <menu_item_call label="Moi znajomi" name="Friends..."/> diff --git a/indra/newview/skins/default/xui/pl/menu_bottomtray.xml b/indra/newview/skins/default/xui/pl/menu_bottomtray.xml index a4a6ea484df80961654b50390ccd7407f8794744..1ec5883cfe2130a4f20e625445392053d5cb0ffc 100644 --- a/indra/newview/skins/default/xui/pl/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/pl/menu_bottomtray.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="hide_camera_move_controls_menu"> + <menu_item_check label="Rozpocznij rozmowÄ™ gÅ‚osowÄ…" name="EnableVoiceChat"/> <menu_item_check label="Przycisk gesturki" name="ShowGestureButton"/> <menu_item_check label="Przycisk ruchu" name="ShowMoveButton"/> <menu_item_check label="Przycisk widoku" name="ShowCameraButton"/> <menu_item_check label="Przycisk zdjęć" name="ShowSnapshotButton"/> - <menu_item_check label="Schowek" name="ShowSidebarButton"/> <menu_item_check label="Buduj" name="ShowBuildButton"/> <menu_item_check label="Szukaj" name="ShowSearchButton"/> <menu_item_check label="Mapa" name="ShowWorldMapButton"/> diff --git a/indra/newview/skins/default/xui/pl/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/pl/menu_inspect_avatar_gear.xml index 5c27d53d906dca7b13b9fc1135c249beb7b630c3..59560f236c279fa3c4acfa2bfba197fecb1bb690 100644 --- a/indra/newview/skins/default/xui/pl/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/pl/menu_inspect_avatar_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Zobacz profil" name="view_profile"/> <menu_item_call label="Dodaj znajomość" name="add_friend"/> <menu_item_call label="IM" name="im"/> @@ -11,9 +11,11 @@ <menu_item_call label="Raport" name="report"/> <menu_item_call label="Unieruchom" name="freeze"/> <menu_item_call label="Wyrzuć" name="eject"/> + <menu_item_call label="Kopnij" name="kick"/> + <menu_item_call label="CSR" name="csr"/> <menu_item_call label="Debugowanie tekstur" name="debug"/> <menu_item_call label="Znajdź na mapie" name="find_on_map"/> <menu_item_call label="Przybliż" name="zoom_in"/> <menu_item_call label="ZapÅ‚ać" name="pay"/> <menu_item_call label="UdostÄ™pnij" name="share"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/pl/menu_inspect_self_gear.xml index 90d71371e8311bcb915c5d1141c02c48d252b685..c4ef9761d9d73eaac285a9d9b8dd6053157e1a1d 100644 --- a/indra/newview/skins/default/xui/pl/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/pl/menu_inspect_self_gear.xml @@ -1,10 +1,31 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> - <menu_item_call label="UsiÄ…dź tutaj" name="sit_down_here"/> - <menu_item_call label="WstaÅ„" name="stand_up"/> - <menu_item_call label="ZmieÅ„ strój" name="change_outfit"/> - <menu_item_call label="Mój profil" name="my_profile"/> - <menu_item_call label="Moi znajomi" name="my_friends"/> - <menu_item_call label="Moje grupy" name="my_groups"/> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="Gear Menu"> + <menu_item_call label="UsiÄ…dź tutaj" name="Sit Down Here"/> + <menu_item_call label="WstaÅ„" name="Stand Up"/> + <context_menu label="Zdejmij" name="Take Off >"> + <context_menu label="Ubranie" name="Clothes >"> + <menu_item_call label="Bluzka" name="Shirt"/> + <menu_item_call label="Spodnie" name="Pants"/> + <menu_item_call label="Spódnica" name="Skirt"/> + <menu_item_call label="Buty" name="Shoes"/> + <menu_item_call label="Skarpetki" name="Socks"/> + <menu_item_call label="Kurtka" name="Jacket"/> + <menu_item_call label="RÄ™kawiczki" name="Gloves"/> + <menu_item_call label="Podkoszulek" name="Self Undershirt"/> + <menu_item_call label="Bielizna" name="Self Underpants"/> + <menu_item_call label="Tatuaż" name="Self Tattoo"/> + <menu_item_call label="Alpha" name="Self Alpha"/> + <menu_item_call label="Ubranie" name="All Clothes"/> + </context_menu> + <context_menu label="HUD" name="Object Detach HUD"/> + <context_menu label="OdÅ‚Ä…cz" name="Object Detach"/> + <menu_item_call label="OdÅ‚Ä…cz wszystko" name="Detach All"/> + </context_menu> + <menu_item_call label="ZmieÅ„ strój" name="Chenge Outfit"/> + <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> + <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Znajomi" name="Friends..."/> + <menu_item_call label="Moje grupy" name="Groups..."/> + <menu_item_call label="Mój profil" name="Profile..."/> <menu_item_call label="Debugowanie tekstur" name="Debug..."/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_inventory.xml b/indra/newview/skins/default/xui/pl/menu_inventory.xml index e47ffa0e188bfa756de60738fce87230005bdb48..5492f78b26c95e5f0f32edc1f7cc5c17d4576921 100644 --- a/indra/newview/skins/default/xui/pl/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pl/menu_inventory.xml @@ -25,6 +25,7 @@ <menu_item_call label="Nowa bielizna" name="New Underpants"/> <menu_item_call label="Nowa maska alpha" name="New Alpha Mask"/> <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> + <menu_item_call label="Nowa fizyka" name="New Physics"/> </menu> <menu label="Nowa Część CiaÅ‚a" name="New Body Parts"> <menu_item_call label="Nowy ksztaÅ‚t" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/pl/menu_inventory_add.xml b/indra/newview/skins/default/xui/pl/menu_inventory_add.xml index 4a56586aafc734e61412a951bd8de451a123aec6..04f9b94f7ca46f1d9cbf506d4ae2759d895c47c6 100644 --- a/indra/newview/skins/default/xui/pl/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/pl/menu_inventory_add.xml @@ -23,6 +23,7 @@ <menu_item_call label="Nowa bielizna" name="New Underpants"/> <menu_item_call label="Nowa maska alpha" name="New Alpha"/> <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> + <menu_item_call label="Nowa fizyka" name="New Physics"/> </menu> <menu label="Nowa Część CiaÅ‚a" name="New Body Parts"> <menu_item_call label="Nowy ksztaÅ‚t" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/pl/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/pl/menu_inventory_gear_default.xml index 491b4deeaaff5b7766f6647aa8f93e4a2a11d2c3..591c3a81d5f3d563c2c5b05179151130f4632efe 100644 --- a/indra/newview/skins/default/xui/pl/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/pl/menu_inventory_gear_default.xml @@ -3,6 +3,7 @@ <menu_item_call label="Nowe okno Szafy" name="new_window"/> <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_by_name"/> <menu_item_check label="PorzÄ…dkuj wedÅ‚ug daty" name="sort_by_recent"/> + <menu_item_check label="Sortuj foldery zawsze wedÅ‚ug nazwy" name="sort_folders_by_name"/> <menu_item_check label="Posortuj foldery systemowe od góry" name="sort_system_folders_to_top"/> <menu_item_call label="Pokaż filtry" name="show_filters"/> <menu_item_call label="Zresetuj filtry" name="reset_filters"/> diff --git a/indra/newview/skins/default/xui/pl/menu_media_ctrl.xml b/indra/newview/skins/default/xui/pl/menu_media_ctrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..60dc3673a949593a3651e30864a1e96a4a9daad2 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/menu_media_ctrl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="media ctrl context menu"> + <menu_item_call label="Wytnij" name="Cut"/> + <menu_item_call label="Kopiuj" name="Copy"/> + <menu_item_call label="Wklej" name="Paste"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_object.xml b/indra/newview/skins/default/xui/pl/menu_object.xml index 2173401dd26d2c6aeb061c809739af0d0b93405b..3da6c5c8905b6b43975dfe532900bd11b7e4355a 100644 --- a/indra/newview/skins/default/xui/pl/menu_object.xml +++ b/indra/newview/skins/default/xui/pl/menu_object.xml @@ -16,14 +16,14 @@ <context_menu label="DoÅ‚Ä…cz" name="Object Attach"/> <context_menu label="DoÅ‚Ä…cz HUD" name="Object Attach HUD"/> </context_menu> - <context_menu label="UsuÅ„" name="Remove"> + <context_menu label="ZarzÄ…dzaj" name="Remove"> <menu_item_call label="Raport" name="Report Abuse..."/> <menu_item_call label="Zablokuj" name="Object Mute"/> <menu_item_call label="Zwróć" name="Return..."/> - <menu_item_call label="UsuÅ„" name="Delete"/> </context_menu> <menu_item_call label="Weź" name="Pie Object Take"/> <menu_item_call label="Weź kopiÄ™" name="Take Copy"/> <menu_item_call label="ZapÅ‚ać" name="Pay..."/> <menu_item_call label="Kup" name="Buy..."/> + <menu_item_call label="Skasuj" name="Delete"/> </context_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_outfit_gear.xml b/indra/newview/skins/default/xui/pl/menu_outfit_gear.xml index 1a70e76ec7cb6a32136c781317a6e0f3dc2b86f2..c093557e861f0f7d1db2c6c3ed03396aadcefafd 100644 --- a/indra/newview/skins/default/xui/pl/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/pl/menu_outfit_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="Gear Outfit"> +<toggleable_menu name="Gear Outfit"> <menu_item_call label="Załóż - ZastÄ…p obecny strój" name="wear"/> <menu_item_call label="Załóż - Dodaj do bieżącego stroju" name="wear_add"/> <menu_item_call label="Zdejmij - UsuÅ„ z obecnego stroju" name="take_off"/> @@ -14,6 +14,7 @@ <menu_item_call label="Nowa podkoszulka" name="New Undershirt"/> <menu_item_call label="Nowa bielizna" name="New Underpants"/> <menu_item_call label="Nowa maska alpha" name="New Alpha"/> + <menu_item_call label="Nowa fizyka" name="New Physics"/> <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> </menu> <menu label="Nowe części ciaÅ‚a" name="New Body Parts"> @@ -24,4 +25,4 @@ </menu> <menu_item_call label="ZmieÅ„ nazwÄ™ stroju" name="rename"/> <menu_item_call label="UsuÅ„ strój" name="delete_outfit"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/pl/menu_places_gear_folder.xml index 65417cef221b0b058386038bec0db270060efbc9..d1f283b7aa3c4672f6405d7aae7969493e624170 100644 --- a/indra/newview/skins/default/xui/pl/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/pl/menu_places_gear_folder.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_folder_gear"> <menu_item_call label="Dodaj do landmarków" name="add_landmark"/> <menu_item_call label="Dodaj folder" name="add_folder"/> + <menu_item_call label="Przywróć obiekt" name="restore_item"/> <menu_item_call label="Wytnij" name="cut"/> <menu_item_call label="Kopiuj" name="copy_folder"/> <menu_item_call label="Wklej" name="paste"/> @@ -12,4 +13,4 @@ <menu_item_call label="RozwiÅ„ wszystkie foldery" name="expand_all"/> <menu_item_call label="Schowaj wszystkie foldery" name="collapse_all"/> <menu_item_check label="Sortuj wedÅ‚ug daty" name="sort_by_date"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/pl/menu_places_gear_landmark.xml index 36787dd0aa8cfa2e51ac43d7f4e047c18788e6c7..0139d3a98799049e5571c87b1c0d6c00f7e19592 100644 --- a/indra/newview/skins/default/xui/pl/menu_places_gear_landmark.xml +++ b/indra/newview/skins/default/xui/pl/menu_places_gear_landmark.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_ladmark_gear"> +<toggleable_menu name="menu_ladmark_gear"> <menu_item_call label="Teleportuj" name="teleport"/> <menu_item_call label="WiÄ™cej informacji" name="more_info"/> <menu_item_call label="Pokaż na mapie" name="show_on_map"/> <menu_item_call label="Dodaj do landmarków" name="add_landmark"/> <menu_item_call label="Dodaj folder" name="add_folder"/> + <menu_item_call label="Przywróć obiekt" name="restore_item"/> <menu_item_call label="Wytnij" name="cut"/> <menu_item_call label="Kopiuj landmark" name="copy_landmark"/> <menu_item_call label="Kopiuj SLurl" name="copy_slurl"/> @@ -15,4 +16,4 @@ <menu_item_call label="Schowaj wszystkie foldery" name="collapse_all"/> <menu_item_check label="Sortuj wedÅ‚ug daty" name="sort_by_date"/> <menu_item_call label="Stwórz Ulubione" name="create_pick"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml index e6a9d360c4c2c74eeaa0fee511b981519051d259..e869806d04f2ab7d51596ec572f2546623fdb590 100644 --- a/indra/newview/skins/default/xui/pl/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml @@ -5,7 +5,7 @@ <menu_item_call label="Dashboard" name="Manage My Account"/> <menu_item_call label="Kup L$" name="Buy and Sell L$"/> <menu_item_call label="Mój Profil" name="Profile"/> - <menu_item_call label="ZmieÅ„ strój" name="ChangeOutfit"/> + <menu_item_call label="Mój wyglÄ…d" name="ChangeOutfit"/> <menu_item_check label="Moja Szafa" name="Inventory"/> <menu_item_check label="Moja Szafa" name="ShowSidetrayInventory"/> <menu_item_check label="Moje gesturki" name="Gestures"/> @@ -33,6 +33,7 @@ <menu label="Åšwiat" name="World"> <menu_item_check label="Mini-Mapa" name="Mini-Map"/> <menu_item_check label="Mapa Åšwiata" name="World Map"/> + <menu_item_check label="Szukaj" name="Search"/> <menu_item_call label="Zrób zdjÄ™cie" name="Take Snapshot"/> <menu_item_call label="ZapamiÄ™taj to miejsce (LM)" name="Create Landmark Here"/> <menu label="Miejsce" name="Land"> @@ -222,7 +223,9 @@ <menu label="Pokaż informacje" name="Display Info"> <menu_item_check label="Pokaż czas" name="Show Time"/> <menu_item_check label="Pokaż informacje o renderowaniu" name="Show Render Info"/> + <menu_item_check label="Pokaż informacjÄ™ o teksturze" name="Show Texture Info"/> <menu_item_check label="Pokaż kolor pod kursorem" name="Show Color Under Cursor"/> + <menu_item_check label="Pokaż pamięć" name="Show Memory"/> <menu_item_check label="Pokaż aktualizacje obiektów" name="Show Updates"/> </menu> <menu label="Reset bÅ‚Ä™du" name="Force Errors"> @@ -240,6 +243,9 @@ <menu_item_check label="Losowa ilość klatek" name="Randomize Framerate"/> <menu_item_check label="Test klatki obrazu" name="Frame Test"/> </menu> + <menu label="Render Metadata" name="Render Metadata"> + <menu_item_check label="Aktualizuj typ" name="Update Type"/> + </menu> <menu label="Renderowanie" name="Rendering"> <menu_item_check label="Osie" name="Axes"/> <menu_item_check label="Tryb obrazu szkieletowego" name="Wireframe"/> @@ -328,4 +334,9 @@ </menu> <menu_item_call label="Boskie narzÄ™dzia" name="God Tools"/> </menu> + <menu label="Admin" name="Deprecated"> + <menu label="Take Off Clothing" name="Take Off Clothing"> + <menu_item_call label="Fizyka" name="Physics"/> + </menu> + </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 25fa5da3ab0c28b5059a2627a92ee577c58007d3..63f976a31469d9c5749dc811956575c214e4ff24 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -72,9 +72,9 @@ Szczegóły bÅ‚Ä™du: BÅ‚Ä…d o nazwie '[_NAME]' nie zostaÅ‚ odnaleziony <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="LoginFailedNoNetwork"> - Brak poÅ‚Ä…czenia z [SECOND_LIFE_GRID]. -'[DIAGNOSTIC]' -Sprawdź stan swojego poÅ‚Ä…czenia sieciowego. + Nie można poÅ‚Ä…czyć z [SECOND_LIFE_GRID]. + '[DIAGNOSTIC]' +Upewnij siÄ™, że Twoje poÅ‚Ä…czenie z internetem dziaÅ‚a. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="MessageTemplateNotFound"> @@ -331,13 +331,6 @@ Potrzebujesz konta aby siÄ™ zalogować do [SECOND_LIFE]. Czy chcesz utworzyć je <notification name="InvalidCredentialFormat"> Należy wprowadzić nazwÄ™ użytkownika lub imiÄ™ oraz nazwisko Twojego awatara w pole nazwy użytkownika a nastÄ™pnie ponownie siÄ™ zalogować. </notification> - <notification name="AddClassified"> - OgÅ‚oszenia reklamowe ukazujÄ… siÄ™ w zakÅ‚adce Reklama w wyszukiwarce (Szukaj) oraz na [http://secondlife.com/community/classifieds secondlife.com] przez tydzieÅ„. -Napisz treść swojej reklamy, kliknij Zamieść by dodać katalogu ogÅ‚oszeÅ„. -Po zamieszczeniu reklamy zostaniesz poproszony o sprecyzowanie opÅ‚aty za ReklamÄ™. -Im wyższa opÅ‚ata tym wyżej Twoja reklama wyÅ›wietla siÄ™ w katalogu i wyszukiwarce po wpisaniu słów kluczowych. - <usetemplate ignoretext="Jak stworzyć nowÄ… reklamÄ™?" name="okcancelignore" notext="Anuluj" yestext="OK"/> - </notification> <notification name="DeleteClassified"> Usunąć reklamÄ™ '[NAME]'? PamiÄ™taj! Nie ma rekompensaty za poniesione koszta. @@ -2723,7 +2716,7 @@ Przycisk zostanie wyÅ›wietlony w przypadku dostatecznej iloÅ›ci przestrzeni. Zaznacz Rezydentów, z którymi chcesz siÄ™ podzielić. </notification> <notification name="ShareItemsConfirmation"> - JesteÅ› pewien/pewna, że chcesz udostÄ™pnić nastÄ™pujÄ…ce obiekty: + Czy na pewno chcesz udostÄ™pnić nastÄ™pujÄ…ce obiekty: <nolink>[ITEMS]</nolink> @@ -2814,24 +2807,32 @@ Wyciszyć wszystkich? <notification label="WstaÅ„" name="HintSit"> Aby wstać i opuÅ›cić pozycjÄ™ siedzÄ…cÄ…, kliknij przycisk WstaÅ„. </notification> + <notification label="Mów" name="HintSpeak"> + Kliknij przycisk "Mów" aby wÅ‚Ä…czyć i wyÅ‚Ä…czyć Twój mikrofon. + +Kliknij w strzaÅ‚kÄ™ aby zobaczyć panel kontroli gÅ‚osu. + +Ukrycie przycisku "Mów" zdezaktywuje gÅ‚os. + </notification> <notification label="Odkrywaj Åšwiat" name="HintDestinationGuide"> Destination Guide zawiera tysiÄ…ce nowych miejsc do odkrycia. Wybierz lokalizacjÄ™ i teleportuj siÄ™ aby rozpocząć zwiedzanie. </notification> - <notification label="ZmieÅ„ wyglÄ…d swojego awatara" name="HintAvatarPicker"> - Czy chcesz inaczej wyglÄ…dać? Kliknij poniższy przycisk aby zobaczyć wiÄ™cej przykÅ‚adów awatarów. - </notification> <notification label="Schowek" name="HintSidePanel"> Schowek umożliwia szybki dostÄ™p do Twojej Szafy, ubraÅ„, profili i innych w panelu bocznym. </notification> <notification label="Ruch" name="HintMove"> Aby chodzić lub biegać, otwórz panel ruchu i użyj strzaÅ‚ek do nawigacji. Możesz także używać strzaÅ‚ek z klawiatury. </notification> + <notification label="" name="HintMoveClick"> + 1. Kliknij aby chodzić. +Kliknij gdziekolwiek na ziemi aby przejść do wskazanego miejsca. + +2. Kliknij i przeciÄ…gnij aby zmienić widok. +Kliknij i przeciÄ…gnij gdziekolwiek aby obrócić widok. + </notification> <notification label="WyÅ›wietlana nazwa" name="HintDisplayName"> Ustaw wyÅ›wietlanÄ… nazwÄ™, którÄ… możesz zmieniać tutaj. Jest ona dodatkiem do unikatowej nazwy użytkownika, która nie może być zmieniona. Możesz zmienić sposób w jaki widzisz nazwy innych osób w Twoich Ustawieniach. </notification> - <notification label="Ruch" name="HintMoveArrows"> - Użyj przycisków ze strzaÅ‚kami z klawiatury aby chodzić. JeÅ›li wciÅ›niesz strzaÅ‚kÄ™ 'do góry' podwójnie, zaczniesz biec. - </notification> <notification label="Widok" name="HintView"> To change your camera view, use the Orbit and Pan controls. Zresetuj widok poprzez wciÅ›niÄ™cie klawisza Esc lub chodzenie. </notification> @@ -2857,6 +2858,38 @@ Wyciszyć wszystkich? <button name="cancel" text="Anuluj"/> </form> </notification> + <notification label="" name="ModeChange"> + Zmiana trybu wymaga restartu. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoClassifieds"> + Tworzenie i edycja reklam jest możliwa tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoGroupInfo"> + Tworzenie i edycja grup jest możliwa tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoPicks"> + Tworzenie i edycja Ulubionych jest możliwa jedynie w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoWorldMap"> + OglÄ…danie mapy Å›wiata jest możliwe tylko w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoVoiceCall"> + Rozmowy gÅ‚osowe sÄ… możliwe tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoAvatarShare"> + UdostÄ™pnienie jest możliwe tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoAvatarPay"> + PÅ‚acenie innym Rezydentom jest możliwe tylko w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> <global name="UnsupportedCPU"> - PrÄ™dkość Twojego CPU nie speÅ‚nia minimalnych wymagaÅ„. </global> diff --git a/indra/newview/skins/default/xui/pl/panel_edit_physics.xml b/indra/newview/skins/default/xui/pl/panel_edit_physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..a773a52a59c60a249d9b4cb683c9434192fe563f --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_edit_physics.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="edit_physics_panel"> + <panel label="" name="accordion_panel"> + <accordion name="physics_accordion"> + <accordion_tab name="physics_breasts_updown_tab" title="Podskakiwanie piersi"/> + <accordion_tab name="physics_breasts_inout_tab" title="Rowek miÄ™dzy piersiami"/> + <accordion_tab name="physics_breasts_leftright_tab" title="KoÅ‚ysanie piersi"/> + <accordion_tab name="physics_belly_tab" title="Poskakiwanie brzucha"/> + <accordion_tab name="physics_butt_tab" title="Podksakiwanie poÅ›ladków"/> + <accordion_tab name="physics_butt_leftright_tab" title="KoÅ‚ysanie poÅ›ladków"/> + <accordion_tab name="physics_advanced_tab" title="Zaawansowane parametry"/> + </accordion> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pl/panel_edit_wearable.xml b/indra/newview/skins/default/xui/pl/panel_edit_wearable.xml index d1157b910d66809b8e2b14eb6407e624f6143d9d..2027b8715b6d03cbd64a713c7d6a013e2fa8bee7 100644 --- a/indra/newview/skins/default/xui/pl/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/pl/panel_edit_wearable.xml @@ -45,6 +45,9 @@ <string name="edit_tattoo_title"> Edycja tatuażu </string> + <string name="edit_physics_title"> + Edycja fizyki + </string> <string name="shape_desc_text"> KsztaÅ‚t: </string> @@ -90,6 +93,9 @@ <string name="tattoo_desc_text"> Tatuaż: </string> + <string name="physics_desc_text"> + Fizyka: + </string> <labeled_back_button label="Zapisz" name="back_btn" tool_tip="Powrót do edycji stroju"/> <text name="edit_wearable_title" value="Edycja ksztaÅ‚tu"/> <panel label="Koszula" name="wearable_type_panel"> diff --git a/indra/newview/skins/default/xui/pl/panel_login.xml b/indra/newview/skins/default/xui/pl/panel_login.xml index 81da94a65952e37aec3130f46b2b95ee9b191f80..dc8e7399af15b2129f95fc182df736de6cf1f1c1 100644 --- a/indra/newview/skins/default/xui/pl/panel_login.xml +++ b/indra/newview/skins/default/xui/pl/panel_login.xml @@ -14,6 +14,13 @@ </text> <check_box label="ZapamiÄ™taj hasÅ‚o" name="remember_check"/> <button label="PoÅ‚Ä…cz" name="connect_btn"/> + <text name="mode_selection_text"> + Tryb życia: + </text> + <combo_box name="mode_combo" tool_tip="Wybierz tryb życia. Wybierz tryb turystyczny dla Å‚atwego zwiedzania i czatowania. Wybierz tryb zaawansowany aby mieć dostÄ™p do wiÄ™kszej iloÅ›ci opcji."> + <combo_box.item label="Turystyczny" name="Basic"/> + <combo_box.item label="Zaawansowany" name="Advanced"/> + </combo_box> <text name="start_location_text"> Rozpocznij w: </text> diff --git a/indra/newview/skins/default/xui/pl/panel_nearby_media.xml b/indra/newview/skins/default/xui/pl/panel_nearby_media.xml index c9f951f7c6adc9cc665c07668c823718864dcf2a..d77c6d7852cd96d4d1be4928aeddc83e204ffe96 100644 --- a/indra/newview/skins/default/xui/pl/panel_nearby_media.xml +++ b/indra/newview/skins/default/xui/pl/panel_nearby_media.xml @@ -19,7 +19,7 @@ <button label="Zatrzymaj" name="all_nearby_media_disable_btn" tool_tip="WyÅ‚Ä…cz wszystkie media w pobliżu"/> <button label="WÅ‚Ä…cz" name="all_nearby_media_enable_btn" tool_tip="WÅ‚Ä…cz wszystkie media w pobliżu"/> <button name="open_prefs_btn" tool_tip="Uruchom preferencje medialne"/> - <button label="WiÄ™cej >>" label_selected="Mniej <<" name="more_btn" tool_tip="Zaawansowane"/> + <button label="WiÄ™cej >>" label_selected="<< Mniej" name="more_btn" tool_tip="Zaawansowane"/> <button label="WiÄ™cej >>" label_selected="Mniej <<" name="less_btn" tool_tip="Zaawansowane"/> </panel> <panel name="nearby_media_panel"> diff --git a/indra/newview/skins/default/xui/pl/panel_people.xml b/indra/newview/skins/default/xui/pl/panel_people.xml index 1bd5b4a9123f15f536a6f461c7366f3c537601e3..da9f84cb2e423b2ff3f4e880099e11ff5f23b5fe 100644 --- a/indra/newview/skins/default/xui/pl/panel_people.xml +++ b/indra/newview/skins/default/xui/pl/panel_people.xml @@ -18,6 +18,8 @@ Chcesz spotkać ludzi? Spróbuj [secondlife:///app/worldmap Mapa Åšwiata]. <string name="groups_filter_label" value="Filtruj grupy"/> <string name="no_filtered_groups_msg" value="Nie znaleziono tego czego szukasz? Spróbuj [secondlife:///app/search/groups/[SEARCH_TERM] Szukaj]."/> <string name="no_groups_msg" value="Chcesz doÅ‚Ä…czyć do grup? Spróbuj [secondlife:///app/search/groups Szukaj]."/> + <string name="MiniMapToolTipMsg" value="[REGION](Podwójne klikniÄ™cie otwiera mapÄ™, wciÅ›nij Shift i przeciÄ…gnij aby przesunąć)"/> + <string name="AltMiniMapToolTipMsg" value="[REGION](Podwójne klikniÄ™cie aktywuje teleport, wciÅ›nij Shift i przeciÄ…gnij aby przesunąć)"/> <filter_editor label="Filtr" name="filter_input"/> <tab_container name="tabs"> <panel label="W POBLIÅ»U" name="nearby_panel"> diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml index 4a4e6509ab0cc5e3b8b7b8fa29fc28503526d880..3251099f747ed9372e995ebac33cf4ebfd924281 100644 --- a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml @@ -30,7 +30,9 @@ <spinner label="Czas widocznoÅ›ci czatu w pobliżu:" name="nearby_toasts_lifetime"/> <spinner label="Czas znikania czatu w pobliżu:" name="nearby_toasts_fadingtime"/> <check_box name="translate_chat_checkbox"/> - <text name="translate_chb_label" >Używaj translatora podczas rozmowy (wspierany przez Google)</text> + <text name="translate_chb_label"> + Użyj translatora podczas rozmowy (wspierany przez Google) + </text> <text name="translate_language_text"> PrzetÅ‚umacz czat na: </text> diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_colors.xml b/indra/newview/skins/default/xui/pl/panel_preferences_colors.xml index 3d1160882b6af1587c4bb4e71137391740b9f2d4..3affda57bf93558481caf8e325c3b67f3f4e01c8 100644 --- a/indra/newview/skins/default/xui/pl/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_colors.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Kolory" name="colors_panel"> <text name="effects_color_textbox"> - Moje efekty (selection beam): + Moje efekty (opcje wyboru): </text> <color_swatch name="effect_color_swatch" tool_tip="Kliknij aby wybrać kolor"/> <text name="font_colors"> - Kolor czcionki czatu: + Kolory czcionki czatu: </text> <text name="text_box1"> Ja @@ -34,8 +34,8 @@ <color_swatch name="background" tool_tip="Wybierz kolor taga"/> <slider label="Przeźroczystość:" name="bubble_chat_opacity" tool_tip="Wybierz przeźroczystość taga"/> <text name="floater_opacity"> - Przeźroczystość: + Floater Opacity: </text> - <slider label="Aktywny:" name="active"/> - <slider label="Niekatywny:" name="inactive"/> + <slider label="Aktywne:" name="active"/> + <slider label="Nieaktywne:" name="inactive"/> </panel> diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml index 0f21aa9dd1f467e674ed1dc3e634e6d722f7c1c6..f2beef091a413646edb99fefe1b43d950a79af0c 100644 --- a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml @@ -40,6 +40,10 @@ <combo_box.item label="Awatary i obiekty" name="3"/> <combo_box.item label="Wszystko" name="4"/> </combo_box> + <slider label="Fizyka awatara:" name="AvatarPhysicsDetail"/> + <text name="AvatarPhysicsDetailText"> + Niska + </text> <slider label="Pole widzenia:" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> m @@ -78,7 +82,7 @@ MaÅ‚o </text> <text name="AvatarRenderingText"> - Rendering awatarów + Rendering awatara: </text> <check_box initial_value="true" label="Impostoryzacja awatarowa" name="AvatarImpostors"/> <check_box initial_value="true" label="Rendering awatara przez GPU" name="AvatarVertexProgram"/> diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml b/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml index 692f24715bf9d03a073c10c589fa09c667e642d2..46f5ebb8e25921ab0a0f071773d761a73d9aec2a 100644 --- a/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml @@ -5,12 +5,14 @@ </panel.string> <slider label="Główny" name="System Volume"/> <check_box initial_value="true" name="mute_when_minimized"/> - <text name="mute_chb_label">Wycisz podczas minimalizacji</text> + <text name="mute_chb_label"> + Wycisz podczas minimalizacji + </text> <slider label="Interfejs" name="UI Volume"/> <slider label="Otoczenie" name="Wind Volume"/> <slider label="Efekty dźwiÄ™kowe" name="SFX Volume"/> <slider label="Muzyka strumieniowa" name="Music Volume"/> - <check_box label="Odtwarzaj media audio" name="enable_music"/> + <check_box label="Aktywny" name="enable_music"/> <slider label="Media" name="Media Volume"/> <check_box label="Odtwarzaj media" name="enable_media"/> <slider label="Komunikacja gÅ‚osowa" name="Voice Volume"/> diff --git a/indra/newview/skins/default/xui/pl/panel_profile.xml b/indra/newview/skins/default/xui/pl/panel_profile.xml index 4152c003860debab7eee0dd81fda66ebc4981f34..77dd951bc42b9acd8842beae2dc97ef3b5b96704 100644 --- a/indra/newview/skins/default/xui/pl/panel_profile.xml +++ b/indra/newview/skins/default/xui/pl/panel_profile.xml @@ -5,6 +5,12 @@ <string name="RegisterDateFormat"> [REG_DATE] ([AGE]) </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> <layout_stack name="layout"> <layout_panel name="profile_stack"> <scroll_container name="profile_scroll"> @@ -19,7 +25,7 @@ <text name="title_acc_status_text" value="Konto:"/> <text name="title_partner_text" value="Partner:"/> <panel name="partner_data_panel"> - <name_box initial_value="(przetwarzanie)" name="partner_text"/> + <text initial_value="(przetwarzanie)" name="partner_text"/> </panel> <text name="title_groups_text" value="Grupy:"/> </panel> diff --git a/indra/newview/skins/default/xui/pl/panel_script_ed.xml b/indra/newview/skins/default/xui/pl/panel_script_ed.xml index e18900af68541b410e6b4ed5896b08c8cfa18be0..b05223aa0f4f2a1dacf564fd175c0d6f59664777 100644 --- a/indra/newview/skins/default/xui/pl/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/pl/panel_script_ed.xml @@ -15,6 +15,9 @@ <panel.string name="Title"> Skrypt: [NAME] </panel.string> + <panel.string name="external_editor_not_set"> + Wybierz edytor poprzez ustawienie zmiennej Å›rodowiska LL_SCRIPT_EDITOR lub ustawienie ExternalEditor. + </panel.string> <menu_bar name="script_menu"> <menu label="Plik" name="File"> <menu_item_call label="Zapisz" name="Save"/> diff --git a/indra/newview/skins/default/xui/pl/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/pl/panel_scrolling_param_base.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa659040eaa57c1c5e325093dcc427058ea160b3 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_scrolling_param_base.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="LLScrollingPanelParamBase"> + <slider label="[DESC]" name="param slider"/> +</panel> diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index e6019bf66d1159648c5e36247b645b9b1b25ddfb..94708ba448a5374c25fda7b7e2380ae24aa34d60 100644 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -852,6 +852,9 @@ <string name="tattoo"> Tatuaż </string> + <string name="physics"> + Fizyka + </string> <string name="invalid"> niewÅ‚aÅ›ciwa funkcja </string> @@ -891,6 +894,9 @@ <string name="tattoo_not_worn"> Tatuaż nie jest zaÅ‚ożony </string> + <string name="physics_not_worn"> + Fizyka niezaÅ‚ożona + </string> <string name="invalid_not_worn"> nieważny </string> @@ -939,6 +945,9 @@ <string name="create_new_tattoo"> Nowy tatuaż </string> + <string name="create_new_physics"> + Stwórz nowÄ… fizykÄ™ + </string> <string name="create_new_invalid"> nieważny </string> @@ -1037,7 +1046,7 @@ </string> <string name="WornOnAttachmentPoint" value=" (zaÅ‚ożony na [ATTACHMENT_POINT])"/> <string name="ActiveGesture" value="[GESLABEL] (aktywne)"/> - <string name="Chat" value=" Czat :"/> + <string name="Chat Message" value="Czat:"/> <string name="Sound" value=" DźwiÄ™k :"/> <string name="Wait" value=" --- Zaczekaj :"/> <string name="AnimFlagStop" value=" Zatrzymaj animacjÄ™ :"/> @@ -1819,12 +1828,6 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh <string name="accel-win-shift"> Shift+ </string> - <string name="Esc"> - Esc - </string> - <string name="Home"> - Miejsce Startu - </string> <string name="FileSaved"> Zapisane pliki </string> @@ -1847,13 +1850,13 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh Do przodu </string> <string name="Direction_Left"> - W lewo + Lewo </string> <string name="Direction_Right"> - W prawo + Prawo </string> <string name="Direction_Back"> - Wróć + Wstecz </string> <string name="Direction_North"> Północ @@ -1942,6 +1945,9 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh <string name="Other"> Inna </string> + <string name="Rental"> + Wynajem + </string> <string name="Any"> Jakiekolwiek </string> @@ -2178,6 +2184,114 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj siÄ™ z [SUPPORT_SITE]. <string name="Bulbous Nose"> Bulwiasty nos </string> + <string name="Breast Physics Mass"> + Masa piersi + </string> + <string name="Breast Physics Smoothing"> + WygÅ‚adzanie piersi + </string> + <string name="Breast Physics Gravity"> + Grawitacja piersi + </string> + <string name="Breast Physics Drag"> + ÅšciÅ›niÄ™cie piersi + </string> + <string name="Breast Physics InOut Max Effect"> + Efekt max + </string> + <string name="Breast Physics InOut Spring"> + Sprężystość + </string> + <string name="Breast Physics InOut Gain"> + Wzmocnienie + </string> + <string name="Breast Physics InOut Damping"> + TÅ‚umienie + </string> + <string name="Breast Physics UpDown Max Effect"> + Efekt max + </string> + <string name="Breast Physics UpDown Spring"> + Sprężystość + </string> + <string name="Breast Physics UpDown Gain"> + Wzmocnienie + </string> + <string name="Breast Physics UpDown Damping"> + TÅ‚umienie + </string> + <string name="Breast Physics LeftRight Max Effect"> + Efekt max + </string> + <string name="Breast Physics LeftRight Spring"> + Sprężystość + </string> + <string name="Breast Physics LeftRight Gain"> + Wzmocnienie + </string> + <string name="Breast Physics LeftRight Damping"> + TÅ‚umienie + </string> + <string name="Belly Physics Mass"> + Masa brzucha + </string> + <string name="Belly Physics Smoothing"> + WygÅ‚adzanie brzucha + </string> + <string name="Belly Physics Gravity"> + Grawitacja brzucha + </string> + <string name="Belly Physics Drag"> + ÅšciÅ›niÄ™cie brzucha + </string> + <string name="Belly Physics UpDown Max Effect"> + Efekt max + </string> + <string name="Belly Physics UpDown Spring"> + Sprężystość + </string> + <string name="Belly Physics UpDown Gain"> + Wzmocnienie + </string> + <string name="Belly Physics UpDown Damping"> + TÅ‚umienie + </string> + <string name="Butt Physics Mass"> + Masa poÅ›ladków + </string> + <string name="Butt Physics Smoothing"> + WygÅ‚adzanie poÅ›ladków + </string> + <string name="Butt Physics Gravity"> + Grawitacja poÅ›ladków + </string> + <string name="Butt Physics Drag"> + ÅšciÅ›niÄ™cie poÅ›ladków + </string> + <string name="Butt Physics UpDown Max Effect"> + Efekt max + </string> + <string name="Butt Physics UpDown Spring"> + Sprężystość + </string> + <string name="Butt Physics UpDown Gain"> + Wzmocnienie + </string> + <string name="Butt Physics UpDown Damping"> + TÅ‚umienie + </string> + <string name="Butt Physics LeftRight Max Effect"> + Efekt max + </string> + <string name="Butt Physics LeftRight Spring"> + Sprężystość + </string> + <string name="Butt Physics LeftRight Gain"> + Wzmocnienie + </string> + <string name="Butt Physics LeftRight Damping"> + TÅ‚umienie + </string> <string name="Bushy Eyebrows"> Bujne brwi </string> @@ -2187,6 +2301,9 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj siÄ™ z [SUPPORT_SITE]. <string name="Butt Size"> Rozmiar poÅ›ladków </string> + <string name="Butt Gravity"> + Grawitacja poÅ›ladków + </string> <string name="bustle skirt"> Bustle Skirt </string> @@ -3662,6 +3779,9 @@ Raport o Nadużyciu <string name="New Tattoo"> Nowy tatuaż </string> + <string name="New Physics"> + Nowa fizyka + </string> <string name="Invalid Wearable"> Nieaktualne ubranie/część ciaÅ‚a </string> @@ -3861,7 +3981,7 @@ Raport o Nadużyciu <string name="Notices"> OgÅ‚oszenia </string> - <string name="Chat"> + <string name="Chat" value=" Czat :"> Czat </string> <string name="DeleteItems"> @@ -3873,4 +3993,348 @@ Raport o Nadużyciu <string name="EmptyOutfitText"> W tym stroju nie ma elementów </string> + <string name="ExternalEditorNotSet"> + Wybierz edytor używajÄ…c ustawieÅ„ ExternalEditor. + </string> + <string name="ExternalEditorNotFound"> + Nie odnaleziono zewnÄ™trzego edytora wskazanego przez Ciebie. +Spróbuj zaÅ‚Ä…czyć Å›cieżkÄ™ do edytora w cytowaniu. +(np. "/Å›cieżka do mojego/edytora" "%s") + </string> + <string name="ExternalEditorCommandParseError"> + BÅ‚Ä…d w skÅ‚adni komendy zewnÄ™trznego edytora. + </string> + <string name="ExternalEditorFailedToRun"> + Uruchomienie zewnÄ™trznego edytora nie powiodÅ‚o siÄ™. + </string> + <string name="Esc"> + Esc + </string> + <string name="Space"> + Space + </string> + <string name="Enter"> + Enter + </string> + <string name="Tab"> + Tab + </string> + <string name="Ins"> + Ins + </string> + <string name="Del"> + Del + </string> + <string name="Backsp"> + Backsp + </string> + <string name="Shift"> + Shift + </string> + <string name="Ctrl"> + Ctrl + </string> + <string name="Alt"> + Alt + </string> + <string name="CapsLock"> + CapsLock + </string> + <string name="Home"> + Miejsce Startu + </string> + <string name="End"> + End + </string> + <string name="PgUp"> + PgUp + </string> + <string name="PgDn"> + PgDn + </string> + <string name="F1"> + F1 + </string> + <string name="F2"> + F2 + </string> + <string name="F3"> + F3 + </string> + <string name="F4"> + F4 + </string> + <string name="F5"> + F5 + </string> + <string name="F6"> + F6 + </string> + <string name="F7"> + F7 + </string> + <string name="F8"> + F8 + </string> + <string name="F9"> + F9 + </string> + <string name="F10"> + F10 + </string> + <string name="F11"> + F11 + </string> + <string name="F12"> + F12 + </string> + <string name="Add"> + Dodaj + </string> + <string name="Subtract"> + Odejmij + </string> + <string name="Multiply"> + Mnożenie + </string> + <string name="Divide"> + Podziel + </string> + <string name="PAD_DIVIDE"> + PAD_DIVIDE + </string> + <string name="PAD_LEFT"> + PAD_LEFT + </string> + <string name="PAD_RIGHT"> + PAD_RIGHT + </string> + <string name="PAD_DOWN"> + PAD_DOWN + </string> + <string name="PAD_UP"> + PAD_UP + </string> + <string name="PAD_HOME"> + PAD_HOME + </string> + <string name="PAD_END"> + PAD_END + </string> + <string name="PAD_PGUP"> + PAD_PGUP + </string> + <string name="PAD_PGDN"> + PAD_PGDN + </string> + <string name="PAD_CENTER"> + PAD_CENTER + </string> + <string name="PAD_INS"> + PAD_INS + </string> + <string name="PAD_DEL"> + PAD_DEL + </string> + <string name="PAD_Enter"> + PAD_Enter + </string> + <string name="PAD_BUTTON0"> + PAD_BUTTON0 + </string> + <string name="PAD_BUTTON1"> + PAD_BUTTON1 + </string> + <string name="PAD_BUTTON2"> + PAD_BUTTON2 + </string> + <string name="PAD_BUTTON3"> + PAD_BUTTON3 + </string> + <string name="PAD_BUTTON4"> + PAD_BUTTON4 + </string> + <string name="PAD_BUTTON5"> + PAD_BUTTON5 + </string> + <string name="PAD_BUTTON6"> + PAD_BUTTON6 + </string> + <string name="PAD_BUTTON7"> + PAD_BUTTON7 + </string> + <string name="PAD_BUTTON8"> + PAD_BUTTON8 + </string> + <string name="PAD_BUTTON9"> + PAD_BUTTON9 + </string> + <string name="PAD_BUTTON10"> + PAD_BUTTON10 + </string> + <string name="PAD_BUTTON11"> + PAD_BUTTON11 + </string> + <string name="PAD_BUTTON12"> + PAD_BUTTON12 + </string> + <string name="PAD_BUTTON13"> + PAD_BUTTON13 + </string> + <string name="PAD_BUTTON14"> + PAD_BUTTON14 + </string> + <string name="PAD_BUTTON15"> + PAD_BUTTON15 + </string> + <string name="-"> + - + </string> + <string name="="> + = + </string> + <string name="`"> + ` + </string> + <string name=";"> + ; + </string> + <string name="["> + [ + </string> + <string name="]"> + ] + </string> + <string name="\"> + \ + </string> + <string name="0"> + 0 + </string> + <string name="1"> + 1 + </string> + <string name="2"> + 2 + </string> + <string name="3"> + 3 + </string> + <string name="4"> + 4 + </string> + <string name="5"> + 5 + </string> + <string name="6"> + 6 + </string> + <string name="7"> + 7 + </string> + <string name="8"> + 8 + </string> + <string name="9"> + 9 + </string> + <string name="A"> + A + </string> + <string name="B"> + B + </string> + <string name="C"> + C + </string> + <string name="D"> + D + </string> + <string name="E"> + E + </string> + <string name="F"> + F + </string> + <string name="G"> + G + </string> + <string name="H"> + H + </string> + <string name="I"> + I + </string> + <string name="J"> + J + </string> + <string name="K"> + K + </string> + <string name="L"> + L + </string> + <string name="M"> + M + </string> + <string name="N"> + N + </string> + <string name="O"> + O + </string> + <string name="P"> + P + </string> + <string name="Q"> + Q + </string> + <string name="R"> + R + </string> + <string name="S"> + S + </string> + <string name="T"> + T + </string> + <string name="U"> + U + </string> + <string name="V"> + V + </string> + <string name="W"> + W + </string> + <string name="X"> + X + </string> + <string name="Y"> + Y + </string> + <string name="Z"> + Z + </string> + <string name="BeaconParticle"> + PodglÄ…d lokalizatorów czÄ…steczek (niebieski) + </string> + <string name="BeaconPhysical"> + PodglÄ…d lokalizatorów fizycznych obiektów (zielony) + </string> + <string name="BeaconScripted"> + PodglÄ…d lokalizatorów obiektów skryptowanych (czerwony) + </string> + <string name="BeaconScriptedTouch"> + PodglÄ…d lokalizatorów obiektów skryptowanych z opcjÄ… dotyku (czerwony) + </string> + <string name="BeaconSound"> + PodglÄ…d lokalizatorów dźwiÄ™ków (żółty) + </string> + <string name="BeaconMedia"> + PodglÄ…d lokalizatorów mediów (biaÅ‚y) + </string> + <string name="ParticleHiding"> + Ukryj czÄ…steczki + </string> </strings> diff --git a/indra/newview/skins/default/xui/pt/floater_beacons.xml b/indra/newview/skins/default/xui/pt/floater_beacons.xml index b16ff6003e02f002c33e6a1e4227318081101675..f8ae3cd2d8c33341610471aea29fa6663505e587 100644 --- a/indra/newview/skins/default/xui/pt/floater_beacons.xml +++ b/indra/newview/skins/default/xui/pt/floater_beacons.xml @@ -17,5 +17,6 @@ <check_box label="Só tocar" name="touch_only"/> <check_box label="Fontes de som" name="sounds"/> <check_box label="Fontes de partÃculas" name="particles"/> + <check_box label="Fontes de mÃdia" name="moapbeacon"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml index e2fd61745f554168a9e3dbf38c99e588ea585e40..e84dcb093db4ada7713438e0387f19c2af544264 100644 --- a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml @@ -14,6 +14,7 @@ <menu_item_call label="Camiseta" name="Self Undershirt"/> <menu_item_call label="Roupa de baixo" name="Self Underpants"/> <menu_item_call label="Tatuagem" name="Self Tattoo"/> + <menu_item_call label="FÃsico" name="Self Physics"/> <menu_item_call label="Alpha" name="Self Alpha"/> <menu_item_call label="Todas as roupas" name="All Clothes"/> </context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml index bd628c94d38e21921e49a37393c33d2b4f8b8185..758516095443f71d8eae72d50a37543ebaf71791 100644 --- a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="hide_camera_move_controls_menu"> - <menu_item_check label="Voz ativada" name="EnableVoiceChat"/> + <menu_item_check label="Botão Falar" name="EnableVoiceChat"/> <menu_item_check label="Botão de gestos" name="ShowGestureButton"/> <menu_item_check label="Botão de movimento" name="ShowMoveButton"/> <menu_item_check label="Botão de ver" name="ShowCameraButton"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml index 1b1efd3270448befc153a9a2b5fc728f541690ca..7aa3b836a44cf2ba5036fe1390d744bc4dbac8eb 100644 --- a/indra/newview/skins/default/xui/pt/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml @@ -25,6 +25,7 @@ <menu_item_call label="Nova roupa de baixo" name="New Underpants"/> <menu_item_call label="Nova máscara alfa" name="New Alpha Mask"/> <menu_item_call label="Nova tatuagem" name="New Tattoo"/> + <menu_item_call label="Novo fÃsico" name="New Physics"/> </menu> <menu label="Nova parte do corpo" name="New Body Parts"> <menu_item_call label="Nova forma" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml index 2723f39287d43544a58066c4b02ad5208d5088e4..9f345b5b6ed3f97a01171cc6669f0c1d64e80291 100644 --- a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml @@ -23,6 +23,7 @@ <menu_item_call label="Novas roupa de baixo" name="New Underpants"/> <menu_item_call label="Novo alpha" name="New Alpha"/> <menu_item_call label="Nova tatuagem" name="New Tattoo"/> + <menu_item_call label="Novo fÃsico" name="New Physics"/> </menu> <menu label="Nova parte do corpo" name="New Body Parts"> <menu_item_call label="Nova forma" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/pt/menu_media_ctrl.xml b/indra/newview/skins/default/xui/pt/menu_media_ctrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..44117c886523bb929f2ed8f3bf5d51122f4cba29 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_media_ctrl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="media ctrl context menu"> + <menu_item_call label="Cortar" name="Cut"/> + <menu_item_call label="Cortar" name="Copy"/> + <menu_item_call label="Colar" name="Paste"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml b/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml index 11b3e653c66cc3b5734c5b3dfbadf97a81b5accb..894f1d741cf570a52a3b5c0b018f8cf326f40700 100644 --- a/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="Gear Outfit"> +<toggleable_menu name="Gear Outfit"> <menu_item_call label="Vestir - Substituir look atual" name="wear"/> <menu_item_call label="Vestir - Adicionar ao look atual" name="wear_add"/> <menu_item_call label="Tirar - Tirar do look atual" name="take_off"/> @@ -14,6 +14,7 @@ <menu_item_call label="Nova camiseta" name="New Undershirt"/> <menu_item_call label="Novas roupa de baixo" name="New Underpants"/> <menu_item_call label="Novo alpha" name="New Alpha"/> + <menu_item_call label="Novo fÃsico" name="New Physics"/> <menu_item_call label="Nova tatuagem" name="New Tattoo"/> </menu> <menu label="Nova parte do corpo" name="New Body Parts"> @@ -24,4 +25,4 @@ </menu> <menu_item_call label="Renomear look" name="rename"/> <menu_item_call label="Excluir visual" name="delete_outfit"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index 538b20e01f341186b1222c2912d2d591e6c83c55..0a2a2994f6f9d350dfbf215995108097b41a10fd 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -336,4 +336,9 @@ </menu> <menu_item_call label="God Tools" name="God Tools"/> </menu> + <menu label="Admin" name="Deprecated"> + <menu label="Take Off Clothing" name="Take Off Clothing"> + <menu_item_call label="FÃsico" name="Physics"/> + </menu> + </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 31e29fb6c15eab8e7932dac7388b8b54a6425b85..4adfe8e37fe285f99480bd9a059228099d0e8efe 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2822,6 +2822,13 @@ Silenciar todos? <notification label="Levantar-se" name="HintSit"> Para se levantar quando estiver sentado, clique em Levantar-se </notification> + <notification label="Falar" name="HintSpeak"> + Clique no botão Falar para ligar ou desligar o microfone. + +Clique na seta para cima para ver o painel de controles de voz. + +Se o botão Falar for ocultado, o recurso de voz será desabilitado. + </notification> <notification label="Explore o mundo" name="HintDestinationGuide"> O Guia de Destinos traz milhares de lugares novos para você explorar e conhecer. Selecione um lugar, clique em Teletransportar e comece suas descobertas. </notification> @@ -2831,12 +2838,14 @@ Silenciar todos? <notification label="Movimentar" name="HintMove"> Para andar ou correr, clique no botão Movimentar e use as setas para controlar a direção. Ou use as setas do teclado. </notification> + <notification label="" name="HintMoveClick"> + 1. Clique para andar Clique em qualquer lugar no solo para andar até o local. + +2. Clique e arraste para girar a exibição Clique e arraste em qualquer lugar no mundo para girar a exibição + </notification> <notification label="Nome de tela" name="HintDisplayName"> Defina seu nome de tela personalizável. O nome de tele é separado do seu nome de usuário, que não pode ser modificado. Você pode mudar a visualização dos nomes de outras pessoas nas suas preferências. </notification> - <notification label="Movimentar" name="HintMoveArrows"> - Para andar, use as setas do teclado. Para correr, pressione a seta para cima duas vezes. - </notification> <notification label="Exibir" name="HintView"> Para mudar o ângulo de visualização, use os controles Órbita e Pan. Volte à visualização normal pressionando a tecla Escape ou começando a andar. </notification> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_physics.xml b/indra/newview/skins/default/xui/pt/panel_edit_physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..967aab8bc3b0c9fa6122d14ebbee4ae82b9c03d0 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_edit_physics.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="edit_physics_panel"> + <panel label="" name="accordion_panel"> + <accordion name="physics_accordion"> + <accordion_tab name="physics_breasts_updown_tab" title="Seios - movimento vertical"/> + <accordion_tab name="physics_breasts_inout_tab" title="Seios - decote"/> + <accordion_tab name="physics_breasts_leftright_tab" title="Seios - movimento lateral"/> + <accordion_tab name="physics_belly_tab" title="Barriga - movimento vertical"/> + <accordion_tab name="physics_butt_tab" title="Nádegas - movimento vertical"/> + <accordion_tab name="physics_butt_leftright_tab" title="Nádegas - movimento lateral"/> + <accordion_tab name="physics_advanced_tab" title="Parâmetros avançados"/> + </accordion> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml index 679bb524b44f648986862e3f291cd5950af81433..2e3e3d63058b417c39999911e566e9212768a246 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml @@ -45,6 +45,9 @@ <string name="edit_tattoo_title"> Editando tatuagem </string> + <string name="edit_physics_title"> + Editando o fÃsico + </string> <string name="shape_desc_text"> Forma: </string> @@ -90,6 +93,9 @@ <string name="tattoo_desc_text"> Tatuagem: </string> + <string name="physics_desc_text"> + FÃsico: + </string> <labeled_back_button label="Salvar" name="back_btn" tool_tip="Voltar à edição de look"/> <text name="edit_wearable_title" value="Editando forma"/> <panel label="Camisa" name="wearable_type_panel"> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml index 412bdbb13ed574f58b53dac901c3ccf61e0bad86..e5aa42aae0cb4bd00d55a7367a32f4ba146b5dbd 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml @@ -30,7 +30,9 @@ <spinner label="Transição de avisos de bate-papos por perto:" name="nearby_toasts_lifetime"/> <spinner label="Transição de avisos de bate-papos por perto:" name="nearby_toasts_fadingtime"/> <check_box name="translate_chat_checkbox"/> - <text name="translate_chb_label" >Traduzir bate-papo automaticamente (via Google)</text> + <text name="translate_chb_label"> + Traduzir bate-papo automaticamente (via Google) + </text> <text name="translate_language_text"> Traduzir bate-papo para: </text> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_colors.xml b/indra/newview/skins/default/xui/pt/panel_preferences_colors.xml index 5f2f341e3fdacfdbdddac7591e4bc86b8cd4f6c6..46d9517a9817c2f76aa2c742c4c556317f507a79 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_colors.xml @@ -14,7 +14,7 @@ Outros </text> <text name="text_box3"> - Objetos + Objects </text> <text name="text_box4"> Sistema diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml index c2efbf03003fe3ca556e2b5b98cfe90d080c9063..4b03c79a9edd0a49fecc3f7b1db584c93d3f2739 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml @@ -40,6 +40,10 @@ rápido <combo_box.item label="Avatares e objetos" name="3"/> <combo_box.item label="Tudo" name="4"/> </combo_box> + <slider label="FÃsico do avatar:" name="AvatarPhysicsDetail"/> + <text name="AvatarPhysicsDetailText"> + Baixo + </text> <slider label="Distancia de desenho:" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> m @@ -78,7 +82,7 @@ rápido Baixo </text> <text name="AvatarRenderingText"> - Renderização de Avatar: + Renderização do avatar: </text> <check_box initial_value="true" label="Atributos do Avatar" name="AvatarImpostors"/> <check_box initial_value="true" label="Melhoria de Hardware" name="AvatarVertexProgram"/> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml index 6053deb5b10f1ad937223000beccfc2527f77b07..4164147e5c355486795b83a648cac5e615076ac1 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml @@ -5,7 +5,9 @@ </panel.string> <slider label="Volume principal" name="System Volume"/> <check_box initial_value="true" name="mute_when_minimized"/> - <text name="mute_chb_label">Silenciar ao minimizar</text> + <text name="mute_chb_label"> + Silenciar ao minimizar + </text> <slider label="Botões" name="UI Volume"/> <slider label="Ambiente" name="Wind Volume"/> <slider label="Efeitos sonoros" name="SFX Volume"/> diff --git a/indra/newview/skins/default/xui/pt/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/pt/panel_scrolling_param_base.xml new file mode 100644 index 0000000000000000000000000000000000000000..0a5a2e257222575187755188422a7f078de6ccdb --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_scrolling_param_base.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="LLScrollingPanelParamBase"> + <slider label="[DESC]:" name="param slider"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 47813604ff7f67e65a7fe0329fb180594a73adcc..6466f42c7559990388d9a0379f2cae9f588c32b8 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -855,6 +855,9 @@ <string name="tattoo"> Tatuagem </string> + <string name="physics"> + FÃsico + </string> <string name="invalid"> Inválido </string> @@ -894,6 +897,9 @@ <string name="tattoo_not_worn"> Tatuagem não usada </string> + <string name="physics_not_worn"> + FÃsico não usado + </string> <string name="invalid_not_worn"> inválido </string> @@ -942,6 +948,9 @@ <string name="create_new_tattoo"> Criar nova tatuagem </string> + <string name="create_new_physics"> + Criar novo fÃsico + </string> <string name="create_new_invalid"> inválido </string> @@ -2177,6 +2186,114 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Bulbous Nose"> Nariz em bulbo </string> + <string name="Breast Physics Mass"> + Seios - massa + </string> + <string name="Breast Physics Smoothing"> + Seios - suavização + </string> + <string name="Breast Physics Gravity"> + Seios - gravidade + </string> + <string name="Breast Physics Drag"> + Seios - resistência do ar + </string> + <string name="Breast Physics InOut Max Effect"> + Efeito máximo + </string> + <string name="Breast Physics InOut Spring"> + Vibração + </string> + <string name="Breast Physics InOut Gain"> + Ganho + </string> + <string name="Breast Physics InOut Damping"> + Duração + </string> + <string name="Breast Physics UpDown Max Effect"> + Efeito máximo + </string> + <string name="Breast Physics UpDown Spring"> + Vibração + </string> + <string name="Breast Physics UpDown Gain"> + Ganho + </string> + <string name="Breast Physics UpDown Damping"> + Duração + </string> + <string name="Breast Physics LeftRight Max Effect"> + Efeito máximo + </string> + <string name="Breast Physics LeftRight Spring"> + Vibração + </string> + <string name="Breast Physics LeftRight Gain"> + Ganho + </string> + <string name="Breast Physics LeftRight Damping"> + Duração + </string> + <string name="Belly Physics Mass"> + Barriga - massa + </string> + <string name="Belly Physics Smoothing"> + Barriga - suavização + </string> + <string name="Belly Physics Gravity"> + Barriga - gravidade + </string> + <string name="Belly Physics Drag"> + Barriga - resistência do ar + </string> + <string name="Belly Physics UpDown Max Effect"> + Efeito máximo + </string> + <string name="Belly Physics UpDown Spring"> + Vibração + </string> + <string name="Belly Physics UpDown Gain"> + Ganho + </string> + <string name="Belly Physics UpDown Damping"> + Duração + </string> + <string name="Butt Physics Mass"> + Nádegas - massa + </string> + <string name="Butt Physics Smoothing"> + Nádegas - suavização + </string> + <string name="Butt Physics Gravity"> + Nádegas - gravidade + </string> + <string name="Butt Physics Drag"> + Nádegas - resistência do ar + </string> + <string name="Butt Physics UpDown Max Effect"> + Efeito máximo + </string> + <string name="Butt Physics UpDown Spring"> + Vibração + </string> + <string name="Butt Physics UpDown Gain"> + Ganho + </string> + <string name="Butt Physics UpDown Damping"> + Duração + </string> + <string name="Butt Physics LeftRight Max Effect"> + Efeito máximo + </string> + <string name="Butt Physics LeftRight Spring"> + Vibração + </string> + <string name="Butt Physics LeftRight Gain"> + Ganho + </string> + <string name="Butt Physics LeftRight Damping"> + Duração + </string> <string name="Bushy Eyebrows"> Sobrancelhas grossas </string> @@ -2186,6 +2303,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Butt Size"> Tamanho do traseiro </string> + <string name="Butt Gravity"> + Nádegas - gravidade + </string> <string name="bustle skirt"> Saia armada </string> @@ -3661,6 +3781,9 @@ Denunciar abuso <string name="New Tattoo"> Nova tatuagem </string> + <string name="New Physics"> + Novo fÃsico + </string> <string name="Invalid Wearable"> Item inválido </string> diff --git a/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml index d0a77e8c2a98c6ea5581d9681a04d3bb756c40f1..e0c0bd13d978097e34a0a06139b3cc524080b67e 100644 --- a/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml @@ -59,8 +59,8 @@ follows="left|right" /> </layout_panel> - <layout_panel - auto_resize="false" + <layout_panel + auto_resize="false" follows="right" height="28" layout="topleft" @@ -163,7 +163,7 @@ layout="topleft" left="0" name="destination_btn" - tool_tip="Shows destinations" + tool_tip="Shows destinations window" top="5" is_toggle="true" use_ellipses="true" diff --git a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml index 53def54aca0ef61ce6bdb89114c0b14667abcb38..c3f46f11e06c53de9ce83323f9d1be1924410ec4 100644 --- a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml @@ -23,5 +23,69 @@ orientation="vertical" top_pad="5" width="145"> + <layout_panel + auto_resize="false" + follows="top|left|right" + height="20" + layout="topleft" + left="2" + min_height="20" + width="140" + name="view_profile_btn_panel" + top="0" + user_resize="false"> + <button + follows="left|top|right" + height="23" + label="Profile" + name="view_profile_btn" + top="0" + width="140" /> + </layout_panel> + <layout_panel + auto_resize="false" + follows="top|left|right" + height="25" + layout="topleft" + min_height="25" + width="140" + name="add_friend_btn_panel" + user_resize="false"> + <button + follows="left|top|right" + height="23" + label="Add Friend" + name="add_friend_btn" + top="5" + width="140" /> + </layout_panel> + <layout_panel + auto_resize="false" + follows="top|left|right" + height="25" + layout="topleft" + min_height="25" + width="140" + name="teleport_btn_panel" + user_resize="false"> + <button + auto_resize="false" + follows="left|top|right" + height="23" + label="Teleport" + name="teleport_btn" + tool_tip = "Offer to teleport this person" + width="140" /> + </layout_panel> + <layout_panel + mouse_opaque="false" + auto_resize="true" + follows="top|left" + height="0" + layout="topleft" + min_height="0" + width="140" + name="spacer" + user_resize="false" /> </layout_stack> </panel> diff --git a/indra/newview/skins/minimal/xui/pl/floater_camera.xml b/indra/newview/skins/minimal/xui/pl/floater_camera.xml new file mode 100644 index 0000000000000000000000000000000000000000..5b9dd476160be1619e0ac4f9a28820d726ba8df5 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/floater_camera.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="camera_floater" title=""> + <floater.string name="rotate_tooltip"> + Obracaj kamerÄ™ wokół obiektu + </floater.string> + <floater.string name="zoom_tooltip"> + Najedź kamerÄ… w kierunku obiektu + </floater.string> + <floater.string name="move_tooltip"> + Poruszaj kamerÄ… w dół/górÄ™ oraz w prawo/lewo + </floater.string> + <floater.string name="camera_modes_title"> + Ustawienia + </floater.string> + <floater.string name="pan_mode_title"> + W prawo lub w lewo + </floater.string> + <floater.string name="presets_mode_title"> + Ustaw widok + </floater.string> + <floater.string name="free_mode_title"> + Zobacz obiekt + </floater.string> + <panel name="controls"> + <panel name="preset_views_list"> + <panel_camera_item name="front_view"> + <panel_camera_item.text name="front_view_text"> + Widok z przodu + </panel_camera_item.text> + </panel_camera_item> + <panel_camera_item name="group_view"> + <panel_camera_item.text name="side_view_text"> + PodglÄ…d grupy + </panel_camera_item.text> + </panel_camera_item> + <panel_camera_item name="rear_view"> + <panel_camera_item.text name="rear_view_text"> + Widok z tyÅ‚u + </panel_camera_item.text> + </panel_camera_item> + </panel> + <panel name="camera_modes_list"> + <panel_camera_item name="object_view"> + <panel_camera_item.text name="object_view_text"> + Widok obiektu + </panel_camera_item.text> + </panel_camera_item> + <panel_camera_item name="mouselook_view"> + <panel_camera_item.text name="mouselook_view_text"> + Widok panoramiczny + </panel_camera_item.text> + </panel_camera_item> + </panel> + <panel name="zoom" tool_tip="Najedź kamerÄ… w kierunku obiektu"> + <joystick_rotate name="cam_rotate_stick" tool_tip="Obracaj kamerÄ™ wokoÅ‚ osi"/> + <slider_bar name="zoom_slider" tool_tip="Przybliż kamerÄ™ do ogniskowej"/> + <joystick_track name="cam_track_stick" tool_tip="Poruszaj kamerÄ… w górÄ™, w dół, w lewo i w prawo"/> + </panel> + </panel> + <panel name="buttons"> + <button label="" name="presets_btn" tool_tip="Ustaw widok"/> + <button label="" name="pan_btn" tool_tip="Kamera horyzontalna"/> + <button label="" name="avatarview_btn" tool_tip="Ustawienia"/> + </panel> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/floater_help_browser.xml b/indra/newview/skins/minimal/xui/pl/floater_help_browser.xml new file mode 100644 index 0000000000000000000000000000000000000000..66fde04f887afdbd8e9fa6aa5fd2d5bb8a96f8ba --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/floater_help_browser.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_help_browser" title="POMOC"> + <floater.string name="loading_text"> + Åadowanie... + </floater.string> + <layout_stack name="stack1"> + <layout_panel name="external_controls"/> + </layout_stack> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/floater_media_browser.xml b/indra/newview/skins/minimal/xui/pl/floater_media_browser.xml new file mode 100644 index 0000000000000000000000000000000000000000..02b7c6bc2bee40ef09a8b9ea549a6b8d026751ce --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/floater_media_browser.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_about" title="PRZEGLÄ„DARKA MEDIÓW"> + <floater.string name="home_page_url"> + http://www.secondlife.com + </floater.string> + <floater.string name="support_page_url"> + http://support.secondlife.com + </floater.string> + <layout_stack name="stack1"> + <layout_panel name="nav_controls"> + <button label="Wstecz" name="back"/> + <button label="Dalej" name="forward"/> + <button label="OdÅ›wież" name="reload"/> + <button label="Idź" name="go"/> + </layout_panel> + <layout_panel name="time_controls"> + <button label="przewiÅ„" name="rewind"/> + <button label="zatrzymaj" name="stop"/> + <button label="dalej" name="seek"/> + </layout_panel> + <layout_panel name="parcel_owner_controls"> + <button label="WyÅ›lij bieżącÄ… stronÄ™ do parceli" name="assign"/> + </layout_panel> + <layout_panel name="external_controls"> + <button label="Otwórz w przeglÄ…darce zewnÄ™trznej" name="open_browser"/> + <check_box label="Zawsze otwieraj w przeglÄ…darce zewnÄ™trznej" name="open_always"/> + <button label="Zamknij" name="close"/> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/pl/floater_nearby_chat.xml new file mode 100644 index 0000000000000000000000000000000000000000..7dc3e1f22ef6ae6136fa3e980f0d76abcd7f117e --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/floater_nearby_chat.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="nearby_chat" title="CZAT LOKALNY"> + <check_box label="TÅ‚umaczenie czatu (wspierane przez Google)" name="translate_chat_checkbox"/> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/floater_web_content.xml b/indra/newview/skins/minimal/xui/pl/floater_web_content.xml new file mode 100644 index 0000000000000000000000000000000000000000..e3096f1e54c9123110995802ac36e3d82a32a1bd --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/floater_web_content.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_web_content" title=""> + <layout_stack name="stack1"> + <layout_panel name="nav_controls"> + <button name="back" tool_tip="Wstecz"/> + <button name="forward" tool_tip="Dalej"/> + <button name="stop" tool_tip="Zatrzymaj"/> + <button name="reload" tool_tip="OdÅ›wież stronÄ™"/> + <combo_box name="address" tool_tip="Wpisz URL tutaj"/> + <icon name="media_secure_lock_flag" tool_tip="Zabezpieczona przeglÄ…darka"/> + <button name="popexternal" tool_tip="Otwórz bieżący URL w zewnÄ™trznej przeglÄ…darce"/> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/inspect_avatar.xml b/indra/newview/skins/minimal/xui/pl/inspect_avatar.xml new file mode 100644 index 0000000000000000000000000000000000000000..5e982c0185f9d0f1959bc9de4460c4eb48850623 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/inspect_avatar.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> +<floater name="inspect_avatar"> + <string name="Subtitle"> + [AGE] + </string> + <string name="Details"> + [SL_PROFILE] + </string> + <text name="user_details"> + To jest mój opis w Second Life. + </text> + <slider name="volume_slider" tool_tip="Poziom gÅ‚oÅ›noÅ›ci" value="0.5"/> + <button label="Dodaj znajomość" name="add_friend_btn"/> + <button label="IM" name="im_btn"/> + <button label="Profil" name="view_profile_btn"/> + <panel name="moderator_panel"> + <button label="WyÅ‚Ä…cz komunikacjÄ™ gÅ‚osowÄ…" name="disable_voice"/> + <button label="WÅ‚Ä…cz komunikacjÄ™ gÅ‚osowÄ…" name="enable_voice"/> + </panel> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/inspect_object.xml b/indra/newview/skins/minimal/xui/pl/inspect_object.xml new file mode 100644 index 0000000000000000000000000000000000000000..23d8ce77004e97fef09fab70c456268948dc71a1 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/inspect_object.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> +<floater name="inspect_object"> + <string name="Creator"> + Przez [CREATOR] + </string> + <string name="CreatorAndOwner"> + Twórca [CREATOR] +WÅ‚aÅ›ciciel [OWNER] + </string> + <string name="Price"> + L$[AMOUNT] + </string> + <string name="PriceFree"> + Darmowe! + </string> + <string name="Touch"> + Dotknij + </string> + <string name="Sit"> + UsiÄ…dź tutaj + </string> + <text name="object_name" value="Test Object Name That Is actually two lines and Really Long"/> + <text name="price_text"> + L$30,000 + </text> + <text name="object_description"> + This is a really long description for an object being as how it is at least 80 characters in length and so but maybe more like 120 at this point. Who knows, really? + </text> + <button label="Kup" name="buy_btn"/> + <button label="ZapÅ‚ać" name="pay_btn"/> + <button label="Weź kopiÄ™" name="take_free_copy_btn"/> + <button label="Dotknij" name="touch_btn"/> + <button label="UsiÄ…dź tutaj" name="sit_btn"/> + <button label="Otwórz" name="open_btn"/> + <icon name="secure_browsing" tool_tip="Zabezpiecz przeglÄ…danie"/> + <button label="WiÄ™cej" name="more_info_btn"/> +</floater> diff --git a/indra/newview/skins/minimal/xui/pl/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_add_wearable_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c572b4fc93e4081d4ea1d3d4a7fbd4bf4a50421 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_add_wearable_gear.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Add Wearable Gear Menu"> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug daty" name="sort_by_most_recent"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_by_name"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug typu" name="sort_by_type"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/pl/menu_attachment_other.xml new file mode 100644 index 0000000000000000000000000000000000000000..aacdad97e3e932105f1cc6f0e5d18064d2d37fdd --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_attachment_other.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- *NOTE: See also menu_avatar_other.xml --> +<context_menu name="Avatar Pie"> + <menu_item_call label="Zobacz profil" name="Profile..."/> + <menu_item_call label="Dodaj znajomość" name="Add Friend"/> + <menu_item_call label="IM" name="Send IM..."/> + <menu_item_call label="ZadzwoÅ„" name="Call"/> + <menu_item_call label="ZaproÅ› do grupy" name="Invite..."/> + <menu_item_call label="Zablokuj" name="Avatar Mute"/> + <menu_item_call label="Raport" name="abuse"/> + <menu_item_call label="Unieruchom" name="Freeze..."/> + <menu_item_call label="Wyrzuć" name="Eject..."/> + <menu_item_call label="Debugowanie tekstur" name="Debug..."/> + <menu_item_call label="Przybliż" name="Zoom In"/> + <menu_item_call label="ZapÅ‚ać" name="Pay..."/> + <menu_item_call label="Sprawdź" name="Object Inspect"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/pl/menu_attachment_self.xml new file mode 100644 index 0000000000000000000000000000000000000000..163b3a231e266d7dbc4b77d765932f973d38273c --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_attachment_self.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Attachment Pie"> + <menu_item_call label="Dotknij" name="Attachment Object Touch"/> + <menu_item_call label="Edytuj" name="Edit..."/> + <menu_item_call label="OdÅ‚Ä…cz" name="Detach"/> + <menu_item_call label="UsiÄ…dź tutaj" name="Sit Down Here"/> + <menu_item_call label="WstaÅ„" name="Stand Up"/> + <menu_item_call label="Mój wyglÄ…d" name="Change Outfit"/> + <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> + <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Moi znajomi" name="Friends..."/> + <menu_item_call label="Moje grupy" name="Groups..."/> + <menu_item_call label="Mój profil" name="Profile..."/> + <menu_item_call label="Debugowanie tekstur" name="Debug..."/> + <menu_item_call label="Opuść" name="Drop"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/pl/menu_avatar_icon.xml new file mode 100644 index 0000000000000000000000000000000000000000..e8d2b14231fd1e8ad90f2fc34fe5daabf042cd14 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_avatar_icon.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Avatar Icon Menu"> + <menu_item_call label="Profil" name="Show Profile"/> + <menu_item_call label="Czat/IM..." name="Send IM"/> + <menu_item_call label="Dodaj znajomość..." name="Add Friend"/> + <menu_item_call label="UsuÅ„..." name="Remove Friend"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/pl/menu_avatar_other.xml new file mode 100644 index 0000000000000000000000000000000000000000..dcf7921badc165902f342d4df3944ae8f3419129 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_avatar_other.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- *NOTE: See also menu_attachment_other.xml --> +<context_menu name="Avatar Pie"> + <menu_item_call label="Zobacz profil" name="Profile..."/> + <menu_item_call label="Dodaj znajomość" name="Add Friend"/> + <menu_item_call label="IM" name="Send IM..."/> + <menu_item_call label="ZadzwoÅ„" name="Call"/> + <menu_item_call label="ZaproÅ› do grupy" name="Invite..."/> + <menu_item_call label="Zablokuj" name="Avatar Mute"/> + <menu_item_call label="Raport" name="abuse"/> + <menu_item_call label="Unieruchom" name="Freeze..."/> + <menu_item_call label="Wyrzuć" name="Eject..."/> + <menu_item_call label="Debugowanie tekstur" name="Debug..."/> + <menu_item_call label="Przybliż" name="Zoom In"/> + <menu_item_call label="ZapÅ‚ać" name="Pay..."/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/pl/menu_avatar_self.xml new file mode 100644 index 0000000000000000000000000000000000000000..d481475803bcecfd055b97f6fd438279a8bae171 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_avatar_self.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Self Pie"> + <menu_item_call label="UsiÄ…dź tu" name="Sit Down Here"/> + <menu_item_call label="WstaÅ„" name="Stand Up"/> + <context_menu label="Zdejmij" name="Take Off >"> + <context_menu label="Ubrania" name="Clothes >"> + <menu_item_call label="KoszulÄ™" name="Shirt"/> + <menu_item_call label="Spodnie" name="Pants"/> + <menu_item_call label="SpódnicÄ™" name="Skirt"/> + <menu_item_call label="Buty" name="Shoes"/> + <menu_item_call label="Skarpetki" name="Socks"/> + <menu_item_call label="KurtkÄ™" name="Jacket"/> + <menu_item_call label="RÄ™kawiczki" name="Gloves"/> + <menu_item_call label="Podkoszulek" name="Self Undershirt"/> + <menu_item_call label="BieliznÄ™" name="Self Underpants"/> + <menu_item_call label="Tatuaż" name="Self Tattoo"/> + <menu_item_call label="Ubranie alpha" name="Self Alpha"/> + <menu_item_call label="Wszystko" name="All Clothes"/> + </context_menu> + <context_menu label="HUD" name="Object Detach HUD"/> + <context_menu label="OdÅ‚Ä…cz" name="Object Detach"/> + <menu_item_call label="OdÅ‚Ä…cz wszystko" name="Detach All"/> + </context_menu> + <menu_item_call label="Mój wyglÄ…d" name="Chenge Outfit"/> + <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> + <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Moi znajomi" name="Friends..."/> + <menu_item_call label="Moje grupy" name="Groups..."/> + <menu_item_call label="Mój profil" name="Profile..."/> + <menu_item_call label="Debugowanie tekstur" name="Debug..."/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/pl/menu_bottomtray.xml new file mode 100644 index 0000000000000000000000000000000000000000..8da40dcedfbd5929d2fe53f36dad80dc510ccc41 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_bottomtray.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="hide_camera_move_controls_menu"> + <menu_item_check label="Rozmowy gÅ‚osowe aktywne" name="EnableVoiceChat"/> + <menu_item_check label="Przycisk gesturki" name="ShowGestureButton"/> + <menu_item_check label="Przycisk ruchu" name="ShowMoveButton"/> + <menu_item_check label="Przycisk widoku" name="ShowCameraButton"/> + <menu_item_check label="Przycisk zdjęć" name="ShowSnapshotButton"/> + <menu_item_check label="Buduj" name="ShowBuildButton"/> + <menu_item_check label="Szukaj" name="ShowSearchButton"/> + <menu_item_check label="Mapa" name="ShowWorldMapButton"/> + <menu_item_check label="Mini-Mapa" name="ShowMiniMapButton"/> + <menu_item_call label="Wytnij" name="NearbyChatBar_Cut"/> + <menu_item_call label="Kopiuj" name="NearbyChatBar_Copy"/> + <menu_item_call label="Wklej" name="NearbyChatBar_Paste"/> + <menu_item_call label="UsuÅ„" name="NearbyChatBar_Delete"/> + <menu_item_call label="Zaznacz wszystko" name="NearbyChatBar_Select_All"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/pl/menu_cof_attachment.xml new file mode 100644 index 0000000000000000000000000000000000000000..4e5407601b455003e7873bc683569d53624ef755 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_cof_attachment.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="COF Attachment"> + <menu_item_call label="OdÅ‚Ä…cz" name="detach"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/pl/menu_cof_body_part.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee60d3feb657db0a28da74b50ae820a130fd83ee --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_cof_body_part.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="COF Body"> + <menu_item_call label="ZastÄ…p" name="replace"/> + <menu_item_call label="Edytuj" name="edit"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/pl/menu_cof_clothing.xml new file mode 100644 index 0000000000000000000000000000000000000000..ad4390013787524fe0ca0a5c638f5022367ad111 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_cof_clothing.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="COF Clothing"> + <menu_item_call label="Zdejmij" name="take_off"/> + <menu_item_call label="Edytuj" name="edit"/> + <menu_item_call label="ZastÄ…p" name="replace"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_cof_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..9fba39be1ac3a325ee7246563876f3fe5fa14dde --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_cof_gear.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Gear COF"> + <menu label="Nowe ubranie" name="COF.Gear.New_Clothes"/> + <menu label="Nowe części ciaÅ‚a" name="COF.Geear.New_Body_Parts"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_edit.xml b/indra/newview/skins/minimal/xui/pl/menu_edit.xml new file mode 100644 index 0000000000000000000000000000000000000000..578e270fed0f15465e3a5f41ad4830473a74c3b9 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_edit.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu label="Edycja" name="Edit"> + <menu_item_call label="Cofnij" name="Undo"/> + <menu_item_call label="Powtórz" name="Redo"/> + <menu_item_call label="Wytnij" name="Cut"/> + <menu_item_call label="Kopiuj" name="Copy"/> + <menu_item_call label="Wklej" name="Paste"/> + <menu_item_call label="UsuÅ„" name="Delete"/> + <menu_item_call label="Powiel" name="Duplicate"/> + <menu_item_call label="Zaznacz wszystko" name="Select All"/> + <menu_item_call label="Odznacz" name="Deselect"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_favorites.xml b/indra/newview/skins/minimal/xui/pl/menu_favorites.xml new file mode 100644 index 0000000000000000000000000000000000000000..7310ff5c2765b984bc26c51453dcf41089c6aab5 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_favorites.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Popup"> + <menu_item_call label="Teleportuj" name="Teleport To Landmark"/> + <menu_item_call label="Zobacz/Edytuj Ulubione miejsce" name="Landmark Open"/> + <menu_item_call label="Kopiuj SLurl" name="Copy slurl"/> + <menu_item_call label="Pokaż na mapie" name="Show On Map"/> + <menu_item_call label="Kopiuj" name="Landmark Copy"/> + <menu_item_call label="Wklej" name="Landmark Paste"/> + <menu_item_call label="UsuÅ„" name="Delete"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_gesture_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..a72dec22fc1dc2612c097b528a2af56ba3ce7b3d --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_gesture_gear.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_gesture_gear"> + <menu_item_call label="Dodaj/UsuÅ„ z Ulubionych" name="activate"/> + <menu_item_call label="Kopiuj" name="copy_gesture"/> + <menu_item_call label="Wklej" name="paste"/> + <menu_item_call label="Kopiuj UUID" name="copy_uuid"/> + <menu_item_call label="Zapisz do obecnego zestawu ubrania" name="save_to_outfit"/> + <menu_item_call label="Edytuj" name="edit_gesture"/> + <menu_item_call label="Sprawdź" name="inspect"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_group_plus.xml b/indra/newview/skins/minimal/xui/pl/menu_group_plus.xml new file mode 100644 index 0000000000000000000000000000000000000000..83be4d38c515a9713f1b1aec807432df20ae8c46 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_group_plus.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_call label="DoÅ‚Ä…cz do grupy..." name="item_join"/> + <menu_item_call label="Nowa grupa..." name="item_new"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/pl/menu_hide_navbar.xml new file mode 100644 index 0000000000000000000000000000000000000000..19d9510cd3f05c26ac4174f8308ea7febacf338c --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_hide_navbar.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="hide_navbar_menu"> + <menu_item_check label="Pokaż pasek Nawigacji" name="ShowNavbarNavigationPanel"/> + <menu_item_check label="Pokaż pasek Ulubionych" name="ShowNavbarFavoritesPanel"/> + <menu_item_check label="Pokaż pasek mini-lokalizacji" name="ShowMiniLocationPanel"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/pl/menu_im_well_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..207bc2211b30df0242c54f17dfc33ba95794f5f2 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_im_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="IM Well Button Context Menu"> + <menu_item_call label="Zamknij wszystkie" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_adhoc.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ead44878a3f23d27dda5e640c3fe4ae454a19aa --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_adhoc.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="IMChiclet AdHoc Menu"> + <menu_item_call label="ZakoÅ„cz rozmowÄ™" name="End Session"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_group.xml new file mode 100644 index 0000000000000000000000000000000000000000..2b9a362123b23e779dd2701d2e98c53920b18a20 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_group.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="IMChiclet Group Menu"> + <menu_item_call label="O grupie" name="Show Profile"/> + <menu_item_call label="Pokaż sesjÄ™" name="Chat"/> + <menu_item_call label="ZakoÅ„cz rozmowÄ™" name="End Session"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_p2p.xml new file mode 100644 index 0000000000000000000000000000000000000000..8924d6db3e1b1fa6b7156902b1122ccc265cffb4 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_imchiclet_p2p.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="IMChiclet P2P Menu"> + <menu_item_call label="Zobacz profil" name="Show Profile"/> + <menu_item_call label="Dodaj znajomość" name="Add Friend"/> + <menu_item_call label="Pokaż sesjÄ™" name="Send IM"/> + <menu_item_call label="ZakoÅ„cz rozmowÄ™" name="End Session"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_inspect_avatar_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..59560f236c279fa3c4acfa2bfba197fecb1bb690 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inspect_avatar_gear.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<toggleable_menu name="Gear Menu"> + <menu_item_call label="Zobacz profil" name="view_profile"/> + <menu_item_call label="Dodaj znajomość" name="add_friend"/> + <menu_item_call label="IM" name="im"/> + <menu_item_call label="ZadzwoÅ„" name="call"/> + <menu_item_call label="Teleportuj" name="teleport"/> + <menu_item_call label="ZaproÅ› do grupy" name="invite_to_group"/> + <menu_item_call label="Zablokuj" name="block"/> + <menu_item_call label="Odblokuj" name="unblock"/> + <menu_item_call label="Raport" name="report"/> + <menu_item_call label="Unieruchom" name="freeze"/> + <menu_item_call label="Wyrzuć" name="eject"/> + <menu_item_call label="Kopnij" name="kick"/> + <menu_item_call label="CSR" name="csr"/> + <menu_item_call label="Debugowanie tekstur" name="debug"/> + <menu_item_call label="Znajdź na mapie" name="find_on_map"/> + <menu_item_call label="Przybliż" name="zoom_in"/> + <menu_item_call label="ZapÅ‚ać" name="pay"/> + <menu_item_call label="UdostÄ™pnij" name="share"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_inspect_object_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..c12bd490ff98485bcd41eae09577487f10c63798 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inspect_object_gear.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu name="Gear Menu"> + <menu_item_call label="Dotknij" name="touch"/> + <menu_item_call label="UsiÄ…dź" name="sit"/> + <menu_item_call label="ZapÅ‚ać" name="pay"/> + <menu_item_call label="Kup" name="buy"/> + <menu_item_call label="Weź" name="take"/> + <menu_item_call label="Weź kopiÄ™" name="take_copy"/> + <menu_item_call label="Otwórz" name="open"/> + <menu_item_call label="Edytuj" name="edit"/> + <menu_item_call label="Ubierz" name="wear"/> + <menu_item_call label="Dodaj" name="add"/> + <menu_item_call label="Raport" name="report"/> + <menu_item_call label="Zablokuj" name="block"/> + <menu_item_call label="Przybliż" name="zoom_in"/> + <menu_item_call label="UsuÅ„" name="remove"/> + <menu_item_call label="WiÄ™cej informacji" name="more_info"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_inspect_self_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4ef9761d9d73eaac285a9d9b8dd6053157e1a1d --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inspect_self_gear.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="Gear Menu"> + <menu_item_call label="UsiÄ…dź tutaj" name="Sit Down Here"/> + <menu_item_call label="WstaÅ„" name="Stand Up"/> + <context_menu label="Zdejmij" name="Take Off >"> + <context_menu label="Ubranie" name="Clothes >"> + <menu_item_call label="Bluzka" name="Shirt"/> + <menu_item_call label="Spodnie" name="Pants"/> + <menu_item_call label="Spódnica" name="Skirt"/> + <menu_item_call label="Buty" name="Shoes"/> + <menu_item_call label="Skarpetki" name="Socks"/> + <menu_item_call label="Kurtka" name="Jacket"/> + <menu_item_call label="RÄ™kawiczki" name="Gloves"/> + <menu_item_call label="Podkoszulek" name="Self Undershirt"/> + <menu_item_call label="Bielizna" name="Self Underpants"/> + <menu_item_call label="Tatuaż" name="Self Tattoo"/> + <menu_item_call label="Alpha" name="Self Alpha"/> + <menu_item_call label="Ubranie" name="All Clothes"/> + </context_menu> + <context_menu label="HUD" name="Object Detach HUD"/> + <context_menu label="OdÅ‚Ä…cz" name="Object Detach"/> + <menu_item_call label="OdÅ‚Ä…cz wszystko" name="Detach All"/> + </context_menu> + <menu_item_call label="ZmieÅ„ strój" name="Chenge Outfit"/> + <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> + <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Znajomi" name="Friends..."/> + <menu_item_call label="Moje grupy" name="Groups..."/> + <menu_item_call label="Mój profil" name="Profile..."/> + <menu_item_call label="Debugowanie tekstur" name="Debug..."/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/pl/menu_inv_offer_chiclet.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ef0f2f7a48925dd5026047ff49a51be7aff7cbf --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inv_offer_chiclet.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="InvOfferChiclet Menu"> + <menu_item_call label="Zamknij" name="Close"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inventory.xml b/indra/newview/skins/minimal/xui/pl/menu_inventory.xml new file mode 100644 index 0000000000000000000000000000000000000000..e47ffa0e188bfa756de60738fce87230005bdb48 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inventory.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Popup"> + <menu_item_call label="UdostÄ™pnij" name="Share"/> + <menu_item_call label="Kupuj" name="Task Buy"/> + <menu_item_call label="Otwórz" name="Task Open"/> + <menu_item_call label="Odtwarzaj" name="Task Play"/> + <menu_item_call label="WÅ‚aÅ›ciwoÅ›ci" name="Task Properties"/> + <menu_item_call label="ZmieÅ„ nazwÄ™" name="Task Rename"/> + <menu_item_call label="UsuÅ„" name="Task Remove"/> + <menu_item_call label="Opróżnij Kosz" name="Empty Trash"/> + <menu_item_call label="Opróżnij Folder Zgubione i odnalezione" name="Empty Lost And Found"/> + <menu_item_call label="Nowy folder" name="New Folder"/> + <menu_item_call label="Nowy skrypt" name="New Script"/> + <menu_item_call label="Nowa nota" name="New Note"/> + <menu_item_call label="Nowa gesturka" name="New Gesture"/> + <menu label="Nowe Ubranie" name="New Clothes"> + <menu_item_call label="Nowa koszula" name="New Shirt"/> + <menu_item_call label="Nowe spodnie" name="New Pants"/> + <menu_item_call label="Nowe buty" name="New Shoes"/> + <menu_item_call label="Nowe skarpety" name="New Socks"/> + <menu_item_call label="Nowa kurtka" name="New Jacket"/> + <menu_item_call label="Nowa spódnica" name="New Skirt"/> + <menu_item_call label="Nowe rÄ™kawiczki" name="New Gloves"/> + <menu_item_call label="Nowy podkoszulek" name="New Undershirt"/> + <menu_item_call label="Nowa bielizna" name="New Underpants"/> + <menu_item_call label="Nowa maska alpha" name="New Alpha Mask"/> + <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> + </menu> + <menu label="Nowa Część CiaÅ‚a" name="New Body Parts"> + <menu_item_call label="Nowy ksztaÅ‚t" name="New Shape"/> + <menu_item_call label="Nowa skórka" name="New Skin"/> + <menu_item_call label="Nowe wÅ‚osy" name="New Hair"/> + <menu_item_call label="Nowe oczy" name="New Eyes"/> + </menu> + <menu label="ZmieÅ„ CzcionkÄ™" name="Change Type"> + <menu_item_call label="DomyÅ›lna" name="Default"/> + <menu_item_call label="RÄ™kawiczki" name="Gloves"/> + <menu_item_call label="Kurtka" name="Jacket"/> + <menu_item_call label="Spodnie" name="Pants"/> + <menu_item_call label="KsztaÅ‚t" name="Shape"/> + <menu_item_call label="Buty" name="Shoes"/> + <menu_item_call label="Koszula" name="Shirt"/> + <menu_item_call label="Spódnica" name="Skirt"/> + <menu_item_call label="Bielizna" name="Underpants"/> + <menu_item_call label="Podkoszulek" name="Undershirt"/> + </menu> + <menu_item_call label="Teleportuj" name="Landmark Open"/> + <menu_item_call label="Otwórz" name="Animation Open"/> + <menu_item_call label="Otwórz" name="Sound Open"/> + <menu_item_call label="ZmieÅ„ strój" name="Replace Outfit"/> + <menu_item_call label="Dodaj do stroju" name="Add To Outfit"/> + <menu_item_call label="UsuÅ„ obiekt" name="Purge Item"/> + <menu_item_call label="Przywróć obiekt" name="Restore Item"/> + <menu_item_call label="Otwórz" name="Open"/> + <menu_item_call label="Otwórz oryginalne" name="Open Original"/> + <menu_item_call label="WÅ‚aÅ›ciwoÅ›ci" name="Properties"/> + <menu_item_call label="ZmieÅ„ nazwÄ™" name="Rename"/> + <menu_item_call label="Kopiuj dane UUID" name="Copy Asset UUID"/> + <menu_item_call label="Kopiuj" name="Copy"/> + <menu_item_call label="Wklej" name="Paste"/> + <menu_item_call label="Wklej jako link" name="Paste As Link"/> + <menu_item_call label="UsuÅ„" name="Remove Link"/> + <menu_item_call label="UsuÅ„" name="Delete"/> + <menu_item_call label="Skasuj folder systemu" name="Delete System Folder"/> + <menu_item_call label="Rozpocznij konferencjÄ™ czatowÄ…" name="Conference Chat Folder"/> + <menu_item_call label="Odtwarzaj" name="Sound Play"/> + <menu_item_call label="O Miejscu" name="About Landmark"/> + <menu_item_call label="Używaj in-world" name="Animation Play"/> + <menu_item_call label="Odtwarzaj lokalnie" name="Animation Audition"/> + <menu_item_call label="WyÅ›lij IM" name="Send Instant Message"/> + <menu_item_call label="Teleportuj..." name="Offer Teleport..."/> + <menu_item_call label="Rozpocznij konferencjÄ™ czatowÄ…" name="Conference Chat"/> + <menu_item_call label="Aktywuj" name="Activate"/> + <menu_item_call label="Deaktywuj" name="Deactivate"/> + <menu_item_call label="Zapisz jako" name="Save As"/> + <menu_item_call label="OdÅ‚Ä…cz od siebie" name="Detach From Yourself"/> + <menu_item_call label="Załóż" name="Wearable And Object Wear"/> + <menu label="DoÅ‚Ä…cz do" name="Attach To"/> + <menu label="DoÅ‚Ä…cz do zaÅ‚Ä…czników HUD" name="Attach To HUD"/> + <menu_item_call label="Edytuj" name="Wearable Edit"/> + <menu_item_call label="Dodaj" name="Wearable Add"/> + <menu_item_call label="Zdejmij" name="Take Off"/> + <menu_item_call label="--brak opcji--" name="--no options--"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/pl/menu_inventory_add.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a56586aafc734e61412a951bd8de451a123aec6 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inventory_add.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_inventory_add"> + <menu label="ZaÅ‚aduj" name="upload"> + <menu_item_call label="obraz (L$[COST])..." name="Upload Image"/> + <menu_item_call label="dźwiÄ™k (L$[COST])..." name="Upload Sound"/> + <menu_item_call label="animacjÄ™ (L$[COST])..." name="Upload Animation"/> + <menu_item_call label="zbiór plików (L$[COST] za jeden plik)..." name="Bulk Upload"/> + <menu_item_call label="Ustaw domyÅ›lne pozwolenia Å‚adowania" name="perm prefs"/> + </menu> + <menu_item_call label="Nowy folder" name="New Folder"/> + <menu_item_call label="Nowy skrypt" name="New Script"/> + <menu_item_call label="Nowa nota" name="New Note"/> + <menu_item_call label="Nowa gesturka" name="New Gesture"/> + <menu label="Nowe Ubranie" name="New Clothes"> + <menu_item_call label="Nowa koszula" name="New Shirt"/> + <menu_item_call label="Nowe spodnie" name="New Pants"/> + <menu_item_call label="Nowe buty" name="New Shoes"/> + <menu_item_call label="Nowe skarpetki" name="New Socks"/> + <menu_item_call label="Nowa kurtka" name="New Jacket"/> + <menu_item_call label="Nowa spódnica" name="New Skirt"/> + <menu_item_call label="Nowe rÄ™kawiczki" name="New Gloves"/> + <menu_item_call label="Nowy podkoszulek" name="New Undershirt"/> + <menu_item_call label="Nowa bielizna" name="New Underpants"/> + <menu_item_call label="Nowa maska alpha" name="New Alpha"/> + <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> + </menu> + <menu label="Nowa Część CiaÅ‚a" name="New Body Parts"> + <menu_item_call label="Nowy ksztaÅ‚t" name="New Shape"/> + <menu_item_call label="Nowa skórka" name="New Skin"/> + <menu_item_call label="Nowe wÅ‚osy" name="New Hair"/> + <menu_item_call label="Nowe oczy" name="New Eyes"/> + </menu> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/pl/menu_inventory_gear_default.xml new file mode 100644 index 0000000000000000000000000000000000000000..591c3a81d5f3d563c2c5b05179151130f4632efe --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_inventory_gear_default.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_gear_default"> + <menu_item_call label="Nowe okno Szafy" name="new_window"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_by_name"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug daty" name="sort_by_recent"/> + <menu_item_check label="Sortuj foldery zawsze wedÅ‚ug nazwy" name="sort_folders_by_name"/> + <menu_item_check label="Posortuj foldery systemowe od góry" name="sort_system_folders_to_top"/> + <menu_item_call label="Pokaż filtry" name="show_filters"/> + <menu_item_call label="Zresetuj filtry" name="reset_filters"/> + <menu_item_call label="Zamknij wszystkie foldery" name="close_folders"/> + <menu_item_call label="Opróżnij Zagubione i odnalezione" name="empty_lostnfound"/> + <menu_item_call label="Zapisz teksturÄ™ jako" name="Save Texture As"/> + <menu_item_call label="UdostÄ™pnij" name="Share"/> + <menu_item_call label="Znajdź oryginaÅ‚" name="Find Original"/> + <menu_item_call label="Znajdź wszystkie linki" name="Find All Links"/> + <menu_item_call label="Opróżnij Kosz" name="empty_trash"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_land.xml b/indra/newview/skins/minimal/xui/pl/menu_land.xml new file mode 100644 index 0000000000000000000000000000000000000000..cbfecaee56855bd8427660cbad9a8869f54a3ea2 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_land.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Land Pie"> + <menu_item_call label="O PosiadÅ‚oÅ›ci" name="Place Information..."/> + <menu_item_call label="UsiÄ…dź tutaj" name="Sit Here"/> + <menu_item_call label="Kup posiadÅ‚ość" name="Land Buy"/> + <menu_item_call label="Kup przepustkÄ™" name="Land Buy Pass"/> + <menu_item_call label="Buduj" name="Create"/> + <menu_item_call label="Edytuj teren" name="Edit Terrain"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_landmark.xml b/indra/newview/skins/minimal/xui/pl/menu_landmark.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa5808390c4d7a3a6c1ba7e475b6b383782da4d0 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_landmark.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="landmark_overflow_menu"> + <menu_item_call label="Kopiuj SLurl" name="copy"/> + <menu_item_call label="UsuÅ„" name="delete"/> + <menu_item_call label="Utwórz" name="pick"/> + <menu_item_call label="Dodaj do paska Ulubionych" name="add_to_favbar"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_login.xml b/indra/newview/skins/minimal/xui/pl/menu_login.xml new file mode 100644 index 0000000000000000000000000000000000000000..e50b69464119b2f3b2b020f5af4b6422adbdfbdf --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_login.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu_bar name="Login Menu"> + <menu label="Ja" name="File"> + <menu_item_call label="Ustawienia" name="Preferences..."/> + <menu_item_call label="WyÅ‚Ä…cz [APP_NAME]" name="Quit"/> + </menu> + <menu label="Pomoc" name="Help"> + <menu_item_call label="[SECOND_LIFE]: Pomoc" name="Second Life Help"/> + <menu_item_call label="O [APP_NAME]" name="About Second Life"/> + </menu> + <menu_item_check label="Pokaż ustawienia debugowania" name="Show Debug Menu"/> + <menu label="Debug" name="Debug"> + <menu_item_call label="Ustawienia debugowania" name="Debug Settings"/> + <menu_item_call label="Ustawienia UI/kolor" name="UI/Color Settings"/> + <menu label="UI Testy" name="UI Tests"/> + <menu_item_call label="Ustaw rozmiar interfejsu..." name="Set Window Size..."/> + <menu_item_call label="WyÅ›wietl TOS" name="TOS"/> + <menu_item_call label="WyÅ›wietl wiadomość krytycznÄ…" name="Critical"/> + <menu_item_call label="Test przeglÄ…darki mediów" name="Web Browser Test"/> + <menu_item_call label="Test zawartoÅ›ci strony" name="Web Content Floater Test"/> + <menu_item_check label="Pokaż siatkÄ™" name="Show Grid Picker"/> + <menu_item_call label="Pokaż konsolÄ™ ZawiadomieÅ„" name="Show Notifications Console"/> + </menu> +</menu_bar> diff --git a/indra/newview/skins/minimal/xui/pl/menu_mini_map.xml b/indra/newview/skins/minimal/xui/pl/menu_mini_map.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f869654165d268d4c23e4ed73383f0473b47979 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_mini_map.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Popup"> + <menu_item_call label="Zoom blisko" name="Zoom Close"/> + <menu_item_call label="Zoom Å›rednio" name="Zoom Medium"/> + <menu_item_call label="Zoom daleko" name="Zoom Far"/> + <menu_item_call label="Zoom domyÅ›lny" name="Zoom Default"/> + <menu_item_check label="Obróć mapÄ™" name="Rotate Map"/> + <menu_item_check label="Autocentrowanie" name="Auto Center"/> + <menu_item_call label="Zatrzymaj" name="Stop Tracking"/> + <menu_item_call label="Mapa Åšwiata" name="World Map"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_navbar.xml b/indra/newview/skins/minimal/xui/pl/menu_navbar.xml new file mode 100644 index 0000000000000000000000000000000000000000..1d434670eeea01435f615e6c5f3c2b819cdca8a4 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_navbar.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Navbar Menu"> + <menu_item_check label="Pokaż współrzÄ™dne" name="Show Coordinates"/> + <menu_item_check label="Pokaż wÅ‚aÅ›ciwoÅ›ci posiadÅ‚oÅ›ci" name="Show Parcel Properties"/> + <menu_item_call label="Landmark" name="Landmark"/> + <menu_item_call label="Wytnij" name="Cut"/> + <menu_item_call label="Kopiuj" name="Copy"/> + <menu_item_call label="Wklej" name="Paste"/> + <menu_item_call label="UsuÅ„" name="Delete"/> + <menu_item_call label="Zaznacz wszystko" name="Select All"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/pl/menu_nearby_chat.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe5bc6ba6f39a545357459212609220118016daf --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_nearby_chat.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="NearBy Chat Menu"> + <menu_item_call label="Pokaż osoby w pobliżu..." name="nearby_people"/> + <menu_item_check label="Pokaż zablokowany tekst" name="muted_text"/> + <menu_item_check label="WyÅ›wietlaj ikonki znajomych" name="show_buddy_icons"/> + <menu_item_check label="WyÅ›wietlaj imiona" name="show_names"/> + <menu_item_check label="WyÅ›wietlaj ikonki i imiona" name="show_icons_and_names"/> + <menu_item_call label="Rozmiar czcionki" name="font_size"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/pl/menu_notification_well_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd3d42f9b1facfeef347dcd3aeaaf36cbac0423e --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Zamknij" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_object.xml b/indra/newview/skins/minimal/xui/pl/menu_object.xml new file mode 100644 index 0000000000000000000000000000000000000000..3da6c5c8905b6b43975dfe532900bd11b7e4355a --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_object.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Object Pie"> + <menu_item_call label="Dotknij" name="Object Touch"> + <menu_item_call.on_enable name="EnableTouch" parameter="Dotknij"/> + </menu_item_call> + <menu_item_call label="Edytuj" name="Edit..."/> + <menu_item_call label="Buduj" name="Build"/> + <menu_item_call label="Otwórz" name="Open"/> + <menu_item_call label="UsiÄ…dź tutaj" name="Object Sit"/> + <menu_item_call label="WstaÅ„" name="Object Stand Up"/> + <menu_item_call label="Sprawdź" name="Object Inspect"/> + <menu_item_call label="Przybliż" name="Zoom In"/> + <context_menu label="Załóż na" name="Put On"> + <menu_item_call label="Załóż" name="Wear"/> + <menu_item_call label="Dodaj" name="Add"/> + <context_menu label="DoÅ‚Ä…cz" name="Object Attach"/> + <context_menu label="DoÅ‚Ä…cz HUD" name="Object Attach HUD"/> + </context_menu> + <context_menu label="ZarzÄ…dzaj" name="Remove"> + <menu_item_call label="Raport" name="Report Abuse..."/> + <menu_item_call label="Zablokuj" name="Object Mute"/> + <menu_item_call label="Zwróć" name="Return..."/> + </context_menu> + <menu_item_call label="Weź" name="Pie Object Take"/> + <menu_item_call label="Weź kopiÄ™" name="Take Copy"/> + <menu_item_call label="ZapÅ‚ać" name="Pay..."/> + <menu_item_call label="Kup" name="Buy..."/> + <menu_item_call label="Skasuj" name="Delete"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_object_icon.xml b/indra/newview/skins/minimal/xui/pl/menu_object_icon.xml new file mode 100644 index 0000000000000000000000000000000000000000..b499bca2dbfbd32c18c98b859dd4315d6348ba1f --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_object_icon.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Object Icon Menu"> + <menu_item_call label="Sprawdź..." name="Object Profile"/> + <menu_item_call label="Zablokuj..." name="Block"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_outfit_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a70e76ec7cb6a32136c781317a6e0f3dc2b86f2 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_outfit_gear.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Gear Outfit"> + <menu_item_call label="Załóż - ZastÄ…p obecny strój" name="wear"/> + <menu_item_call label="Załóż - Dodaj do bieżącego stroju" name="wear_add"/> + <menu_item_call label="Zdejmij - UsuÅ„ z obecnego stroju" name="take_off"/> + <menu label="Nowe ubranie" name="New Clothes"> + <menu_item_call label="Nowa koszula" name="New Shirt"/> + <menu_item_call label="Nowe spodnie" name="New Pants"/> + <menu_item_call label="Nowe buty" name="New Shoes"/> + <menu_item_call label="Nowe skarpetki" name="New Socks"/> + <menu_item_call label="Nowa kurtka" name="New Jacket"/> + <menu_item_call label="Nowa spódnica" name="New Skirt"/> + <menu_item_call label="Nowe rÄ™kawiczki" name="New Gloves"/> + <menu_item_call label="Nowa podkoszulka" name="New Undershirt"/> + <menu_item_call label="Nowa bielizna" name="New Underpants"/> + <menu_item_call label="Nowa maska alpha" name="New Alpha"/> + <menu_item_call label="Nowy tatuaż" name="New Tattoo"/> + </menu> + <menu label="Nowe części ciaÅ‚a" name="New Body Parts"> + <menu_item_call label="Nowy ksztaÅ‚t" name="New Shape"/> + <menu_item_call label="Nowa skórka" name="New Skin"/> + <menu_item_call label="Nowe wÅ‚osy" name="New Hair"/> + <menu_item_call label="Nowe oczy" name="New Eyes"/> + </menu> + <menu_item_call label="ZmieÅ„ nazwÄ™ stroju" name="rename"/> + <menu_item_call label="UsuÅ„ strój" name="delete_outfit"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/pl/menu_outfit_tab.xml new file mode 100644 index 0000000000000000000000000000000000000000..998e25f38ee12d50260a79628df0732c6a0178d9 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_outfit_tab.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Outfit"> + <menu_item_call label="Załóż - ZastÄ…p obecny strój" name="wear_replace"/> + <menu_item_call label="Załóż - Dodaj do obecnego stroju" name="wear_add"/> + <menu_item_call label="Zdejmij - UsuÅ„ z obecnego stroju" name="take_off"/> + <menu_item_call label="Edytuj strój" name="edit"/> + <menu_item_call label="ZmieÅ„ nazwÄ™ stroju" name="rename"/> + <menu_item_call label="UsuÅ„ strój" name="delete"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_participant_list.xml b/indra/newview/skins/minimal/xui/pl/menu_participant_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e591027887e7654c2e7c3ea37c6aad2c10f3256 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_participant_list.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Participant List Context Menu"> + <menu_item_check label="Sortuj wedÅ‚ug imienia" name="SortByName"/> + <menu_item_check label="Sortuj wedÅ‚ug ostatniego mówcy" name="SortByRecentSpeakers"/> + <menu_item_call label="Zobacz profil" name="View Profile"/> + <menu_item_call label="Dodaj znajomość" name="Add Friend"/> + <menu_item_call label="IM" name="IM"/> + <menu_item_call label="ZadzwoÅ„" name="Call"/> + <menu_item_call label="UdostÄ™pnij" name="Share"/> + <menu_item_call label="ZapÅ‚ać" name="Pay"/> + <menu_item_check label="PrzeglÄ…daj ikonki" name="View Icons"/> + <menu_item_check label="Zablokuj gÅ‚os" name="Block/Unblock"/> + <menu_item_check label="Zablokuj tekst" name="MuteText"/> + <context_menu label="Opcje Moderatora" name="Moderator Options"> + <menu_item_check label="Czat/IM dozwolony" name="AllowTextChat"/> + <menu_item_call label="Wycisz tego uczestnika" name="ModerateVoiceMuteSelected"/> + <menu_item_call label="Odblokuj wyciszenie tego uczestnika" name="ModerateVoiceUnMuteSelected"/> + <menu_item_call label="Wycisz wszystkich" name="ModerateVoiceMute"/> + <menu_item_call label="Cofnij wyciszenie wszystkim" name="ModerateVoiceUnmute"/> + </context_menu> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/pl/menu_people_friends_view_sort.xml new file mode 100644 index 0000000000000000000000000000000000000000..b62b85d30a4f8659e8afa4e6b8d1a5955f36c466 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_friends_view_sort.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_name"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug statusu" name="sort_status"/> + <menu_item_check label="WyÅ›wietlaj ikonki" name="view_icons"/> + <menu_item_check label="Zobacz udzielone prawa" name="view_permissions"/> + <menu_item_call label="Pokaż zablokowanych Rezydentów & obiekty" name="show_blocked_list"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_groups.xml b/indra/newview/skins/minimal/xui/pl/menu_people_groups.xml new file mode 100644 index 0000000000000000000000000000000000000000..ace5ebf888464b9c1aab41dd8797c22feaeb7301 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_groups.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_call label="Zobacz info" name="View Info"/> + <menu_item_call label="Czat" name="Chat"/> + <menu_item_call label="Rozmowa" name="Call"/> + <menu_item_call label="Aktywuj" name="Activate"/> + <menu_item_call label="Opuść" name="Leave"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/pl/menu_people_groups_view_sort.xml new file mode 100644 index 0000000000000000000000000000000000000000..c70ea2315f4fd8f108729ef45d76f6a71da7ad10 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_groups_view_sort.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_check label="WyÅ›wietlaj ikonki grupy" name="Display Group Icons"/> + <menu_item_call label="Opuść zaznaczone grupy" name="Leave Selected Group"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/pl/menu_people_nearby.xml new file mode 100644 index 0000000000000000000000000000000000000000..0111e0fd5125383ffb1a4687d3142257b95807da --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_nearby.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Avatar Context Menu"> + <menu_item_call label="Zobacz profil" name="View Profile"/> + <menu_item_call label="Dodaj do znajomych" name="Add Friend"/> + <menu_item_call label="UsuÅ„ z listy znajomych" name="Remove Friend"/> + <menu_item_call label="IM" name="IM"/> + <menu_item_call label="ZadzwoÅ„" name="Call"/> + <menu_item_call label="Mapa" name="Map"/> + <menu_item_call label="UdostÄ™pnij" name="Share"/> + <menu_item_call label="ZapÅ‚ać" name="Pay"/> + <menu_item_check label="Zablokuj/Odblokuj" name="Block/Unblock"/> + <menu_item_call label="Teleportuj" name="teleport"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/pl/menu_people_nearby_multiselect.xml new file mode 100644 index 0000000000000000000000000000000000000000..dcfc48fb606418674cb003f172e16e5247d5964c --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_nearby_multiselect.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Multi-Selected People Context Menu"> + <menu_item_call label="Dodaj znajomych" name="Add Friends"/> + <menu_item_call label="UsuÅ„ znajomych" name="Remove Friend"/> + <menu_item_call label="IM" name="IM"/> + <menu_item_call label="ZadzwoÅ„" name="Call"/> + <menu_item_call label="UdostÄ™pnij" name="Share"/> + <menu_item_call label="ZapÅ‚ać" name="Pay"/> + <menu_item_call label="Teleportuj" name="teleport"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/pl/menu_people_nearby_view_sort.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ec3820f84e888c5bc13ee47df866d53d55997b2 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_nearby_view_sort.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug ostatnich rozmówców" name="sort_by_recent_speakers"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_name"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug odlegÅ‚oÅ›ci" name="sort_distance"/> + <menu_item_check label="WyÅ›wietlaj ikonki" name="view_icons"/> + <menu_item_call label="Pokaż zablokowanych Rezydentów & obiekty" name="show_blocked_list"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/pl/menu_people_recent_view_sort.xml new file mode 100644 index 0000000000000000000000000000000000000000..b474a556bdad38e6f19fa4c2892a3ef251507b53 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_people_recent_view_sort.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_group_plus"> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug daty" name="sort_most"/> + <menu_item_check label="PorzÄ…dkuj wedÅ‚ug nazwy" name="sort_name"/> + <menu_item_check label="WyÅ›wietlaj ikonki" name="view_icons"/> + <menu_item_call label="Pokaż zablokowanych Rezydentów & obiekty" name="show_blocked_list"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_picks.xml b/indra/newview/skins/minimal/xui/pl/menu_picks.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f6e4b7fa80df9a2d9801c5aea2f2d3a9e4b2974 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_picks.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Picks"> + <menu_item_call label="Info" name="pick_info"/> + <menu_item_call label="Edytuj" name="pick_edit"/> + <menu_item_call label="Teleportuj" name="pick_teleport"/> + <menu_item_call label="Mapa" name="pick_map"/> + <menu_item_call label="UsuÅ„" name="pick_delete"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/pl/menu_picks_plus.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9c00f51a978c7ff28b5a47c8e373a9761fc05b3 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_picks_plus.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="picks_plus_menu"> + <menu_item_call label="Stwórz" name="create_pick"/> + <menu_item_call label="Nowa reklama" name="create_classified"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_place.xml b/indra/newview/skins/minimal/xui/pl/menu_place.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3b72d6abbddafed423f8ada857be161387c422c --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_place.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="place_overflow_menu"> + <menu_item_call label="Zapisz landmark" name="landmark"/> + <menu_item_call label="Utwórz" name="pick"/> + <menu_item_call label="Kup przepustkÄ™" name="pass"/> + <menu_item_call label="Edytuj" name="edit"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/pl/menu_place_add_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..3d0c1c87fb199763200ed65e5e3e7a00f9ead0bc --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_place_add_button.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_folder_gear"> + <menu_item_call label="Dodaj folder" name="add_folder"/> + <menu_item_call label="Dodaj do landmarków" name="add_landmark"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/pl/menu_places_gear_folder.xml new file mode 100644 index 0000000000000000000000000000000000000000..d1f283b7aa3c4672f6405d7aae7969493e624170 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_places_gear_folder.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_folder_gear"> + <menu_item_call label="Dodaj do landmarków" name="add_landmark"/> + <menu_item_call label="Dodaj folder" name="add_folder"/> + <menu_item_call label="Przywróć obiekt" name="restore_item"/> + <menu_item_call label="Wytnij" name="cut"/> + <menu_item_call label="Kopiuj" name="copy_folder"/> + <menu_item_call label="Wklej" name="paste"/> + <menu_item_call label="ZmieÅ„ nazwÄ™" name="rename"/> + <menu_item_call label="UsuÅ„" name="delete"/> + <menu_item_call label="RozwiÅ„" name="expand"/> + <menu_item_call label="Schowaj" name="collapse"/> + <menu_item_call label="RozwiÅ„ wszystkie foldery" name="expand_all"/> + <menu_item_call label="Schowaj wszystkie foldery" name="collapse_all"/> + <menu_item_check label="Sortuj wedÅ‚ug daty" name="sort_by_date"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/pl/menu_places_gear_landmark.xml new file mode 100644 index 0000000000000000000000000000000000000000..0139d3a98799049e5571c87b1c0d6c00f7e19592 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_places_gear_landmark.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_ladmark_gear"> + <menu_item_call label="Teleportuj" name="teleport"/> + <menu_item_call label="WiÄ™cej informacji" name="more_info"/> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Dodaj do landmarków" name="add_landmark"/> + <menu_item_call label="Dodaj folder" name="add_folder"/> + <menu_item_call label="Przywróć obiekt" name="restore_item"/> + <menu_item_call label="Wytnij" name="cut"/> + <menu_item_call label="Kopiuj landmark" name="copy_landmark"/> + <menu_item_call label="Kopiuj SLurl" name="copy_slurl"/> + <menu_item_call label="Wklej" name="paste"/> + <menu_item_call label="ZmieÅ„ nazwÄ™" name="rename"/> + <menu_item_call label="UsuÅ„" name="delete"/> + <menu_item_call label="RozwiÅ„ wszystkie foldery" name="expand_all"/> + <menu_item_call label="Schowaj wszystkie foldery" name="collapse_all"/> + <menu_item_check label="Sortuj wedÅ‚ug daty" name="sort_by_date"/> + <menu_item_call label="Stwórz Ulubione" name="create_pick"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/pl/menu_profile_overflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef836c8ecfe3f59c0244a46a60f2a1f492fc49ce --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_profile_overflow.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="profile_overflow_menu"> + <menu_item_call label="Mapa" name="show_on_map"/> + <menu_item_call label="ZapÅ‚ać" name="pay"/> + <menu_item_call label="UdostÄ™pnij" name="share"/> + <menu_item_call label="Zablokuj" name="block"/> + <menu_item_call label="Odblokuj" name="unblock"/> + <menu_item_call label="Wyrzuć" name="kick"/> + <menu_item_call label="Unieruchom" name="freeze"/> + <menu_item_call label="Uruchom" name="unfreeze"/> + <menu_item_call label="CSR" name="csr"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/pl/menu_save_outfit.xml new file mode 100644 index 0000000000000000000000000000000000000000..4bc65eca38fa4421e0d8749acd634a4a46f266bd --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_save_outfit.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="save_outfit_menu"> + <menu_item_call label="Zapisz" name="save_outfit"/> + <menu_item_call label="Zapisz jako" name="save_as_new_outfit"/> +</toggleable_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/pl/menu_script_chiclet.xml new file mode 100644 index 0000000000000000000000000000000000000000..256500a402a883b6d77a85914ff5525cc9b0dd10 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_script_chiclet.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="ScriptChiclet Menu"> + <menu_item_call label="Zamknij" name="Close"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_slurl.xml b/indra/newview/skins/minimal/xui/pl/menu_slurl.xml new file mode 100644 index 0000000000000000000000000000000000000000..862f538aa7730b3641bff874bd406d46551e01ea --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_slurl.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Popup"> + <menu_item_call label="O miejscu" name="about_url"/> + <menu_item_call label="Teleportuj do miejsca" name="teleport_to_url"/> + <menu_item_call label="Mapa" name="show_on_map"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e58592d46a66a044465a2a1229051e5df44feef --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_gear.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Teleport History Gear Context Menu"> + <menu_item_call label="RozwiÅ„ wszystkie foldery" name="Expand all folders"/> + <menu_item_call label="Schowaj wszystkie foldery" name="Collapse all folders"/> + <menu_item_call label="Wyczyść historiÄ™ teleportacji" name="Clear Teleport History"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd36c116b065f7a49c2538de5de7baf257912058 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_item.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Teleport History Item Context Menu"> + <menu_item_call label="Teleportuj" name="Teleport"/> + <menu_item_call label="WiÄ™cej szczegółów" name="More Information"/> + <menu_item_call label="Kopiuj do schowka" name="CopyToClipboard"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_tab.xml new file mode 100644 index 0000000000000000000000000000000000000000..b12df08d6ae55b1bab1334bc81eb704e2e2164ee --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_teleport_history_tab.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Teleport History Item Context Menu"> + <menu_item_call label="Otwórz" name="TabOpen"/> + <menu_item_call label="Zamknij" name="TabClose"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_text_editor.xml b/indra/newview/skins/minimal/xui/pl/menu_text_editor.xml new file mode 100644 index 0000000000000000000000000000000000000000..812f87bc1a3183957ac62940e842beab7003539d --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_text_editor.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Text editor context menu"> + <menu_item_call label="Wytnij" name="Cut"/> + <menu_item_call label="Kopiuj" name="Copy"/> + <menu_item_call label="Wklej" name="Paste"/> + <menu_item_call label="UsuÅ„" name="Delete"/> + <menu_item_call label="Zaznacz wszystko" name="Select All"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/pl/menu_topinfobar.xml new file mode 100644 index 0000000000000000000000000000000000000000..53536c8f1cfe96b08de665eea9dca7a6d9bbab81 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_topinfobar.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="menu_topinfobar"> + <menu_item_check label="Pokaż współprzÄ™dne" name="Show Coordinates"/> + <menu_item_check label="Pokaż O PosiadÅ‚oÅ›ci" name="Show Parcel Properties"/> + <menu_item_call label="Landmark" name="Landmark"/> + <menu_item_call label="Kopiuj" name="Copy"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_agent.xml b/indra/newview/skins/minimal/xui/pl/menu_url_agent.xml new file mode 100644 index 0000000000000000000000000000000000000000..db729be725febdf25e91584d4788d05a523cb160 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_agent.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż profil Rezydenta" name="show_agent"/> + <menu_item_call label="Kopiuj nazwÄ™ do schowka" name="url_copy_label"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_group.xml b/indra/newview/skins/minimal/xui/pl/menu_url_group.xml new file mode 100644 index 0000000000000000000000000000000000000000..f340b3296aac7f193d7046cf0e4139110965292d --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_group.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż szczegóły o grupie" name="show_group"/> + <menu_item_call label="Kopiuj grupÄ™ do schowka" name="url_copy_label"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_http.xml b/indra/newview/skins/minimal/xui/pl/menu_url_http.xml new file mode 100644 index 0000000000000000000000000000000000000000..e73f7b674562e71b81864fba4fa3decd812fb360 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_http.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Otwórz przeglÄ…darkÄ™ internetowÄ…" name="url_open"/> + <menu_item_call label="Otwórz w wewnÄ™trzenej przeglÄ…darce" name="url_open_internal"/> + <menu_item_call label="Otwórz w zewnÄ™trznej przeglÄ…darce" name="url_open_external"/> + <menu_item_call label="Kopiuj URL do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/pl/menu_url_inventory.xml new file mode 100644 index 0000000000000000000000000000000000000000..e36fa0dd2baddb63cb7a09f121dac47e099be005 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_inventory.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż obiekt w szafie" name="show_item"/> + <menu_item_call label="Kopiuj nazwÄ™ do schowka" name="url_copy_label"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_map.xml b/indra/newview/skins/minimal/xui/pl/menu_url_map.xml new file mode 100644 index 0000000000000000000000000000000000000000..179ab1f6768213a1629ae7b3ce85cabc542f30d9 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_map.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Teleportuj do miejsca" name="teleport_to_location"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/pl/menu_url_objectim.xml new file mode 100644 index 0000000000000000000000000000000000000000..7576208a9ef1e706579dbcc90ff65d866cd73c2a --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_objectim.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż szczegóły o obiekcie" name="show_object"/> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Teleportuj to miejsca obiektu" name="teleport_to_object"/> + <menu_item_call label="Kopiuj nazwÄ™ obiektu do schowka" name="url_copy_label"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/pl/menu_url_parcel.xml new file mode 100644 index 0000000000000000000000000000000000000000..1b8dd6213723ea427d82b95527066d918c3a21c8 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_parcel.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż szczegóły o miejscu" name="show_parcel"/> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/pl/menu_url_slapp.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb83245c48c5cc44616619b08371486ec3d9812b --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_slapp.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Uruchom tÄ™ komendÄ™" name="run_slapp"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/pl/menu_url_slurl.xml new file mode 100644 index 0000000000000000000000000000000000000000..4d4a5b4c4d90b11c0895763bf83aafe22f57eefa --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_slurl.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Pokaż szczegóły o miejscu" name="show_place"/> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Teleportuj do miejsca" name="teleport_to_location"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/pl/menu_url_teleport.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2255469300600f63e6d03878778526e85c1aa28 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_url_teleport.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Url Popup"> + <menu_item_call label="Teleportuj do tego miejsca" name="teleport"/> + <menu_item_call label="Pokaż na mapie" name="show_on_map"/> + <menu_item_call label="Kopiuj SLurl do schowka" name="url_copy"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_viewer.xml b/indra/newview/skins/minimal/xui/pl/menu_viewer.xml new file mode 100644 index 0000000000000000000000000000000000000000..0196dc86130913cd9e7592fd781ffca3e82e01d1 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_viewer.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu_bar name="Main Menu"> + <menu label="Pomoc" name="Help"> + <menu_item_call label="[SECOND_LIFE] Portal Pomocy" name="Second Life Help"/> + </menu> + <menu label="Zaawansowane" name="Advanced"> + <menu label="Skróty" name="Shortcuts"> + <menu_item_check label="Zacznij latać" name="Fly"/> + <menu_item_call label="Zamknij okno" name="Close Window"/> + <menu_item_call label="Zamknij wszystkie okna" name="Close All Windows"/> + <menu_item_call label="Reset widoku" name="Reset View"/> + </menu> + </menu> +</menu_bar> diff --git a/indra/newview/skins/minimal/xui/pl/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/pl/menu_wearable_list_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf85246be84d8adcb589b0f4be3c14d597d79357 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_wearable_list_item.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Outfit Wearable Context Menu"> + <menu_item_call label="ZastÄ…p" name="wear_replace"/> + <menu_item_call label="Załóż" name="wear_wear"/> + <menu_item_call label="Dodaj" name="wear_add"/> + <menu_item_call label="Zdejmij/OdÅ‚Ä…cz" name="take_off_or_detach"/> + <menu_item_call label="OdÅ‚Ä…cz" name="detach"/> + <context_menu label="DoÅ‚Ä…cz do" name="wearable_attach_to"/> + <context_menu label="DoÅ‚Ä…cz do zaÅ‚Ä…czników HUD" name="wearable_attach_to_hud"/> + <menu_item_call label="Zdejmij" name="take_off"/> + <menu_item_call label="Edytuj" name="edit"/> + <menu_item_call label="Profil obiektu" name="object_profile"/> + <menu_item_call label="Pokaż oryginalny" name="show_original"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/pl/menu_wearing_gear.xml new file mode 100644 index 0000000000000000000000000000000000000000..47cafdbd999efb8a5b318a54e0a148b04e633a96 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_wearing_gear.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<menu name="Gear Wearing"> + <menu_item_call label="Edytuj strój" name="edit"/> + <menu_item_call label="Zdejmij" name="takeoff"/> +</menu> diff --git a/indra/newview/skins/minimal/xui/pl/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/pl/menu_wearing_tab.xml new file mode 100644 index 0000000000000000000000000000000000000000..753143704320159934e6c540e4739625c20dc5af --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/menu_wearing_tab.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Wearing"> + <menu_item_call label="Zdejmij" name="take_off"/> + <menu_item_call label="OdÅ‚Ä…cz" name="detach"/> + <menu_item_call label="Edytuj strój" name="edit"/> +</context_menu> diff --git a/indra/newview/skins/minimal/xui/pl/notifications.xml b/indra/newview/skins/minimal/xui/pl/notifications.xml new file mode 100644 index 0000000000000000000000000000000000000000..6e62478ed0c5769dcf0f6b67303df131deda58de --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/notifications.xml @@ -0,0 +1,2907 @@ +<?xml version="1.0" encoding="utf-8"?> +<notifications> + <global name="skipnexttime"> + Nie pokazuj tej opcji nastÄ™pnym razem + </global> + <global name="alwayschoose"> + Pozwalaj na wybór tej opcji + </global> + <global name="implicitclosebutton"> + Zamknij + </global> + <template name="okbutton"> + <form> + <button name="OK_okbutton" text="$yestext"/> + </form> + </template> + <template name="okignore"> + <form> + <button name="OK_okignore" text="$yestext"/> + </form> + </template> + <template name="okcancelbuttons"> + <form> + <button name="OK_okcancelbuttons" text="$yestext"/> + <button name="Cancel_okcancelbuttons" text="$notext"/> + </form> + </template> + <template name="okcancelignore"> + <form> + <button name="OK_okcancelignore" text="$yestext"/> + <button name="Cancel_okcancelignore" text="$canceltext"/> + </form> + </template> + <template name="okhelpbuttons"> + <form> + <button name="OK_okhelpbuttons" text="$yestext"/> + <button name="Help" text="$helptext"/> + </form> + </template> + <template name="yesnocancelbuttons"> + <form> + <button name="Yes" text="$yestext"/> + <button name="No" text="$notext"/> + <button name="Cancel_yesnocancelbuttons" text="$canceltext"/> + </form> + </template> + <notification functor="GenericAcknowledge" label="Nieznany rodzaj komunikatu" name="MissingAlert"> + Twoja wersja klienta [APP_NAME] nie może wyÅ›wietlić odebranej wiadomoÅ›ci. Upewnij siÄ™, że posiadasz najnowszÄ… wersjÄ™ klienta. + +Szczegóły bÅ‚Ä™du: BÅ‚Ä…d o nazwie '[_NAME]' nie zostaÅ‚ odnaleziony w pliku notifications.xml. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="FloaterNotFound"> + BÅ‚Ä…d: nie można znaleźć nastÄ™pujÄ…cych elementów: + +[CONTROLS] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TutorialNotFound"> + Brak samouczka na ten temat + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GenericAlert"> + [MESSAGE] + </notification> + <notification name="GenericAlertYesCancel"> + [MESSAGE] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Tak"/> + </notification> + <notification name="BadInstallation"> + Podczas aktualizacji [APP_NAME] wystÄ…piÅ‚ bÅ‚Ä…d. ProszÄ™ odwiedzić stronÄ™ [http://get.secondlife.com pobierz najnowsza wersjÄ™] aby Å›ciÄ…gnąć ostatniÄ… wersjÄ™ klienta. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="LoginFailedNoNetwork"> + Nie można poÅ‚Ä…czyć z [SECOND_LIFE_GRID]. + '[DIAGNOSTIC]' +Upewnij siÄ™, że Twoje poÅ‚Ä…czenie z internetem dziaÅ‚a. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MessageTemplateNotFound"> + Wzór komunikatu dla [PATH] nie zostaÅ‚ odnaleziony. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="WearableSave"> + Zapisać zmiany dotyczÄ…ce ubrania/części ciaÅ‚a? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie Zapisuj" yestext="Zapisz"/> + </notification> + <notification name="CompileQueueSaveText"> + W trakcie Å‚adwania tekstu dla skryptu pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj ponownie za kilka minut. + </notification> + <notification name="CompileQueueSaveBytecode"> + W trakcie Å‚adowania skompilowanego skryptu pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj ponownie za kilka minut. + </notification> + <notification name="WriteAnimationFail"> + Problem w zapisywaniu danych animacji. Spróbuj ponownie za kilka minut. + </notification> + <notification name="UploadAuctionSnapshotFail"> + W trakcie Å‚adwania obrazu aukcji pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON]. + </notification> + <notification name="UnableToViewContentsMoreThanOne"> + Nie można przeglÄ…dać zawartoÅ›ci wiÄ™cej niż jednego obiektu naraz. +Wybierz pojedynczy obiekt i spróbuj jeszcze raz. + </notification> + <notification name="SaveClothingBodyChanges"> + Zapisać wszystkie zmiany dotyczÄ…ce ubrania/czeÅ›ci ciaÅ‚a? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie zapisuj" yestext="Zapisz"/> + </notification> + <notification name="FriendsAndGroupsOnly"> + Osoby spoza listy znajomych, których rozmowy gÅ‚osowe i IM sÄ… ignorowane, nie wiedzÄ… o tym. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="FavoritesOnLogin"> + PamiÄ™taj: kiedy wyÅ‚Ä…czysz tÄ… opcjÄ™, każdy kto używa tego komputera, może zobaczyć TwojÄ… listÄ™ ulubionych miejsc. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GrantModifyRights"> + Udzielenie praw modyfikacji innemu Rezydentowi umożliwia modyfikacjÄ™, usuwanie lub wziÄ™cie JAKIEGOKOLWIEK z Twoich obiektów. Używaj tej opcji z rozwagÄ…! +Czy chcesz udzielić prawa do modyfikacji [NAME]? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="GrantModifyRightsMultiple"> + Udzielenie praw modyfikacji innym Rezydentom umożliwia im modyfikacjÄ™, usuwanie lub wziÄ™cie JAKIEGOKOLWIEK z Twoich obiektów. Używaj tej opcji z rozwagÄ…! +Czy chcesz dać prawa modyfikacji wybranym osobom? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="RevokeModifyRights"> + Czy chcesz odebrać prawa do modyfikacji [NAME]? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="RevokeModifyRightsMultiple"> + Czy chcesz odebrać prawa modyfikacji wybranym Rezydentom? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="UnableToCreateGroup"> + ZaÅ‚ożenie grupy nie jest możliwe. +[MESSAGE] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="PanelGroupApply"> + [NEEDS_APPLY_MESSAGE] +[WANT_APPLY_MESSAGE] + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Ignoruj zmiany" yestext="Zastosuj zmiany"/> + </notification> + <notification name="MustSpecifyGroupNoticeSubject"> + Aby wysÅ‚ać ogÅ‚oszenie do grupy musisz nadać mu tytuÅ‚. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AddGroupOwnerWarning"> + Dodajesz czÅ‚onków do funkcji [ROLE_NAME]. +Ta funkcja nie może być odebrana. +CzÅ‚onkowie muszÄ… sami zrezygnować z peÅ‚nienia tej funkcji. +Chcesz kontynuować? + <usetemplate ignoretext="Przed dodaniem nowego wÅ‚aÅ›ciciela do grupy, proszÄ™ potwierdzić swojÄ… decyzjÄ™." name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="AssignDangerousActionWarning"> + Dodajesz przywilej [ACTION_NAME] do fukcji [ROLE_NAME]. + +*UWAGA* +CzÅ‚onek w funkcji z tym przywilejem może przypisać siebie i innych czÅ‚onków nie bÄ™dÄ…cych wÅ‚aÅ›cicielami do funkcji dajÄ…cych wiÄ™cej przywilejów niż posiadane obecnie potencjalnie dajÄ…ce możliwoÅ›ci zbliżone do możliwoÅ›ci wÅ‚aÅ›ciciela. +Udzielaj tego przywileju z rozwagÄ…." + +Dodać ten przywilej do funkcji [ROLE_NAME]? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="AssignDangerousAbilityWarning"> + Dodajesz przywilej [ACTION_NAME] do fukcji [ROLE_NAME] + +*UWAGA* +CzÅ‚onek w funkcji z tym przywilejem może przypisać sobie i innychm czÅ‚onkom nie bÄ™dÄ…cym wÅ‚aÅ›cicielami wszystkie przywileje potencjalnie dajÄ…ce możliwoÅ›ci zbliżone do możliwoÅ›ci wÅ‚aÅ›ciciela. +Udzielaj tego przywileju z rozwagÄ…. + +Dodać ten przywilej do funkcji [ROLE_NAME]? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="AttachmentDrop"> + WybraÅ‚eÅ› opcjÄ™ opuszczenia swojego zaÅ‚Ä…cznika. + Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź przed zdjÄ™ciem zaÅ‚Ä…cznika." name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="JoinGroupCanAfford"> + DoÅ‚Ä…czenie do tej grupy kosztuje [COST]L$. +Chcesz kontynuować? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="DoÅ‚Ä…cz"/> + </notification> + <notification name="JoinGroupNoCost"> + DoÅ‚Ä…czasz do grupy [NAME]. +Czy chcesz kontynuować? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Akceptuj"/> + </notification> + <notification name="JoinGroupCannotAfford"> + CzÅ‚onkostwo w tej grupie kosztuje [COST]L$ +Masz za maÅ‚o L$ żeby zostać czÅ‚onkiem. + </notification> + <notification name="CreateGroupCost"> + Stworzenie tej grupy kosztuje 100L$. +W grupie powinien być wiÄ™cej niż jeden czÅ‚onek, albo zostanie na zawsze skasowana. +ZaproÅ› proszÄ™ czÅ‚onków w ciÄ…gu 48 godzin. + <usetemplate canceltext="Anuluj" name="okcancelbuttons" notext="Anuluj" yestext="Stwórz grupÄ™ za 100L$"/> + </notification> + <notification name="LandBuyPass"> + Za [COST]L$ możesz odwiedzić tÄ… posiadÅ‚ość ('[PARCEL_NAME]') na [TIME] godzin. Chcesz kupić przepustkÄ™? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="SalePriceRestriction"> + Cena sprzedaży musi być wyższa niż 0L$ jeżeli sprzedajesz komukolwiek. +Musisz wybrać kupca jeżeli chcesz sprzedać za 0L$. + </notification> + <notification name="ConfirmLandSaleChange"> + PosiadÅ‚ość o powierzchni [LAND_SIZE] m zostaje wystawiona na sprzedaż. +Cena wynosi [SALE_PRICE]L$ i sprzedaż bÄ™dzie autoryzowana dla [NAME]. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmLandSaleToAnyoneChange"> + UWAGA: WybierajÄ…c opcjÄ™ "Sprzedaj Każdemu" udostÄ™pniasz swojÄ… posiadÅ‚ość do sprzedaży dla jakiegokolwiek Rezydenta [SECOND_LIFE] , nawet osób nieobecnych w tym regionie. + +PosiadÅ‚ość o powierzchni [LAND_SIZE] m² zostaje wystawiona na sprzedaż. +Cena wynosi [SALE_PRICE]L$ i sprzedaż bÄ™dzie autoryzowana dla [NAME]. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsDeededToGroup"> + Czy na pewno chcesz zwrócić wszystkie obiekty udostÄ™pnione grupie [NAME] na tej posiadÅ‚oÅ›ci do szafy ich poprzednich wÅ‚aÅ›cicieli? + +*UWAGA* Wybrana opcja spowoduje usuniÄ™cie wszystkich obiektów +udostÄ™pnionych grupie, które nie majÄ… praw transferu! + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsOwnedByUser"> + Czy na pewno chcesz zwrócić wszystkie obiekty należące do Rezydenta [NAME] znajdujÄ…ce siÄ™ na tej posiadÅ‚oÅ›ci do szafy wÅ‚aÅ›ciciela? + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsOwnedBySelf"> + Czy na pewno chcesz zwrócić wszystkie Twoje obiekty znajdujÄ…ce siÄ™ na tej posiadÅ‚oÅ›ci do swojej szafy? + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsNotOwnedBySelf"> + Czy na pewno chcesz zwrócić wszystkie obiekty, których nie jesteÅ› wÅ‚aÅ›cicielem znajdujÄ…ce siÄ™ na tej posiadÅ‚oÅ›ci do szaf wÅ‚aÅ›cicieli? Wszystkie obiekty udostÄ™pnione grupie z prawem transferu, zostanÄ… zwrócone poprzednim wÅ‚aÅ›cicielom. + +*UWAGA* Wybrana opcja spowoduje usuniÄ™cie wszystkich obiektów udostÄ™pnionych grupie, które nie majÄ… praw transferu! + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsNotOwnedByUser"> + Czy na pewno chcesz zwrócić wszystkie obiekty, które nie należą do [NAME] znajdujÄ…ce siÄ™ na tej posiadÅ‚oÅ›ci do szaf wÅ‚aÅ›cicieli? Wszystkie obiekty udostÄ™pnione grupie z prawem transferu, zostanÄ… zwrócone poprzednim wÅ‚aÅ›cicielom. + +*UWAGA* Wybrana opcja spowoduje usuniÄ™cie wszystkich obiektów udostÄ™pnionych grupie, które nie majÄ… praw transferu! + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnAllTopObjects"> + Czy na pewno chcesz zwrócić wszystkie wymienione obiekty znajdujÄ…ce siÄ™ na tej posiadÅ‚oÅ›ci do szaf ich wÅ‚aÅ›cicieli? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="DisableAllTopObjects"> + Czy na pewno chcesz deaktywować wszystkie obiekty w tym Regionie? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnObjectsNotOwnedByGroup"> + Zwrócić obiekty z tej posiadÅ‚oÅ›ci, które nie sÄ… udosÄ™pnione grupie [NAME] do ich wÅ‚aÅ›cicieli? + +Obiekty: [N] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="UnableToDisableOutsideScripts"> + Nie można deaktywować skryptów. +Ten region pozwala na uszkodzenia. +Skrypty muszÄ… pozostać aktywne dla prawidÅ‚owego dziaÅ‚ania broni. + </notification> + <notification name="MultipleFacesSelected"> + Obecnie zaznaczono wiele powierzchni. +JeÅ›li dziaÅ‚anie bÄ™dzie kontynuowane, oddzielne media bÄ™dÄ… ustawione na wielu powierzchniach obiektu. +W celu umieszczenia mediów tylko na jednej powierzchni skorzystaj z Wybierz powierzchniÄ™ i kliknij na wybranej powierzchni obiektu oraz kliknij Dodaj. + <usetemplate ignoretext="Media zostanÄ… ustawione na wielu zaznaczonych powierzchniach" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="MustBeInParcel"> + Musisz znajdować siÄ™ wewnÄ…trz posiadÅ‚oÅ›ci żeby wybrać punkt lÄ…dowania. + </notification> + <notification name="PromptRecipientEmail"> + ProszÄ™ wpisać adres emailowy odbiorcy. + </notification> + <notification name="PromptSelfEmail"> + ProszÄ™ wpisać swój adres emailowy. + </notification> + <notification name="PromptMissingSubjMsg"> + WysÅ‚ać widokówkÄ™ z domyÅ›lnym tematem i wiadomoÅ›ciÄ…? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ErrorProcessingSnapshot"> + BÅ‚Ä…d w trakcie przetwarzania danych zdjÄ™cia. + </notification> + <notification name="ErrorEncodingSnapshot"> + BÅ‚Ä…d w kodowaniu zdjÄ™cia. + </notification> + <notification name="ErrorUploadingPostcard"> + W trakcie Å‚adowania zdjÄ™cia pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON] + </notification> + <notification name="ErrorUploadingReportScreenshot"> + W trakcie Å‚adowania zdjÄ™cia ekranu do raportu pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON] + </notification> + <notification name="MustAgreeToLogIn"> + Musisz zaakceptować Warunki Umowy (Terms of Service) by kontynuować logowanie siÄ™ do [SECOND_LIFE]. + </notification> + <notification name="CouldNotPutOnOutfit"> + ZaÅ‚ożenie stroju nie powiodÅ‚o siÄ™. +Folder stroju nie zawiera żadnego ubrania, części ciaÅ‚a ani zaÅ‚Ä…czników. + </notification> + <notification name="CannotWearTrash"> + Nie możesz zaÅ‚ożyć ubrania, które znajduje siÄ™ w koszu. + </notification> + <notification name="MaxAttachmentsOnOutfit"> + Nie można doÅ‚Ä…czyć obiektu. +Limit [MAX_ATTACHMENTS] zaÅ‚Ä…czników zostaÅ‚ przekroczony. ProszÄ™ najpierw odÅ‚Ä…czyć inny obiekt. + </notification> + <notification name="CannotWearInfoNotComplete"> + Nie możesz zaÅ‚ożyć tego artkuÅ‚u ponieważ nie zaÅ‚adowaÅ‚ siÄ™ poprawnie. Spróbuj ponownie za kilka minut. + </notification> + <notification name="MustHaveAccountToLogIn"> + Oops! Brakuje czegoÅ›. +Należy wprowadzić nazwÄ™ użytkownika. + +Potrzebujesz konta aby siÄ™ zalogować do [SECOND_LIFE]. Czy chcesz utworzyć je teraz? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="InvalidCredentialFormat"> + Należy wprowadzić nazwÄ™ użytkownika lub imiÄ™ oraz nazwisko Twojego awatara w pole nazwy użytkownika a nastÄ™pnie ponownie siÄ™ zalogować. + </notification> + <notification name="DeleteClassified"> + Usunąć reklamÄ™ '[NAME]'? +PamiÄ™taj! Nie ma rekompensaty za poniesione koszta. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="DeleteMedia"> + Wybrano usuniÄ™cie mediów zwiÄ…zanych z tÄ… powierzchniÄ…. +Czy na pewno chcesz kontynuować? + <usetemplate ignoretext="Potwierdź przed usuniÄ™ciem mediów z obiektu" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="ClassifiedSave"> + Zapisać zmiany w reklamie [NAME]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie Zapisuj" yestext="Zapisz"/> + </notification> + <notification name="ClassifiedInsufficientFunds"> + Nie posiadasz wystarczajÄ…cych Å›rodków aby dodać reklamÄ™. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="DeleteAvatarPick"> + UsuÅ„ zdjÄ™cie <nolink>[PICK]</nolink>? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="DeleteOutfits"> + Skasować wybrane stroje? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="PromptGoToEventsPage"> + Odwiedzić internetowÄ… stronÄ™ Imprez [SECOND_LIFE]? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="SelectProposalToView"> + Wybierz propozycjÄ™, którÄ… chcesz zobaczyć. + </notification> + <notification name="SelectHistoryItemToView"> + Wybierz obiekt z historii, który chcesz zobaczyć. + </notification> + <notification name="CacheWillClear"> + Bufor danych zostanie wyczyszczony po restarcie aplikacji [APP_NAME]. + </notification> + <notification name="CacheWillBeMoved"> + Bufor danych zostanie przeniesiony po restarcie aplikacji [APP_NAME]. +PamiÄ™taj: Opcja ta wyczyszcza bufor danych. + </notification> + <notification name="ChangeConnectionPort"> + Ustawienia portu zostajÄ… zaktualizowane po restarcie aplikacji [APP_NAME]. + </notification> + <notification name="ChangeSkin"> + Nowa skórka zostanie wczytana po restarcie aplikacji [APP_NAME]. + </notification> + <notification name="ChangeLanguage"> + Zmiana jÄ™zyka zadziaÅ‚a po restarcie [APP_NAME]. + </notification> + <notification name="GoToAuctionPage"> + Odwiedzić stronÄ™ internetowÄ… [SECOND_LIFE] żeby zobaczyć szczgóły aukcji lub zrobić ofertÄ™? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="SaveChanges"> + Zapisać zmiany? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie zapisuj" yestext="Zapisz"/> + </notification> + <notification name="GestureSaveFailedTooManySteps"> + Nie można zapisać gesturki. +Ta gesturka ma zbyt wiele etapów. +UsuÅ„ kilka etapów i zapisz jeszcze raz. + </notification> + <notification name="GestureSaveFailedTryAgain"> + Zapis gesturki nie powiódÅ‚ siÄ™. Spróbuj jeszcze raz za kilka minut. + </notification> + <notification name="GestureSaveFailedObjectNotFound"> + Nie można zapisać gesturki ponieważ obiekt lub szafa powiÄ…zanego obiektu nie zostaÅ‚ znaleziony. +Obiekt może znajdować siÄ™ zbyt daleko albo zostaÅ‚ usuniÄ™ty. + </notification> + <notification name="GestureSaveFailedReason"> + Nie można zapisać gesturki z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj zapisać jeszcze raz później. + </notification> + <notification name="SaveNotecardFailObjectNotFound"> + Nie można zapisać notki ponieważ obiekt lub szafa powiÄ…zanego obiektu nie zostaÅ‚ znaleziony. +Obiekt może znajdować siÄ™ zbyt daleko albo zostaÅ‚ usuniÄ™ty. + </notification> + <notification name="SaveNotecardFailReason"> + Nie można zapisać notki z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj zapisać jeszcze raz później. + </notification> + <notification name="ScriptCannotUndo"> + Nie można cofnąć wszystkich zmian w Twojej wersji skryptu. +Czy chcesz zaÅ‚adować ostatniÄ… wersjÄ™ zapisanÄ… na serwerze? +(*UWAGA* Ta operacja jest nieodwracalna.) + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="SaveScriptFailReason"> + Nie można zapisać skryptu z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj zapisać jeszcze raz później. + </notification> + <notification name="SaveScriptFailObjectNotFound"> + Nie można zapisać skryptu ponieważ obiekt w którym siÄ™ zawiera nie zostaÅ‚ znaleziony. +Obiekt może znajdować siÄ™ zbyt daleko albo zostaÅ‚ usuniÄ™ty. + </notification> + <notification name="SaveBytecodeFailReason"> + Nie można zapisać skompilowanego skryptu z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj zapisać jeszcze raz póżniej. + </notification> + <notification name="StartRegionEmpty"> + Oops, Twoje miejsce startu nie zostaÅ‚o okreÅ›lone. +Wpisz proszÄ™ nazwÄ™ regionu w lokalizacjÄ™ startu w polu Lokalizacja Startu lub wybierz Moja ostatnia lokalizacja albo Miejsce Startu. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CouldNotStartStopScript"> + Nie można uruchomić lub zatrzymać skryptu ponieważ obiekt w którym siÄ™ zawiera nie zostaÅ‚ znaleziony. +Obiekt może znajdować siÄ™ zbyt daleko albo zostaÅ‚ usuniÄ™ty. + </notification> + <notification name="CannotDownloadFile"> + Nie można zaÅ‚adować pliku + </notification> + <notification name="CannotWriteFile"> + Nie można zapisać pliku [[FILE]] + </notification> + <notification name="UnsupportedHardware"> + Niestety Twój komputer nie speÅ‚nia minimalnych wymogów sprzÄ™towych dla poprawnego dziaÅ‚ania [APP_NAME]. Możesz odczuwać bardzo niskÄ… wydajność operacyjnÄ…. Niestety portal pomocy, [SUPPORT_SITE] nie posiada informacji na temat poprawnej konfiguracji technicznej Twojego systemu. + +Po wiÄ™cej info, odwiedź stronÄ™ [_URL] . + <url name="url" option="0"> + http://www.secondlife.com/corporate/sysreqs.php + </url> + <usetemplate ignoretext="Dysk twardy mojego komputera nie jest wspomagany" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="UnknownGPU"> + Twój system jest wyposażony w kartÄ™ graficznÄ…, która nie jest rozpoznana przez [APP_NAME]. +Zdarza siÄ™ to czÄ™sto w przypadku nowego sprzÄ™tu, który nie byÅ‚ testowany z [APP_NAME]. Prawdopodobnie wystarczy dostosowanie ustawieÅ„ grafiki aby dziaÅ‚anie byÅ‚o poprawne. +(Ja > WÅ‚aÅ›ciwoÅ›ci > Grafika). + <form name="form"> + <ignore name="ignore" text="Karta graficzna nie zostaÅ‚a zidentyfikowana."/> + </form> + </notification> + <notification name="DisplaySettingsNoShaders"> + [APP_NAME] zawiesiÅ‚ siÄ™ podczas inicjalizacji sterowników graficznych. +Jakość grafiki zostaÅ‚a zmniejszona - może to pomóc. +Pewne funkcje graficzne zostaÅ‚y wyÅ‚Ä…czone. Zalecamy aktualizcje sterowników graficznych. +Możesz podnieść jakość grafiki pod Ustawienia > Grafika. + </notification> + <notification name="RegionNoTerraforming"> + Region [REGION] nie pozwala na formowanie powierzchni ziemi. + </notification> + <notification name="CannotCopyWarning"> + Nie masz pozwolenia na kopiowanie nastÄ™pujÄ…cych obiektów: +[ITEMS] +i stracisz je w momencie przekazania. Czy na pewno chcesz oddać te obiekty? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="CannotGiveItem"> + Podarowanie obiektu nie powiodÅ‚o siÄ™. + </notification> + <notification name="TransactionCancelled"> + Transakcja anulowana + </notification> + <notification name="TooManyItems"> + Jednorazowo możesz podarować maksymalnie 42 obiekty z szafy. + </notification> + <notification name="NoItems"> + Nie masz praw do transferu wybranych obiektów. + </notification> + <notification name="CannotCopyCountItems"> + Nie masz praw do skopiowania [COUNT] wybranych obiektów. Obiekty zniknÄ… z Twojej szafy. +Na pewno chcesz oddać te obiekty? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="CannotGiveCategory"> + Nie masz praw do transferu wybranego foldera. + </notification> + <notification name="FreezeAvatar"> + Unieruchomić tego awatara? +Awatar tymczasowo nie bÄ™dzie mógÅ‚ siÄ™ poruszać, nie bÄ™dzie mógÅ‚ używać czatu (IM) i nie bÄ™dzie w stanie odziaÅ‚ywać na Å›wiat. + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Odblokuj" yestext="Unieruchom"/> + </notification> + <notification name="FreezeAvatarFullname"> + Unieruchowmić [AVATAR_NAME]? +Ta osoba tymczasowo nie bÄ™dzie mógÅ‚a siÄ™ poruszać, nie bÄ™dzie mógÅ‚ używać czatu (IM) i nie bÄ™dzie w stanie odziaÅ‚ywać na Å›wiat. + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Odblokuj" yestext="Unieruchom"/> + </notification> + <notification name="EjectAvatarFullname"> + Wyrzucić [AVATAR_NAME] z Twojej posiadÅ‚oÅ›ci? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wyrzuć i zabroÅ„ wstÄ™pu (ban)" yestext="Wyrzuć"/> + </notification> + <notification name="EjectAvatarFromGroup"> + Wyrzuć [AVATAR_NAME] z grupy [GROUP_NAME] + </notification> + <notification name="AcquireErrorTooManyObjects"> + BÅÄ„D OTRZYMYWANIA: Zbyt wiele wybranych obiektów. + </notification> + <notification name="AcquireErrorObjectSpan"> + BÅÄ„D OTRZYMYWANIA: Obiekty przekraczajÄ… granicÄ™ regionów. Przemieść wszystkie otrzymywane obiekty do jednego regionu. + </notification> + <notification name="PromptGoToCurrencyPage"> + [EXTRA] + +Odwiedź stronÄ™ [_URL] po wiÄ™cej informacji na temat zakupu L$? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="UnableToLinkObjects"> + Nie można poÅ‚Ä…czyć [COUNT] obiektów. +Maksymalnie można poÅ‚Ä…czyć [MAX] obiektów. + </notification> + <notification name="CannotLinkIncompleteSet"> + Możesz Å‚Ä…czyć tylko kompletne zbiory obiektów i musisz wybrać wiÄ™cej niż jeden obiekt. + </notification> + <notification name="CannotLinkModify"> + Nie możesz poÅ‚Ä…czyć obiektów ponieważ nie masz praw modyfikacji dla wszystkich obiektów. + +Upewnij siÄ™, że żaden z obiktów nie jest zablokowany i że wszystkie obiekty należą do Ciebie. + </notification> + <notification name="CannotLinkDifferentOwners"> + Nie możesz poÅ‚Ä…czyć obiektów ponieważ należą one do różnych osób. + +Upewnij sie, że wszystkie wybrane obiekty należą do Ciebie. + </notification> + <notification name="NoFileExtension"> + Niepoprawna koÅ„cówka nazwy pliku: '[FILE]' + +Upewnij siÄ™, że nazwa pliku ma poprawanÄ… koÅ„cówkÄ™. + </notification> + <notification name="InvalidFileExtension"> + Niepoprawna koÅ„cówka nazwy pliku - [EXTENSION] +Oczekiwana - [VALIDS] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CannotUploadSoundFile"> + Nie można otworzyć zaÅ‚adowanego pliku dźwiÄ™kowego: +[FILE] + </notification> + <notification name="SoundFileNotRIFF"> + Plik nie jest w formacie RIFF WAVE: +[FILE] + </notification> + <notification name="SoundFileNotPCM"> + Plik nie jest w formacie PCM WAVE: +[FILE] + </notification> + <notification name="SoundFileInvalidChannelCount"> + Plik zawiera niewÅ‚aÅ›ciwÄ… liczbÄ™ kanałów (musi być mono albo stereo): +[FILE] + </notification> + <notification name="SoundFileInvalidSampleRate"> + Plik zawiera niewÅ‚aÅ›ciÄ… czÄ™stotliwość (musi być 44.1k): +[FILE] + </notification> + <notification name="SoundFileInvalidWordSize"> + Plik zawiera niewÅ‚aÅ›ciwÄ… szerokość danych (musi być 8 albo 16 bitów): +[FILE] + </notification> + <notification name="SoundFileInvalidHeader"> + Brak bloku 'data' w nagłówku pliku WAV: +[FILE] + </notification> + <notification name="SoundFileInvalidChunkSize"> + NiewÅ‚aÅ›ciwy rozmiar "chunk" w pliku WAV: +[FILE] + </notification> + <notification name="SoundFileInvalidTooLong"> + Plik audio jest zbyt dÅ‚ugi (10 sekund maksimum): +[FILE] + </notification> + <notification name="CannotOpenTemporarySoundFile"> + Nie można otworzyć tymczasowego skompresowango pliku dźwiÄ™kowego w celu zapisu: [FILE] + </notification> + <notification name="UnknownVorbisEncodeFailure"> + Nieznany bÅ‚Ä…d kodowania Vorbis w: [FILE] + </notification> + <notification name="CannotEncodeFile"> + Kodowanie pliku: [FILE] nie powidÅ‚o siÄ™. + </notification> + <notification name="CorruptedProtectedDataStore"> + Nie można wpisać Twojego imienia użytkownika ani hasÅ‚a. To może siÄ™ zdarzyć kiedy zmieniasz ustawienia sieci. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CorruptResourceFile"> + Skorumpowany plik zasobów: [FILE] + </notification> + <notification name="UnknownResourceFileVersion"> + Nieznana wersja pliku zasobów Linden w pliku: [FILE] + </notification> + <notification name="UnableToCreateOutputFile"> + Nie można utworzyć pliku wyjÅ›ciowego: [FILE] + </notification> + <notification name="DoNotSupportBulkAnimationUpload"> + [APP_NAME] obecnie nie wspomaga Å‚adowania grupowego plików animacji. + </notification> + <notification name="CannotUploadReason"> + Åadowanie pliku [FILE] nie powiodÅ‚o siÄ™ z powodu: [REASON] +Spróbuj jeszcze raz póżniej. + </notification> + <notification name="LandmarkCreated"> + Dodano "[LANDMARK_NAME]" do folderu [FOLDER_NAME]. + </notification> + <notification name="LandmarkAlreadyExists"> + Posiadasz już landmark dla tej lokalizacji. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CannotCreateLandmarkNotOwner"> + Nie możesz zapamiÄ™tać tego miejsca (LM) ponieważ wÅ‚aÅ›ciciel posiadÅ‚oÅ›ci nie pozwala na to. + </notification> + <notification name="CannotRecompileSelectObjectsNoScripts"> + 'Rekompilacja' nie powiodÅ‚a siÄ™. + +Wybierz obiekty zawierajÄ…ce skrypty. + </notification> + <notification name="CannotRecompileSelectObjectsNoPermission"> + 'Rekompilacja' nie powiodÅ‚a siÄ™. + +Wybierz skryptowane obiekty do których masz prawa modyfikacji. + </notification> + <notification name="CannotResetSelectObjectsNoScripts"> + 'Resetowanie' nie powiodÅ‚o siÄ™. + +Wybierz obiekty zawierajÄ…ce skrypty. + </notification> + <notification name="CannotResetSelectObjectsNoPermission"> + 'Resetowanie' nie powiodÅ‚o siÄ™. + +Wybierz skryptowane obiekty do których masz prawa modyfikacji. + </notification> + <notification name="CannotOpenScriptObjectNoMod"> + Nie można otworzyć skryptu bez prawa do modyfikacji obiektu. + </notification> + <notification name="CannotSetRunningSelectObjectsNoScripts"> + 'Uruchomienie' skryptów nie powiodÅ‚o siÄ™. + +Wybierz obiekty zawierajÄ…ce skrypty. + </notification> + <notification name="CannotSetRunningNotSelectObjectsNoScripts"> + 'Zatrzymanie' skryptów nie powiodÅ‚o siÄ™. + +Wybierz obiekty zawierajÄ…ce skrypty. + </notification> + <notification name="NoFrontmostFloater"> + Brak górnego okna do zapisu. + </notification> + <notification name="SeachFilteredOnShortWords"> + Twoje zapytanie wyszukiwania zostÅ‚o zmienione - zbyt krótkie sÅ‚owa zostaÅ‚y usuniÄ™te. + +Nowe zapytanie: [FINALQUERY] + </notification> + <notification name="SeachFilteredOnShortWordsEmpty"> + Użyte terminy wyszukiwania byÅ‚y zbyt krótkie - wyszukiwanie zostaÅ‚o anulowane. + </notification> + <notification name="CouldNotTeleportReason"> + Teleportacja nie powiodÅ‚a siÄ™. +[REASON] + </notification> + <notification name="invalid_tport"> + Niestety, pojawiÅ‚ siÄ™ bÅ‚Ä…d podczas próby teleportacji. Proponujemy wylogowanie siÄ™ i spróbowanie teleportacji ponownie. +Jeżeli nadal otrzymujesz tÄ™ wiadomość proponujemy odwiedzić stronÄ™ [SUPPORT_SITE]. + </notification> + <notification name="invalid_region_handoff"> + Niestety, pojawiÅ‚ siÄ™ bÅ‚Ä…d podczas próby przedostania siÄ™ na drugi region. Proponujemy wylogowanie siÄ™ i spróbowanie przedostania siÄ™ na drugi region ponownie. +Jeżeli nadal otrzymujesz tÄ™ wiadomość proponujemy odwiedzić stronÄ™ [SUPPORT_SITE]. + </notification> + <notification name="blocked_tport"> + Przepraszamy, teleportacja jest chwilowo niedostÄ™pna. Spróbuj jeszcze raz. +JeÅ›li nadal nie możesz siÄ™ teleportować wyloguj siÄ™ i ponownie zaloguj. + </notification> + <notification name="nolandmark_tport"> + Przepraszamy, ale nie możemy znaleźć miejsca docelowego. + </notification> + <notification name="timeout_tport"> + Przepraszamy, ale nie udaÅ‚o siÄ™ przeprowadzić teleportacji. Spróbuj jeszcze raz. + </notification> + <notification name="noaccess_tport"> + Przepraszamy, ale nie masz dostÄ™pu do miejsca docelowego. + </notification> + <notification name="missing_attach_tport"> + Czekamy na Twoje akcesoria. Możesz poczekać kilka minut lub zrobić relog przed nastÄ™pnÄ… próbÄ… teleportacji. + </notification> + <notification name="too_many_uploads_tport"> + Obecnie ten region ma problemy z Å‚adowaniem obiektów w zwiÄ…zku z czym teleportacja bardzo sie opóźnia. +Spróbuj jeszcze raz za kilka minut albo teleportuj siÄ™ do mniej zatÅ‚oczonego miejsca. + </notification> + <notification name="expired_tport"> + Przepraszamy, ale nie udaÅ‚o siÄ™ przeprowadzić teleportacji wystarczajÄ…co szybko. Spróbuj jeszcze raz za kilka minut. + </notification> + <notification name="expired_region_handoff"> + Przepraszamy, ale nie udaÅ‚o siÄ™ przeprowadzić zmiany regionu wystarczajÄ…co szybko. Spróbuj jeszcze raz za kilka minut. + </notification> + <notification name="no_host"> + Nie możemy znaleść miejsca docelowego. To miejsce może być chwilowo nieosiÄ…galne albo przestaÅ‚o istnieć. +Spróbuj jeszcze raz za kilka minut. + </notification> + <notification name="no_inventory_host"> + Szafa chwilowo nie dziaÅ‚a. + </notification> + <notification name="CannotSetLandOwnerNothingSelected"> + Nie można wybrać wÅ‚aÅ›ciciela posiadÅ‚oÅ›ci. +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotSetLandOwnerMultipleRegions"> + Nie można wybrać wÅ‚aÅ›ciciela posiadÅ‚oÅ›ci ponieważ wybrany obszar przekracza granicÄ™ regionów. Wybierz mniejszy obszar i spróbuj jeszcze raz. + </notification> + <notification name="ForceOwnerAuctionWarning"> + Ta posiadÅ‚ość jest wystawiona na aukcjÄ™. Wymuszenie wÅ‚asnoÅ›ci anuluje aukcjÄ™ i potencjalnie może zdenerwować zainteresowanych Rezydentów, jeżeli licytacja już siÄ™ rozpoczęła. +Wymusić wÅ‚asność? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="CannotContentifyNothingSelected"> + Nie można sfinalizować: +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotContentifyNoRegion"> + Nie można sfinalizować: +Region nie znaleziony. + </notification> + <notification name="CannotReleaseLandNothingSelected"> + Nie można porzucić posiadÅ‚oÅ›ci: +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotReleaseLandNoRegion"> + Nie można porzucić posiadÅ‚oÅ›ci: +Region nie znaleziony. + </notification> + <notification name="CannotBuyLandNothingSelected"> + Nie można kupić posiadÅ‚oÅ›ci: +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotBuyLandNoRegion"> + Nie można kupić posiadÅ‚oÅ›ci: +Region nie znaleziony. + </notification> + <notification name="CannotCloseFloaterBuyLand"> + Okno zakupu landu nie może zostać zamkniÄ™te dopóki aplikacja [APP_NAME] nie okreÅ›li ceny dla tej transkacji. + </notification> + <notification name="CannotDeedLandNothingSelected"> + Nie można przekazać posiadÅ‚oÅ›ci: +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotDeedLandNoGroup"> + Nie można przekazać posiadÅ‚oÅ›ci: +Grupa nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotDeedLandNoRegion"> + Brak możliwoÅ›ci przepisania posiadÅ‚oÅ›ci grupie: +Region, gdzie posiadÅ‚ość siÄ™ znajduje nie zostaÅ‚ odnaleziony. + </notification> + <notification name="CannotDeedLandMultipleSelected"> + Nie można przekazać posiadÅ‚oÅ›ci: +Wiele posiadÅ‚oÅ›ci jest wybranych. + +Spróbuj wybrać pojedynczÄ… posiadÅ‚ość. + </notification> + <notification name="CannotDeedLandWaitingForServer"> + Nie można przekazać posiadÅ‚oÅ›ci: +Serwer aktualizuje dane wÅ‚asnoÅ›ci. + +Spróbuj jeszcze raz póżniej. + </notification> + <notification name="CannotDeedLandNoTransfer"> + Nie możesz przekazać posiadÅ‚oÅ›ci: +Region [REGION] nie pozwala na transfer posiadÅ‚oÅ›ci. + </notification> + <notification name="CannotReleaseLandWatingForServer"> + Nie można porzucić posiadÅ‚oÅ›ci: +Serwer aktualizuje dane posiadÅ‚oÅ›ci. + +Spróbuj jeszcze raz póżniej. + </notification> + <notification name="CannotReleaseLandSelected"> + Nie możesz porzucić posiadÅ‚oÅ›ci: +Nie jesteÅ› wÅ‚aÅ›cicielem wszystkich wybranych posiadÅ‚oÅ›ci. + +Wybierz pojedynczÄ… posiadÅ‚ość. + </notification> + <notification name="CannotReleaseLandDontOwn"> + Nie możesz porzucić posiadÅ‚oÅ›ci: +Nie masz praw do porzucenia tej posiadÅ‚oÅ›ci. + +Twoje posiadÅ‚oÅ›ci sÄ… podkreÅ›lone na zielono. + </notification> + <notification name="CannotReleaseLandRegionNotFound"> + Brak możliwoÅ›ci porzucenia posiadÅ‚oÅ›ci: +Region, gdzie posiadÅ‚ość siÄ™ znajduje nie zostaÅ‚ odnaleziony. + </notification> + <notification name="CannotReleaseLandNoTransfer"> + Nie możesz porzucić posiadÅ‚oÅ›ci: +Region [REGION] nie pozwala na transfer posiadÅ‚oÅ›ci. + </notification> + <notification name="CannotReleaseLandPartialSelection"> + Nie można porzucić posiadÅ‚oÅ›ci: +Musisz wybrać caÅ‚Ä… posiadÅ‚ość by jÄ… porzucić. +Wybierz caÅ‚Ä… posiadÅ‚ość albo najpierw jÄ… podziel. + </notification> + <notification name="ReleaseLandWarning"> + Porzucasz posiadÅ‚ość o powierzchni [AREA] m². +Porzucenie tej posiadÅ‚oÅ›ci usunie jÄ… z Twoich wÅ‚asnoÅ›ci. +Nie otrzymasz za to żadnej opÅ‚aty. + +Porzucić posiadÅ‚ość? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="CannotDivideLandNothingSelected"> + Nie można podzielić posiadÅ‚oÅ›ci: + +PosiadÅ‚ość nie zostaÅ‚a wybrana. + </notification> + <notification name="CannotDivideLandPartialSelection"> + Nie można podzielić posiadÅ‚oÅ›ci: + +PosiadÅ‚ość zostaÅ‚a wybrana w caÅ‚oÅ›ci. +Spróbuj wybrać część posiadÅ‚oÅ›ci. + </notification> + <notification name="LandDivideWarning"> + PodziaÅ‚ tej posiadÅ‚oÅ›ci stworzy dwie posiadÅ‚oÅ›ci z których każda bÄ™dzie mogÅ‚a mieć indywidualne ustawienia. +Niektóre ustawienia zostanÄ… zmienione na domyÅ›lne po tej operacji. + +Podzielić posiadÅ‚ość? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="CannotDivideLandNoRegion"> + Brak możliwoÅ›ci podziaÅ‚u posiadÅ‚oÅ›ci: +Region, gdzie posiadÅ‚ość siÄ™ znajduje nie zostaÅ‚ odnaleziony. + </notification> + <notification name="CannotJoinLandNoRegion"> + Brak możliwoÅ›ci zÅ‚Ä…czenia posiadÅ‚oÅ›ci: +Region, gdzie posiadÅ‚ość siÄ™ znajduje nie zostaÅ‚ odnaleziony. + </notification> + <notification name="CannotJoinLandNothingSelected"> + Nie można poÅ‚Ä…czyć posiadÅ‚oÅ›ci: +PosiadÅ‚oÅ›ci nie zostaÅ‚y wybrane. + </notification> + <notification name="CannotJoinLandEntireParcelSelected"> + Nie można poÅ‚Ä…czyć posiadÅ‚oÅ›ci: +Tylko jedna posiadÅ‚ość zostaÅ‚a wybrana. + +Wybierz obaszar usytuowany na obu posiadÅ‚oÅ›ciach. + </notification> + <notification name="CannotJoinLandSelection"> + Nie można poÅ‚Ä…czyć posiadÅ‚oÅ›ci: +Musisz wybrać wiÄ™cej niż jednÄ… posiadÅ‚ość. + +Wybierz obaszar usytuowany na obu posiadÅ‚oÅ›ciach. + </notification> + <notification name="JoinLandWarning"> + PoÅ‚Ä…czenie tego obszaru utworzy jednÄ… wiÄ™kszÄ… posiadÅ‚ość ze wszystkich posiadÅ‚oÅ›ci przecinajÄ…cych wybrany prostokÄ…t. Nazwa i opcje posiadÅ‚oÅ›ci bedÄ… musiaÅ‚y zostać skonfigurowane. + +PoÅ‚Ä…czyć posiadÅ‚oÅ›ci? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmNotecardSave"> + Ta notka musi być zapisana żeby mogÅ‚a być skopiowana lub zobaczona. Zapisać notkÄ™? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmItemCopy"> + Skopiować ten obiekt do Twojej szafy? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Skopiuj"/> + </notification> + <notification name="ResolutionSwitchFail"> + Zmiana rozdzielczoÅ›ci do [RESX] x [RESY] nie powidÅ‚a siÄ™ + </notification> + <notification name="ErrorUndefinedGrasses"> + BÅ‚Ä…d: niezdefiniowane trawy: [SPECIES] + </notification> + <notification name="ErrorUndefinedTrees"> + BÅ‚ad: niezdefiniowane drzewa: [SPECIES] + </notification> + <notification name="CannotSaveWearableOutOfSpace"> + Nie można zapisać '[NAME]' do pliku stroju. Musisz zwolnić trochÄ™ miejsca na Twoim komputerze i zapisać strój jeszcze raz. + </notification> + <notification name="CannotSaveToAssetStore"> + Nie można zapisać [NAME] w centralnym zbiorze danych. +Zazwyczaj jest to tymczasowy problem. Możesz kontynuować modyfikacje i zapisać strój ponownie za kilka minut. + </notification> + <notification name="YouHaveBeenLoggedOut"> + NastÄ…piÅ‚o wylogowanie z [SECOND_LIFE] + [MESSAGE] + <usetemplate name="okcancelbuttons" notext="WyÅ‚Ä…cz" yestext="Kontynuuj"/> + </notification> + <notification name="OnlyOfficerCanBuyLand"> + Nie możesz kupić posiadÅ‚oÅ›ci dla grupy. +Nie masz praw kupowania posiadÅ‚oÅ›ci dla Twojej aktywnej grupy. + </notification> + <notification label="Add Friend" name="AddFriendWithMessage"> + Znajomi mogÄ… pozwalać na odnajdywanie siÄ™ wzajemnie na mapie i na otrzymywanie notyfikacji o logowaniu do [SECOND_LIFE]. + +Zaproponować znajomość [NAME]? + <form name="form"> + <input name="message"> + Chcesz zawrzeć znajomość? + </input> + <button name="Offer" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification label="Zapisz strój" name="SaveOutfitAs"> + Zapisz to co noszÄ™ jako nowy strój: + <form name="form"> + <input name="message"> + [DESC] (nowe) + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification label="Zapisz część stroju" name="SaveWearableAs"> + Zapisz obiekt w mojej Szafie jako: + <form name="form"> + <input name="message"> + [DESC] (nowy) + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification label="ZmieÅ„ nazwÄ™ stroju" name="RenameOutfit"> + Nowa nazwa stroju: + <form name="form"> + <input name="new_name"> + [NAME] + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="RemoveFromFriends"> + Czy chcesz usunąć [NAME] z listy znajomych? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="RemoveMultipleFromFriends"> + Chcesz usunąć grupÄ™ osób z listy Twoich znajomych? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="GodDeleteAllScriptedPublicObjectsByUser"> + Na pewno chcesz usunąć wszystkie skryptowane obiekty należące do +** [AVATAR_NAME] ** +z posiadÅ‚oÅ›ci innych w tym symulatorze? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="GodDeleteAllScriptedObjectsByUser"> + Na pewno chcesz usunąć wszystkie skryptowane obiekty należące do +** [AVATAR_NAME] ** +ze wszystkich posiadÅ‚oÅ›ci w tym symulatorze? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="GodDeleteAllObjectsByUser"> + Na pewno chcesz usunąć wszystkie obiekty (skryptowane i nie) należące do +** [AVATAR_NAME] ** +ze wszystkich posiadÅ‚oÅ›ci w tym symulatorze? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BlankClassifiedName"> + Musisz nadać tytuÅ‚ Twojej reklamie. + </notification> + <notification name="MinClassifiedPrice"> + Minimalna cena za publikacjÄ™ wynosi [MIN_PRICE]L$. + +Wybierz wyższÄ… cenÄ™. + </notification> + <notification name="ConfirmItemDeleteHasLinks"> + Co najmiej jeden z elementów, które masz posiada poÅ‚Ä…czone z nim obiekty. JeÅ›li go usuniesz poÅ‚Ä…czenia zostanÄ… usuniÄ™te na staÅ‚e. Zaleca siÄ™ usuniÄ™cie poÅ‚Ä…czeÅ„ w pierwszej kolejnoÅ›ci. + +JesteÅ› pewnien/pewna, że chcesz usunąć te elementy? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteLock"> + Przynajmnie jeden z wybranych obiektów jest zablokowany. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteNoCopy"> + Przynajmniej jeden z wybranych obiektów jest niekopiowalny. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteNoOwn"> + Przynajmniej jeden z wybranych obiektów nie należy do Ciebie. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteLockNoCopy"> + Przynajmnie jeden z wybranych obiektów jest zablokowany. +Przynajmniej jeden z wybranych obiektów jest niekopiwalny. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteLockNoOwn"> + Przynajmnie jeden z wybranych obiektów jest zablokowany. +Przynajmniej jeden z wybranych obiektów nie należy do Ciebie. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteNoCopyNoOwn"> + Przynajmniej jeden z wybranych obiektów jest niekopiowalny. +Przynajmniej jeden z wybranych obiektów nie należy do Ciebie. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectDeleteLockNoCopyNoOwn"> + Przynajmnie jeden z wybranych obiektów jest zablokowany. +Przynajmniej jeden z wybranych obiektów jest niekopiwalny. +Przynajmniej jeden z wybranych obiektów nie należy do Ciebie. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectTakeLock"> + Przynajmnie jeden obiekt jest zablokowany. + +Na pewno chcesz usunąć te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectTakeNoOwn"> + Przynajmniej jeden obiekt nie należy do Ciebie. +Jeżeli bÄ™dziesz kontynuować prawa nastÄ™pnego wÅ‚aÅ›ciciela zostanÄ… przypisane co, potencjalnie, może ograniczyć Twoje prawa do modyfikacji lub kopiowania obiektów. + +Na pewno chcesz wziąść te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmObjectTakeLockNoOwn"> + Przynajmnie jeden obiekt jest zablokowany. +Przynajmniej jeden obiekt nie należy do Ciebie. +Jeżeli bÄ™dziesz kontynuować prawa nastÄ™pnego wÅ‚aÅ›ciciela zostanÄ… przypisane co, potencjalnie, może ograniczyć Twoje prawa do modyfikacji lub kopiowania obiektów. + +Na pewno chcesz wziąść te obiekty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="CantBuyLandAcrossMultipleRegions"> + Nie możesz kupić posiadÅ‚oÅ›ci ponieważ wybrany obszar przekracza granicÄ™ regionów. + +Wybierz mniejszy obszar i spróbuj jeszcze raz. + </notification> + <notification name="DeedLandToGroup"> + Po przekazaniu tej posiadÅ‚oÅ›ci grupa bÄ™dzia musiaÅ‚a mieć i utrzymywać wystarczajÄ…cy kredyt na używanie posiadÅ‚oÅ›ci. Cena zakupu posiadÅ‚oÅ›ci nie jest zwracana wÅ‚aÅ›cicielowi. Jeżeli przekazana posiadÅ‚ość zostanie sprzedana, cana sprzedaży zostanie podzielona pomiÄ™dzy czÅ‚onków grupy. + +Przekazać tÄ… posiadÅ‚ość o powierzchni [AREA] m² grupie '[GROUP_NAME]'? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="DeedLandToGroupWithContribution"> + Po przekazaniu tej posiadÅ‚oÅ›ci grupa bÄ™dzia musiaÅ‚a mieć i utrzymywać wystarczajÄ…cy kredyt na używanie posiadÅ‚oÅ›ci. +Przekazanie bÄ™dzie zawierać równoczesne przypisanie posiadÅ‚oÅ›ci do grupy od '[NAME]'. +Cena zakupu posiadÅ‚oÅ›ci nie jest zwracana wÅ‚aÅ›cicielowi. Jeżeli przekazana posiadÅ‚ość zostanie sprzedana, cana sprzedaży zostanie podzielona pomiÄ™dzy czÅ‚onków grupy. + +Przekazać tÄ… posiadÅ‚ość o powierzchni [AREA] m² grupie '[GROUP_NAME]'? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="DisplaySetToSafe"> + Ustawienia grafiki zostaÅ‚y zmienione do bezpiecznego poziomu ponieważ opcja -safe zostaÅ‚a wybrana. + </notification> + <notification name="DisplaySetToRecommended"> + Ustawienia grafiki zostaÅ‚y zmienione do zalecanego poziomu na podstawie konfiguracji Twojego systemu. + </notification> + <notification name="ErrorMessage"> + [ERROR_MESSAGE] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AvatarMovedDesired"> + Miejsce, do którego chcesz siÄ™ teleportować jest chwilowo nieobecne. +ZostaÅ‚eÅ› przeniesiony do regionu sÄ…siedniego. + </notification> + <notification name="AvatarMovedLast"> + Twoje miejsce startu jest obecnie niedostÄ™pne. +ZostaÅ‚eÅ› przeniesiony do sÄ…siedniego regionu. + </notification> + <notification name="AvatarMovedHome"> + Twoje miejsce startu jest obecnie niedostÄ™pne. +ZostaÅ‚eÅ› przeniesiony do pobliskiego regionu. +Możesz ustawić nowe miejsce startu. + </notification> + <notification name="ClothingLoading"> + Twoje ubranie wciąż siÄ™ Å‚aduje. +Możesz normalnie używać [SECOND_LIFE], inni użytkownicy bÄ™dÄ… CiÄ™ widzieli poprawnie. + <form name="form"> + <ignore name="ignore" text="Åadowanie ubraÅ„ nadal trwa"/> + </form> + </notification> + <notification name="FirstRun"> + Instalacja [APP_NAME] zakoÅ„czona. + +Jeżeli używasz [SECOND_LIFE] po raz pierwszy to musisz stworzyć konto żeby móc siÄ™ zalogować. +Czy chcesz przejść na stronÄ™ [http://join.secondlife.com secondlife.com] żeby stworzyć nowe konto? + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Nowe konto..."/> + </notification> + <notification name="LoginPacketNeverReceived"> + Problemy z poÅ‚Ä…czeniem. Problem może być spowodowany Twoim poÅ‚Ä…czeniem z Internetem albo może istnieć po stronie [SECOND_LIFE_GRID]. + +Możesz sprawdzić swoje poÅ‚Ä…czenie z Internetem i spróbować ponownie za kilka minut lub poÅ‚Ä…czyć siÄ™ ze stronÄ… pomocy technicznej tutaj [SUPPORT_SITE] lub wybrać Teleportuj by teleportować siÄ™ do swojego miejsca startu. + <form name="form"> + <button name="OK" text="OK"/> + <button name="Help" text="Pomoc"/> + <button name="Teleport" text="Teleportuj"/> + </form> + </notification> + <notification name="WelcomeChooseSex"> + Twoja postać pojawi siÄ™ za moment. + +Używaj strzaÅ‚ek żeby sie poruszać. +NaciÅ›nij F1 w dowolnej chwili po pomoc albo żeby dowiedzieć siÄ™ wiÄ™cej o [SECOND_LIFE]. +Wybierz awatara wÅ‚aÅ›ciwej pÅ‚ci. +Ten wybór bÄ™dzie można później zmienić. + <usetemplate name="okcancelbuttons" notext="Kobieta" yestext="Mężczyzna"/> + </notification> + <notification name="CantTeleportToGrid"> + Nie można teleportować do [SLURL], ponieważ jest na innym gridzie ([GRID]) niż obecny grid ([CURRENT_GRID]). ProszÄ™ zamknąć przeglÄ…darkÄ™ i spróbować ponownie. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GeneralCertificateError"> + PoÅ‚Ä…czenie z serwerem nie mogÅ‚o zostać nawiÄ…zane. +[REASON] + +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Valid From: [VALID_FROM] +Valid To: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +SHA1 Fingerprint: [MD5_DIGEST] +Key Usage: [KEYUSAGE] +Extended Key Usage: [EXTENDEDKEYUSAGE] +Subject Key Identifier: [SUBJECTKEYIDENTIFIER] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TrustCertificateError"> + Wydawca certyfikatu dla tego serwera nie jest znany. + +Informacje o certyfikacie: +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Valid From: [VALID_FROM] +Valid To: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +SHA1 Fingerprint: [MD5_DIGEST] +Key Usage: [KEYUSAGE] +Extended Key Usage: [EXTENDEDKEYUSAGE] +Subject Key Identifier: [SUBJECTKEYIDENTIFIER] + +Czy chcesz zaufać temu wydawcy? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Zaufaj"/> + </notification> + <notification name="NotEnoughCurrency"> + [NAME] [PRICE]L$ Masz za maÅ‚o L$. + </notification> + <notification name="GrantedModifyRights"> + Masz teraz prawa modyfikacji obiektów należących do [NAME]. + </notification> + <notification name="RevokedModifyRights"> + Prawa modyfikacji obiektów należących do [NAME] zostaÅ‚y Ci odebrane. + </notification> + <notification name="FlushMapVisibilityCaches"> + To spowoduje wyczyszczenie buforów map regionu. +Jest to użyteczne wyÅ‚Ä…cznie podczas szukania bÅ‚Ä™dów. +(Podczas produkcji poczekaj 5 minut i mapy wszystkich zostanÄ… uaktualnione po relogu.) + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyOneObjectOnly"> + Nie możesz zakupić wiÄ™cej niż jednego obiektu w tym samym czasie. ProszÄ™ wybrać tylko jeden obiekt i spróbować ponowanie. + </notification> + <notification name="OnlyCopyContentsOfSingleItem"> + Nie można kopiować zawartoÅ›ci wiÄ™cej niż jednego obiektu naraz. +Wybierz pojedynczy obiekt i spróbuj jeszcze raz. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="KickUsersFromRegion"> + Teleportować wszystkich Rezydentów z tego regionu to ich miejsca startu? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="EstateObjectReturn"> + Na pewno chcesz odesÅ‚ać wszystkie obiekty należące do +[USER_NAME] ? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="InvalidTerrainBitDepth"> + Nie można ustawić tekstur regionu: +Tekstura terenu [TEXTURE_NUM] ma niewÅ‚aÅ›ciwÄ… gÅ‚Ä™biÄ™ koloru - [TEXTURE_BIT_DEPTH]. +ZamieÅ„ teksturÄ™ [TEXTURE_NUM] na 24-o bitowÄ… teksturÄ™ o wymiarze 512x512 lub mniejszÄ… i ponownie kliknij Zastosuj. + </notification> + <notification name="InvalidTerrainSize"> + Nie można ustawić tekstur regionu: +Tekstura terenu [TEXTURE_NUM] jest za duża - [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y]. +ZamieÅ„ teksturÄ™ [TEXTURE_NUM] na 24-o bitowÄ… teksturÄ™ o wymiarze 512x512 lub mniejszÄ… i ponownie kliknij Zastosuj. + </notification> + <notification name="RawUploadStarted"> + Åadowanie rozpoczÄ™te. Może potrwać do dwóch minut zależnie od prÄ™dkoÅ›ci Twojego poÅ‚Ä…czenia. + </notification> + <notification name="ConfirmBakeTerrain"> + Na pewno chcesz zapisać obecne uksztaÅ‚towanie terenu jako punkt odniesienia dla górnego i dolnego limitu terenu i jako domyÅ›lÄ… wartość dla opcji Odtwórz? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="MaxAllowedAgentOnRegion"> + Maksymalna liczba goÅ›ci wynosi [MAX_AGENTS]. + </notification> + <notification name="MaxBannedAgentsOnRegion"> + Maksymalna liczba niepożądanych Rezydentów (banów) wynosi [MAX_BANNED]. + </notification> + <notification name="MaxAgentOnRegionBatch"> + Próba dodania [NUM_ADDED] osób nie powiodÅ‚a siÄ™: +[MAX_AGENTS] [LIST_TYPE] limit przekroczony o [NUM_EXCESS]. + </notification> + <notification name="MaxAllowedGroupsOnRegion"> + Możesz mieć maksymalnie [MAX_GROUPS] dozwolonych grup. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Ustal"/> + </notification> + <notification name="MaxManagersOnRegion"> + Możesz mieć maksymalnie [MAX_MANAGER] zarzÄ…dców MajÄ…tku. + </notification> + <notification name="OwnerCanNotBeDenied"> + Nie możesz dodać wÅ‚aÅ›ciciela majÄ…tku do listy 'Niepożądanych Rezydentów (banów)' majÄ…tku. + </notification> + <notification name="CanNotChangeAppearanceUntilLoaded"> + Nie możesz zmienić wyglÄ…du podczas Å‚adowania ubraÅ„ i ksztaÅ‚tów. + </notification> + <notification name="ClassifiedMustBeAlphanumeric"> + TytuÅ‚ Twojej reklamy musi zaczynać siÄ™ od litery (A-Z) albo cyfry. Znaki przestankowe sÄ… niedozwolone. + </notification> + <notification name="CantSetBuyObject"> + Nie możesz wybrać Kup obiekt ponieważ obiekt nie jest na sprzedaż. +Wybierz obiekt na sprzedaż i spróbuj jeszcze raz. + </notification> + <notification name="FinishedRawDownload"> + Plik surowego terenu zaÅ‚adowany pod: +[DOWNLOAD_PATH]. + </notification> + <notification name="DownloadWindowsMandatory"> + Nowa wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Musisz zainstalować nowÄ… wersjÄ™ żeby używać [APP_NAME]. + <usetemplate name="okcancelbuttons" notext="WyÅ‚Ä…cz program" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="DownloadWindows"> + Uaktualniona wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prÄ™dkoÅ›ci i stabilnoÅ›ci. + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="DownloadWindowsReleaseForDownload"> + Uaktualniona wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prÄ™dkoÅ›ci i stabilnoÅ›ci. + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="DownloadLinuxMandatory"> + Nowa wersja [APP_NAME] jest dostÄ™pna. +[MESSAGE] +Musisz pobrać aktualizacjÄ™ aby korzystać z [APP_NAME]. + <usetemplate name="okcancelbuttons" notext="Wyjdź" yestext="Pobieranie"/> + </notification> + <notification name="DownloadLinux"> + Aktualizacja [APP_NAME] jest dostÄ™pna. +[MESSAGE] +Ta aktualizacja nie jest wymagana ale zaleca siÄ™ jej instalacjÄ™ w celu poprawienia szybkoÅ›ci i stabilnoÅ›ci. + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Pobieranie"/> + </notification> + <notification name="DownloadLinuxReleaseForDownload"> + Uaktualniona wersja [APP_NAME]zostaÅ‚a opublikowana. +[MESSAGE] +Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prÄ™dkoÅ›ci i stabilnoÅ›ci. + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Pobieranie"/> + </notification> + <notification name="DownloadMacMandatory"> + Nowa wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Musisz zainstalować nowÄ… wersjÄ™ żeby używać [APP_NAME]. + +Pobrać i zapisać w folderze Aplikacji? + <usetemplate name="okcancelbuttons" notext="WyÅ‚Ä…cz program" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="DownloadMac"> + Uaktualniona wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prÄ™dkoÅ›ci i stabilnoÅ›ci. + +Pobrać i zapisać w folderze Aplikacji? + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="DownloadMacReleaseForDownload"> + Uaktualniona wersja [APP_NAME] zostaÅ‚a opublikowana. +[MESSAGE] +Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prÄ™dkoÅ›ci i stabilnoÅ›ci. + +Pobrać i zapisać w folderze Aplikacji? + <usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="ZaÅ‚aduj"/> + </notification> + <notification name="FailedUpdateInstall"> + Podczas aktualizacji pojawiÅ‚ siÄ™ bÅ‚Ä…d. ProszÄ™ pobrać i zainstalować najnowszego klienta z http://secondlife.com/download. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="FailedRequiredUpdateInstall"> + Nie można zainstalować wymaganej aktualizacji. Nie bÄ™dzie można zalogować siÄ™ dopóki [APP_NAME] nie zostanie zaktualizowana. + ProszÄ™ pobrać i zainstalować najnowszÄ… wersjÄ™ z http://secondlife.com/download. + <usetemplate name="okbutton" yestext="Rezygnuj"/> + </notification> + <notification name="UpdaterServiceNotRunning"> + Istnieje obowiÄ…zkowa aktualizacja dla Second Life. Możesz jÄ… pobrać z http://www.secondlife.com/downloads lub zainstalować teraz. + <usetemplate name="okcancelbuttons" notext="Opuść Second Life" yestext="Pobierz i zainstaluj teraz"/> + </notification> + <notification name="DownloadBackgroundTip"> + Aktualizacja dla [APP_NAME] zostaÅ‚a pobrana. +Wersja [VERSION] [[RELEASE_NOTES_FULL_URL] Informacja o tej aktualizacji] + <usetemplate name="okcancelbuttons" notext="Później..." yestext="Zainstaluj teraz i restartuj [APP_NAME]"/> + </notification> + <notification name="DownloadBackgroundDialog"> + Aktualizacja [APP_NAME] zostaÅ‚a pobrana. +Wersja [VERSION] [[RELEASE_NOTES_FULL_URL] Informacja o aktualizacji] + <usetemplate name="okcancelbuttons" notext="Później..." yestext="Zainstaluj teraz i restartuj [APP_NAME]"/> + </notification> + <notification name="RequiredUpdateDownloadedVerboseDialog"> + Pobrano wymaganÄ… aktualizacjÄ™. +Wersja [VERSION] + +W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME]. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="RequiredUpdateDownloadedDialog"> + W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME]. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="DeedObjectToGroup"> + Przekazanie tego obiektu spowoduje, że grupa: +* Otrzyma L$ zapÅ‚acone temu obiektowi + <usetemplate ignoretext="ProszÄ™ potwierdzić decyzjÄ™ przed przepisaniem obiektu do grupy" name="okcancelignore" notext="Anuluj" yestext="Przekaż"/> + </notification> + <notification name="WebLaunchExternalTarget"> + Czy chcesz otworzyć swojÄ… przeglÄ…darkÄ™ internetowÄ… by zobaczyć zawartość? + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by zobaczyć stronÄ™ internetowÄ…" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchJoinNow"> + By dokonać zmian i aktualizacji swojego konta, odwiedź [http://secondlife.com/account/ Dashboard]. + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by dokonać zmian w konfiguracji mojego konta" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchSecurityIssues"> + Odwiedź [SECOND_LIFE] Wiki i zobacz jak zgÅ‚aszać problemy z bezpieczeÅ„stwem danych. + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by dowiedzieć siÄ™ wiÄ™cej na temat zgÅ‚aszania problemów bezpieczeÅ„stwa" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchQAWiki"> + Odwiedź [SECOND_LIFE] Wiki pytaÅ„ i odpowiedzi. + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by zobaczyć QA Wiki" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchPublicIssue"> + Odwiedź [SECOND_LIFE] katalog publicznych problemów, gdzie możesz zgÅ‚aszać bÅ‚Ä™dy i inne problemy. + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by wysÅ‚ać BÅ‚Ä™dy klienta" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchSupportWiki"> + Otwórz oficjalny blog Lindenów żeby zobaczyć nowe wiadomoÅ›ci i informacje. + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by zobaczyć blog" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchLSLGuide"> + Czy chcesz otworzyć samouczek JÄ™zyka skryptowania? + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by samouczek JÄ™zyka skryptowania" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="WebLaunchLSLWiki"> + Czy napewno chcesz odwiedzić portal LSL Portal? + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by LSL Portal" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ReturnToOwner"> + Czy na pewno chcesz zwrócić wybrane obiekty do ich wÅ‚aÅ›cicieli? Wszystkie udostÄ™pnione obiekty z prawem transferu zostanÄ… zwrócone poprzednim wÅ‚aÅ›cicielom. + +*UWAGA* Wszystkie udostÄ™pnione obiekty bez prawa transferu zostanÄ… usuniÄ™te! + <usetemplate ignoretext="Potwierdź zanim zwrócisz obiekty do ich wÅ‚aÅ›cicieli" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="GroupLeaveConfirmMember"> + JesteÅ› czÅ‚onkiem grupy [GROUP]. +Chcesz opuÅ›cić grupÄ™? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmKick"> + Napewno chcesz wyrzucić wszystkich Rezydentów z gridu? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Wyrzuć wszystkich Rezydentów"/> + </notification> + <notification name="MuteLinden"> + Przepraszamy, ale nie możesz zablokować Lindena. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CannotStartAuctionAlreadyForSale"> + Aukcja nie może zostać rozpoczÄ™ta w posiadÅ‚oÅ›ci, która zostaÅ‚a już wczeÅ›niej wystawiona na aukcjÄ™. Deaktywuj opcjÄ™ sprzedaży posiadÅ‚oÅ›ci jeżeli chcesz rozpocząć aukcjÄ™. + </notification> + <notification label="Zablokuj obiekty wedÅ‚ug wpisanej nazwy" name="MuteByNameFailed"> + Rezydent/obiekt jest już zablokowany. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="RemoveItemWarn"> + Pomimo, że jest to dozwolone, usuniÄ™cie zawartoÅ›ci może zniszczyć obiekt. Chcesz usunąć? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="CantOfferCallingCard"> + Nie możesz dać wizytówki w tym momencie. Spróbuj jeszcze raz za chwilÄ™. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="CantOfferFriendship"> + Nie możesz zaoferować znajomoÅ›ci w tym momencie. Spróbuj jeszcze raz za chwilÄ™. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="BusyModeSet"> + Tryb Pracy jest wÅ‚Ä…czony. +Czat i IM bÄ™dÄ… ukryte. WysÅ‚ane IM bÄ™dÄ… otrzymywaÅ‚y TwojÄ… odpowiedź Trybu Pracy. Propozycje teleportacji bÄ™dÄ… odrzucone. +Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywane w folderze "Kosz" w Twojej szafie. + <usetemplate ignoretext="Status zmieniony na Tryb pracy" name="okignore" yestext="OK"/> + </notification> + <notification name="JoinedTooManyGroupsMember"> + Należysz już do maksymalnej iloÅ›ci grup. Opuść proszÄ™ przynajmniej jednÄ… grupÄ™ żeby przyjąć czÅ‚onkostwo w tej grupie, albo odmów. +[NAME] oferuje Ci czÅ‚onkostwo w grupie. + <usetemplate name="okcancelbuttons" notext="Odmów" yestext="Przyjmij"/> + </notification> + <notification name="JoinedTooManyGroups"> + Należysz już do maksymalnej iloÅ›ci grup. Opuść proszÄ™ przynajmiej jednÄ… grupÄ™ żeby przyjąć czÅ‚onkostwo w tej grupie, albo odmów. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="KickUser"> + Wyrzuć tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. + <form name="form"> + <input name="message"> + Administrator wylogowaÅ‚ CiÄ™. + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="KickAllUsers"> + Z jakim komunikatem wyrzucić wszystkich użytkowników z regionu? + <form name="form"> + <input name="message"> + Administrator wylogowaÅ‚ CiÄ™. + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="FreezeUser"> + Unieruchom tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. + <form name="form"> + <input name="message"> + Unieruchomiono CiÄ™. Nie możesz siÄ™ ruszać ani rozmawiać. Administrator skontaktuje siÄ™ z TobÄ… poprzez IM. + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="UnFreezeUser"> + Cofnij unieruchomienie tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. + <form name="form"> + <input name="message"> + Odblokowano CiÄ™. + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="SetDisplayNameSuccess"> + Witaj [DISPLAY_NAME]! + +Podobnie jak w realnym życiu potrzeba trochÄ™ czasu zanim wszyscy dowiedzÄ… siÄ™ o nowej nazwie. Kolejne kilka dni zajmie [http://wiki.secondlife.com/wiki/Setting_your_display_name aktualizacja nazwy] w obiektach, skryptach, wyszukiwarce, etc. + </notification> + <notification name="SetDisplayNameBlocked"> + Przepraszamy, nie można zmienić Twojej wyÅ›wietlanej nazwy. JeÅ›li uważasz ze jest to spowodowane bÅ‚Ä™dem skontaktuj siÄ™ z obsÅ‚ugÄ… klienta. + </notification> + <notification name="SetDisplayNameFailedLength"> + Przepraszamy, ta nazwa jest zbyt dÅ‚uga. WyÅ›wietlana nazwa może mieć maksymalnie [LENGTH] znaków. + +ProszÄ™ wprowadzić krótszÄ… nazwÄ™. + </notification> + <notification name="SetDisplayNameFailedGeneric"> + Przepraszamy, nie można ustawić Twojej wyÅ›wietlanej nazwy. Spróbuj ponownie później. + </notification> + <notification name="SetDisplayNameMismatch"> + Podana wyÅ›wietlana nazwa nie pasuje. ProszÄ™ wprowadzić jÄ… ponownie. + </notification> + <notification name="AgentDisplayNameUpdateThresholdExceeded"> + Przepraszamy, musisz jeszcze poczekać zanim bÄ™dzie można zmienić TwojÄ… wyÅ›wietlanÄ… nazwÄ™. + +Zobacz http://wiki.secondlife.com/wiki/Setting_your_display_name + +ProszÄ™ spróbować ponownie później. + </notification> + <notification name="AgentDisplayNameSetBlocked"> + Przepraszamy, nie można ustawić wskazanej nazwy, ponieważ zawiera zabronione sÅ‚owa. + + ProszÄ™ spróbować wprowadzić innÄ… nazwÄ™. + </notification> + <notification name="AgentDisplayNameSetInvalidUnicode"> + WyÅ›wietlana nazwa, którÄ… chcesz ustawić zawiera niepoprawne znaki. + </notification> + <notification name="AgentDisplayNameSetOnlyPunctuation"> + Twoje wyÅ›wietlane imiÄ™ musi zawierać litery inne niż znaki interpunkcyjne. + </notification> + <notification name="DisplayNameUpdate"> + [OLD_NAME] ([SLID]) jest od tej pory znana/znany jako [NEW_NAME]. + </notification> + <notification name="OfferTeleport"> + Zaproponować teleportacjÄ™ do miejsca Twojego pobytu z tÄ… wiadomoÅ›ciÄ…? + <form name="form"> + <input name="message"> + Zapraszam do siebie. Region: [REGION] + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="OfferTeleportFromGod"> + WysÅ‚ać propozycjÄ™ teleportacji do Twojego miejsca? + <form name="form"> + <input name="message"> + Zapraszam do siebie. Region: [REGION] + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="TeleportFromLandmark"> + Na pewno chcesz siÄ™ teleportować do <nolink>[LOCATION]</nolink>? + <usetemplate ignoretext="Potwierdź próbÄ™ teleportacji do zapisanego miejsca" name="okcancelignore" notext="Anuluj" yestext="Teleportuj"/> + </notification> + <notification name="TeleportToPick"> + Teleportuj do [PICK]? + <usetemplate ignoretext="Potwierdź, że chcesz teleportować siÄ™ do miejsca w Ulubionych" name="okcancelignore" notext="Anuluj" yestext="Teleportuj"/> + </notification> + <notification name="TeleportToClassified"> + Teleportuj do [CLASSIFIED]? + <usetemplate ignoretext="Potwierdź, że chcesz teleportować siÄ™ do lokalizacji z reklamy" name="okcancelignore" notext="Anuluj" yestext="Teleportuj"/> + </notification> + <notification name="TeleportToHistoryEntry"> + Teleportuj do [HISTORY_ENTRY]? + <usetemplate ignoretext="Potwierdź teleportacjÄ™ do lokalizacji z historii" name="okcancelignore" notext="Anuluj" yestext="Teleportuj"/> + </notification> + <notification label="Wiadomość do Wszystkich w Twoim MajÄ…tku" name="MessageEstate"> + Wpisz krótkÄ… wiadomość która zostanie wysÅ‚ana do wszystkich osób w Twoim majÄ…tku. + <form name="form"> + <input name="message"/> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification label="Zmiana MajÄ…tku Lindenów" name="ChangeLindenEstate"> + Czy napewno chcesz zmienić ustawienia majÄ…tku Linden (mainland, teen grid, orientacja, itp). + +Jest to wyjÄ…tkowo niebezpieczna decyzja, odczuwalna przez wszystkich Rezydentów. Dla mainland, spowoduje to zmianÄ™ tysiÄ™cy regionów oraz ich przestrzeÅ„ serwerowÄ…. + +Kontynuować? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification label="Zmiana DostÄ™pu do MajÄ…tku Lindenów" name="ChangeLindenAccess"> + Dokonujesz zmiany w liÅ›cie dostÄ™pu Regionu głównego należącego do Lindenów (Regiony Główne, Teen Grid, Orientacja). + +Żądana operacja jest wyjÄ…tkowo niebezpieczna dla wszystkich Rezydentów przebywajÄ…cych w regionie i powinna być używana wyÅ‚Ä…cznie w celu zablokowania opcji pozwalajÄ…cej na przeniesienie obiektów/L$ do/z sieci. +Dodatkowo, zmiany dokonane w Regionie Głównym mogÄ… spowodować problemy przestrzeni serwerowej innych regionów. + +Kontynuować? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateAllowedAgentAdd"> + Dodać do listy dostÄ™pu do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateAllowedAgentRemove"> + Usunąć z listy dostÄ™pu do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateAllowedGroupAdd"> + Dodać do listy dostÄ™pu grup do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateAllowedGroupRemove"> + Usunąć z listy dostÄ™pu grup do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateBannedAgentAdd"> + Zablokować dostÄ™p do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateBannedAgentRemove"> + Zdjąć tego Rezydenta z listy niepożądanych (bany) dla tego majÄ…tku czy dla [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateManagerAdd"> + Dodać zarzÄ…dce majÄ…tku do tego majÄ…tku czy do [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Wybierz MajÄ…tek" name="EstateManagerRemove"> + Usunąć zarzÄ…dce majÄ…tku z tego majÄ…tku czy z [ALL_ESTATES]? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Wszystkie majÄ…tki" yestext="Ten majÄ…tek"/> + </notification> + <notification label="Potwierdź Wyrzucenie" name="EstateKickUser"> + Wyrzucić [EVIL_USER] z tego majÄ…tku? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="EstateChangeCovenant"> + Na pewno chcesz zminić treść umowy dla tego majÄ…tku? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="RegionEntryAccessBlocked"> + Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku. + +Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="RegionEntryAccessBlocked_KB"> + Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. + +Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <url name="url"> + https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 + </url> + <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> + </notification> + <notification name="RegionEntryAccessBlocked_Notify"> + Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. + </notification> + <notification name="RegionEntryAccessBlocked_Change"> + Nie masz zezwolenia na przebywanie w tym Regionie z powodu Twojego statusu ustawieÅ„ wieku. + +W celu uzyskania dostÄ™pu do tego regiony zmieÅ„ proszÄ™ swój status ustawieÅ„ wieku. BÄ™dziesz mógÅ‚/mogÅ‚a szukać i mieć dostÄ™p do treÅ›ci [REGIONMATURITY]. W celu cofniÄ™cia zmian wybierz z menu Ja > Ustawienia > Ogólne. + <form name="form"> + <button name="OK" text="ZmieÅ„ ustawienia"/> + <button default="true" name="Cancel" text="Zamknij"/> + <ignore name="ignore" text="Moje ustawienia wieku nie dopuszczajÄ… do regionu"/> + </form> + </notification> + <notification name="PreferredMaturityChanged"> + Twoja obecna klasyfikacja wieku to [RATING]. + </notification> + <notification name="LandClaimAccessBlocked"> + W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz odzyskać tej posiadÅ‚oÅ›ci. Możesz potrzebować weryfikacji wieku bÄ…dź instalacji najnowszej wersji klienta. + +Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="LandClaimAccessBlocked_KB"> + Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci. + +Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <url name="url"> + https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 + </url> + <usetemplate ignoretext="W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz odzyskać tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> + </notification> + <notification name="LandClaimAccessBlocked_Notify"> + Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci. + </notification> + <notification name="LandClaimAccessBlocked_Change"> + W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz odzyskać tej posiadÅ‚oÅ›ci. + +Możesz wybrać 'ZmieÅ„ Ustawienia' by dokonać zmian w ustawieniach Twojego wieku by uzyskać dostÄ™p do regionu. Wówczas bÄ™dziesz w stanie znaleźć oraz mieć dostÄ™p do [REGIONMATURITY] treÅ›ci. Jeżeli zdecydujesz siÄ™ na powrót do poprzednich ustawieÅ„, wybierz Ja > Ustawienia > Główne. + <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="ZmieÅ„ Ustawienia"/> + </notification> + <notification name="LandBuyAccessBlocked"> + Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku. + +Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="LandBuyAccessBlocked_KB"> + Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. + +Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + <url name="url"> + https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 + </url> + <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> + </notification> + <notification name="LandBuyAccessBlocked_Notify"> + Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. + </notification> + <notification name="LandBuyAccessBlocked_Change"> + W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz kupić tej posiadÅ‚oÅ›ci. + +Możesz wybrać 'ZmieÅ„ Ustawienia' by dokonać zmian w ustawieniach Twojego wieku by uzyskać dostÄ™p do regionu. Wówczas bÄ™dziesz w stanie znaleźć oraz mieć dostÄ™p do [REGIONMATURITY] treÅ›ci. Jeżeli zdecydujesz siÄ™ na powrót do poprzednich ustawieÅ„, wybierz Ja > Ustawienia > Główne. + <usetemplate ignoretext="W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz kupić tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="ZmieÅ„ Ustawienia"/> + </notification> + <notification name="TooManyPrimsSelected"> + Zbyt wiele wybranych obiektów. Wybierz [MAX_PRIM_COUNT] lub mniej i spróbuj ponownie + </notification> + <notification name="ProblemImportingEstateCovenant"> + Problem z importem umowy majÄ…tku. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ProblemAddingEstateManager"> + Problemy z dodawaniem nowego zarzÄ…dcy majÄ…tku. Jeden lub wiÄ™caj majÄ…tk może mieć wypeÅ‚nionÄ… listÄ™ zarzÄ…dców. + </notification> + <notification name="ProblemAddingEstateGeneric"> + Problemy z dodawaniem do listy majÄ…tku. Jeden lub wiÄ™caj majÄ…tk może mieć wypeÅ‚nionÄ… listÄ™. + </notification> + <notification name="UnableToLoadNotecardAsset"> + Brak możliwoÅ›ci zaÅ‚adowania noty w tej chwili. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="NotAllowedToViewNotecard"> + NiewystarczajÄ…ce prawa do zobaczenia notki przypisanej do wybranego ID. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MissingNotecardAssetID"> + ID notki nie znalezione w bazie danych. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="PublishClassified"> + PamiÄ™taj: OpÅ‚aty za reklamÄ™ sÄ… bezzwrotne. + +ZamieÅ›cić tÄ… reklamÄ™ za [AMOUNT]L$? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="SetClassifiedMature"> + Czy ta reklama zawiera treść 'Mature'? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="SetGroupMature"> + Czy ta grupa zawiera treść 'Mature'? + <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification label="Potwierdź Restart" name="ConfirmRestart"> + Na pewno chcesz zrobić restart tego regionu za 2 minuty? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification label="Wiadomość do Wszystkich w tym Regionie" name="MessageRegion"> + Wpisz krótkÄ… wiadomość która zostanie wysÅ‚ana do wszystkich osób w tym regionie. + <form name="form"> + <input name="message"/> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification label="Zmienione Restrykcje Wieku dla Regionu" name="RegionMaturityChange"> + Ustawienie restrykcji wieku dla regionu zostaÅ‚o zmienione. +Zazwyczaj musi upÅ‚ynąć nieco czasu zanim ta zmiana zostanie odzwierciedlona na mapie. + +Aby wejść do regionu Adult, Rezydenci muszÄ… posiadać zweryfikowane konto, albo w wyniku weryfikacji wieku albo pÅ‚atoÅ›ci. + </notification> + <notification label="Wersja Niezgodna z Systemem Rozmów" name="VoiceVersionMismatch"> + Ta wersja [APP_NAME] nie jest kompatybilna z systemem rozmów w tym Regionie. Musisz zainstalować aktualnÄ… wersjÄ™ [APP_NAME] aby komunikacja gÅ‚osowa dziaÅ‚aÅ‚a poprawnie. + </notification> + <notification label="Nie Można Kupić Obiektów" name="BuyObjectOneOwner"> + Jednorazowo możesz kupować tylko od jednego wÅ‚aÅ›ciciela. +Wybierz pojedynczy obiekt i spróbuj jeszcze raz. + </notification> + <notification label="Nie Można Kupić ZawartoÅ›ci" name="BuyContentsOneOnly"> + Jednorazowo możesz kupić zawartość tylko jednego obiektu. +Wybierz pojedynczy obiekt i spróbuj jeszcze raz. + </notification> + <notification label="Nie Można Kupić ZawartoÅ›ci" name="BuyContentsOneOwner"> + Jednorazowo możesz kupować tylko od jednego wÅ‚aÅ›ciciela. +Wybierz pojedynczy obiekt i spróbuj jeszcze raz. + </notification> + <notification name="BuyOriginal"> + Kupić oryginalny obiekt od [OWNER] za [PRICE]L$? +Zostaniesz wÅ‚aÅ›cicielem tego obiektu z nastÄ™pujÄ…cymi prawami: + Modyfikacje: [MODIFYPERM] + Kopiowanie: [COPYPERM] + Odsprzedawanie i oddawanie: [RESELLPERM] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyOriginalNoOwner"> + Kupić oryginalny obiekt za [PRICE]L$? +Zostaniesz wÅ‚aÅ›cicielem tego obiektu z nastÄ™pujÄ…cymi prawami: + Modyfikacje: [MODIFYPERM] + Kopiowanie: [COPYPERM] + Odsprzedawanie i oddawanie: [RESELLPERM] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyCopy"> + Kupić kopiÄ™ obiektu od [OWNER] za [PRICE]L$? +Obiekt zostanie skopiowany do Twojej szafy z nastÄ™pujÄ…cymi prawami: + Modyfikacje: [MODIFYPERM] + Kopiowanie: [COPYPERM] + Odsprzedawanie i oddawanie: [RESELLPERM] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyCopyNoOwner"> + Kupić kopiÄ™ obiektu za [PRICE]L$? +Obiekt zostanie skopiowany do Twojej szafy z nastÄ™pujÄ…cymi prawami: + Modyfikacje: [MODIFYPERM] + Kopiowanie: [COPYPERM] + Odsprzedawanie i oddawanie: [RESELLPERM] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyContents"> + Kupić zawartość od [OWNER] za [PRICE]L$? +Zawartość zostanie skopiowana do Twojej szafy. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BuyContentsNoOwner"> + Kupić zawartość za [PRICE]L$? +Zawartość zostanie skopiowana do Twojej szafy. + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmPurchase"> + Ta transakcja spowoduje: +[ACTION] + +Na pewno chcesz dokonać tego zakupu? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmPurchasePassword"> + Ta transakcja spowoduje: +[ACTION] + +Na pewno chcesz dokonać tego zakupu? +Wpisz hasÅ‚o ponownie i kliknij OK. + <form name="form"> + <input name="message"/> + <button name="ConfirmPurchase" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="SetPickLocation"> + Uwaga: +Lokalizacja tego wyboru zostaÅ‚a zaktualizowana ale pozostaÅ‚e szczegóły zachowajÄ… oryginalne wartoÅ›ci. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MoveInventoryFromObject"> + Wybrane obiekty Szafy nie majÄ… praw kopiowania. +Obiekty zostanÄ… przeniesione do Twojej Szafy, nie zostanÄ… skopiowane. + +Przenieść obiekty Szafy? + <usetemplate ignoretext="Uprzedź przed przeniesieniem zawartoÅ›ci niekopiowalnej z obiektu" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="MoveInventoryFromScriptedObject"> + Wybrane obiekty Szafy nie majÄ… praw kopiowania. +Obiekty zostanÄ… przeniesione do Twojej Szafy, nie zostanÄ… skopiowane. +Ponieważ obiekty zawierajÄ… skrypty, przeniesienie obiektów do Twojej Szafy może spowodować niepoprawne dziaÅ‚anie skryptów. + +Przenieść obiekty szafy? + <usetemplate ignoretext="Uprzedź przed przeniesieniem zawartoÅ›ci niekopiowalnej z obiektu, która może uszkodzić skrypty obiektu" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ClickActionNotPayable"> + Uwaga: Opcja ZapÅ‚ać obiektowi zostaÅ‚a wybrana, ale żeby ta opcja dziaÅ‚aÅ‚a musi być dodany skrypt z funkcjÄ… money(). + <form name="form"> + <ignore name="ignore" text="Opcja ZapÅ‚ać Obiektowi zostaÅ‚a aktywowana podczas budowania obiektów bez skryptu z funkcjÄ… money()."/> + </form> + </notification> + <notification name="OpenObjectCannotCopy"> + W tym obiekcie nie ma elementów które możesz skopiować. + </notification> + <notification name="WebLaunchAccountHistory"> + Przejść na stronÄ™ [http://secondlife.com/account/ Dashboard] żeby zobaczyć historiÄ™ konta? + <usetemplate ignoretext="Uruchom przeglÄ…darkÄ™ internetowÄ… by zobaczyć historiÄ™ konta" name="okcancelignore" notext="Anuluj" yestext="Idź na stronÄ™"/> + </notification> + <notification name="ConfirmQuit"> + Na pewno chcesz skoÅ„czyć? + <usetemplate ignoretext="Na pewno chcesz skoÅ„czyć?" name="okcancelignore" notext="Nie koÅ„cz" yestext="WyÅ‚Ä…cz"/> + </notification> + <notification name="DeleteItems"> + [QUESTION] + <usetemplate ignoretext="Potwierdź, że na pewno chcesz skasować obiekty" name="okcancelignore" notext="Cofnij" yestext="OK"/> + </notification> + <notification name="HelpReportAbuseEmailLL"> + Używaj tej opcji do zgÅ‚aszania nadużyć [http://secondlife.com/corporate/tos.php Warunków Umowy (Terms of Service)] i [http://secondlife.com/corporate/cs.php Standardów SpoÅ‚eczeÅ„stwa (Community Standards)]. + +Wszystkie zgÅ‚oszone nadużycia sÄ… badane i rozwiÄ…zywane. + </notification> + <notification name="HelpReportAbuseSelectCategory"> + Wybierz kategoriÄ™ dla tego raportu o nadużyciu. +OkreÅ›lenie kategorii pomoże nam w klasyfikacji i prztwarzaniu raportu. + </notification> + <notification name="HelpReportAbuseAbuserNameEmpty"> + Wprowadź imiÄ™ i nazwisko osoby popeÅ‚niajÄ…cej nadużycie. +DokÅ‚adne dane pomogÄ… nam w klasyfikacji i prztwarzaniu raportu. + </notification> + <notification name="HelpReportAbuseAbuserLocationEmpty"> + Wprowadź nazwÄ™ miejsca gdzie popeÅ‚niono nadużycie. +DokÅ‚adne dane pomogÄ… nam w klasyfikacji i prztwarzaniu raportu. + </notification> + <notification name="HelpReportAbuseSummaryEmpty"> + Wprowadź opis popeÅ‚nionego nadużycia. +DokÅ‚adne dane pomogÄ… nam w klasyfikacji i prztwarzaniu raportu. + </notification> + <notification name="HelpReportAbuseDetailsEmpty"> + Wprowadź szczgółowy opis popeÅ‚nionego nadużycia. +Podaj maksymalnÄ… ilość szczgółów oraz imiona i nazwiska osób zwiÄ…zanych z nadużyciem które zgÅ‚aszasz. +DokÅ‚adne dane pomogÄ… nam w klasyfikacji i prztwarzaniu raportu. + </notification> + <notification name="HelpReportAbuseContainsCopyright"> + Szanowny Rezydencie, + +Jeżeli skÅ‚adasz raport dotyczÄ…cy naruszenia praw autorskich proszÄ™ siÄ™ upewnić, że robisz to poprawnie: + +(1) Przypadek Nadużycia. Możesz zÅ‚ożyć raport jeżeli sÄ…dzisz, że Rezydent narusza system przywilejów [SECOND_LIFE], na przykÅ‚ad używajÄ…c CopyBot lub podobnych narzÄ™dzi robiÄ…cych kopie, naruszajÄ…c prawa autorskie. Komisja Nadużyć bada wykroczenia i stosuje akcje dyscyplinarne za zachowania sprzeczne z zasadami Warunków Umowy [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Terms of Service] i Standardów SpoÅ‚eczeÅ„stwa [http://secondlife.com/corporate/cs.php Community Standards]. Komisja Nadużyć nie zajmuje siÄ™ i nie odpowiada na żądania usuniÄ™cia treÅ›ci ze Å›rodowiska [SECOND_LIFE]. + +(2) Przypadek DMCA lub Usuwanie TreÅ›ci. Aby wystÄ…pić z żądaniem o usuniÄ™cie treÅ›ci ze Å›rodowiska [SECOND_LIFE] MUSISZ przedÅ‚ożyć ważne zawiadomienie o nadużyciu zgodne z naszÄ… politykÄ… DMCA [http://secondlife.com/corporate/dmca.php DMCA Policy]. + +Jeżeli chcesz kontynuować dalej zamknij to okno i dokoÅ„cz wysyÅ‚anie raportu. Może być potrzebny wybór kategorii 'CopyBot albo Nadużycie Przywilejów'. + +DziÄ™kujemy, + +Linden Lab + </notification> + <notification name="FailedRequirementsCheck"> + Brak nastÄ™pujÄ…cych wymaganych komponentów w [FLOATER]: +[COMPONENTS] + </notification> + <notification label="ZamieÅ„ IstniejÄ…cy Dodatek" name="ReplaceAttachment"> + Obecnie masz już doÅ‚Ä…czony obiekt do tej części Twojego ciaÅ‚a. +Chcesz go zamienić na wybrany obiekt? + <form name="form"> + <ignore name="ignore" save_option="true" text="Obecnie masz już doÅ‚Ä…czony obiekt do tej części Twojego ciaÅ‚a.Chcesz go zamienić na wybrany obiekt?"/> + <button ignore="ZamieÅ„ automatycznie" name="Yes" text="OK"/> + <button ignore="Nie zamieniaj" name="No" text="Anuluj"/> + </form> + </notification> + <notification label="Ostrzeżenie Trybu Pracy" name="BusyModePay"> + JesteÅ› w Trybie pracy co oznacza, że nie dostaniesz żadnych obiektów w zamian za tÄ… opÅ‚atÄ™. + +Chcesz wyÅ‚Ä…czyć Tryb pracy przed zakoÅ„czeniem tej tranzakcji? + <form name="form"> + <ignore name="ignore" save_option="true" text="JesteÅ› w Trybie Pracy co oznacza, że nie dostaniesz żadnych obiektów w zamian za tÄ… opÅ‚atÄ™. Chcesz wyÅ‚Ä…czyć Tryb Pracy przed zakoÅ„czeniem tej transakcji?"/> + <button ignore="Zawsz wyÅ‚Ä…czaj tryb pracy" name="Yes" text="OK"/> + <button ignore="Nie wyÅ‚Ä…czaj trybu pracy" name="No" text="Anuluj"/> + </form> + </notification> + <notification name="ConfirmDeleteProtectedCategory"> + Ten folder '[FOLDERNAME]' to folder systemowy. UsuniÄ™cie foldera systemowego spowoduje niestabilność. Czy na pewno chcesz go skasować? + <usetemplate ignoretext="Potwierdź zanim folder systemu zostanie skasowany" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmEmptyTrash"> + Na pewno chcesz permanentnie usunąć zawartość Kosza? + <usetemplate ignoretext="Potwierdź przed usuniÄ™ciem zawartoÅ›ci Kosza" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmClearBrowserCache"> + Na pewno chcesz wyczyÅ›cić bufor przeglÄ…darki? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmClearCookies"> + Na pewno chcesz wyczyÅ›cić ciasteczka? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Tak"/> + </notification> + <notification name="ConfirmClearMediaUrlList"> + Na pewno chcesz wyczyÅ›cić listÄ™ zapisanych linków? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Tak"/> + </notification> + <notification name="ConfirmEmptyLostAndFound"> + Na pewno chcesz permanentnie usunąć zawartość Twojego foldera Zgubione i odnalezione? + <usetemplate ignoretext="Potwierdź przed usuniÄ™ciem zawartoÅ›ci foldera Zagubione i odnalezione" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="CopySLURL"> + NastÄ™pujÄ…cy link SLURL zostaÅ‚ skopiowany do schowka: + [SLURL] + +Zamieść go na stronie internetowej żeby umożliwić innym Å‚atwy dostÄ™p do tego miejsca, albo wklej go do panela adresu Twojej przeglÄ…darki żeby go otworzyć. + <form name="form"> + <ignore name="ignore" text="SLurl skopiowany do schowka"/> + </form> + </notification> + <notification name="WLSavePresetAlert"> + Chcesz zmienić zapisane ustawienia? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="WLDeletePresetAlert"> + Chcesz usunąć [SKY]? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="WLNoEditDefault"> + Nie możesz edytować lub usunąć domyÅ›lnych ustawieÅ„. + </notification> + <notification name="WLMissingSky"> + Ten plik cyklu dziennego używa brakujÄ…cego pliku nieba: [SKY]. + </notification> + <notification name="PPSaveEffectAlert"> + Efekt post-procesu już istnieje. Chcesz zapisać nowy na jego miejsce? + <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> + </notification> + <notification name="NewSkyPreset"> + Nazwij nowe niebo. + <form name="form"> + <input name="message"> + Nowe ustawienie + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="ExistsSkyPresetAlert"> + Ustawienie już istnieje! + </notification> + <notification name="NewWaterPreset"> + Nazwij nowe ustawienie wody. + <form name="form"> + <input name="message"> + Nowe ustawienie + </input> + <button name="OK" text="OK"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="ExistsWaterPresetAlert"> + Ustawienie już istnieje! + </notification> + <notification name="WaterNoEditDefault"> + DomyÅ›lne ustawienie nie może być zmienione ani usuniÄ™te. + </notification> + <notification name="ChatterBoxSessionStartError"> + BÅ‚Ä…d podczas rozpoczynania czatu/IM z [RECIPIENT]. +[REASON] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ChatterBoxSessionEventError"> + [EVENT] +[REASON] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ForceCloseChatterBoxSession"> + Twój czat/IM z [NAME] zostanie zamkniÄ™ty. +[REASON] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="Cannot_Purchase_an_Attachment"> + Rzeczy nie mogÄ… być kupione jeżeli sÄ… częściÄ… zaÅ‚Ä…cznika. + </notification> + <notification label="ProÅ›ba o ZgodÄ™ na Pobieranie L$" name="DebitPermissionDetails"> + AkceptujÄ…c tÄ… proÅ›bÄ™ wyrażasz zgodÄ™ na ciÄ…gÅ‚e pobieranie Lindenów (L$) z Twojego konta. Å»eby cofnąć to pozwolenie wÅ‚aÅ›ciciel obiektu bÄ™dzie musiaÅ‚ usunąć ten obiekt albo zresetowć skrypty obieku. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AutoWearNewClothing"> + Czy chcesz automatycznie nosić ubranie które tworzysz? + <usetemplate ignoretext="Załóż ubranie automatycznie bÄ™dÄ…c w trybie Edycji WyglÄ…du" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="NotAgeVerified"> + Nie masz dostÄ™pu do tej posiadÅ‚oÅ›ci ze wzglÄ™du na brak weryfikacji Twojego wieku. Czy chcesz odwiedzić stronÄ™ [SECOND_LIFE] żeby to zmienić? + +[_URL] + <url name="url" option="0"> + https://secondlife.com/account/verification.php + </url> + <usetemplate ignoretext="Brak weryfikacji wieku" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="Cannot enter parcel: no payment info on file"> + Nie masz dostÄ™pu do tej posiadÅ‚oÅ›ci ze wzglÄ™du na brak danych o Twoim koncie. Czy chcesz odwiedzić stronÄ™ [SECOND_LIFE] żeby to zmienić? + +[_URL] + <url name="url" option="0"> + https://secondlife.com/account/ + </url> + <usetemplate ignoretext="Brak danych o koncie" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="MissingString"> + Zdanie [STRING_NAME] nie znalezione w strings.xml + </notification> + <notification name="SystemMessageTip"> + [MESSAGE] + </notification> + <notification name="IMSystemMessageTip"> + [MESSAGE] + </notification> + <notification name="Cancelled"> + Anulowane + </notification> + <notification name="CancelledSit"> + Siadanie anulowane + </notification> + <notification name="CancelledAttach"> + DoÅ‚Ä…czenie anulowane + </notification> + <notification name="ReplacedMissingWearable"> + BarkujÄ…ce ubranie/części ciaÅ‚a zastÄ…piono domyÅ›lnymi obiektami. + </notification> + <notification name="GroupNotice"> + Temat: [SUBJECT], Treść: [MESSAGE] + </notification> + <notification name="FriendOnline"> + [NAME] jest w Second Life + </notification> + <notification name="FriendOffline"> + [NAME] opuszcza Second Life + </notification> + <notification name="AddSelfFriend"> + Nie możesz dodać siebie do listy znajomych. + </notification> + <notification name="UploadingAuctionSnapshot"> + Åadowanie obrazu z Internetu... +(Zajmuje okoÅ‚o 5 minut.) + </notification> + <notification name="UploadPayment"> + Åadowanie kosztowaÅ‚o [AMOUNT]L$. + </notification> + <notification name="UploadWebSnapshotDone"> + Åadowanie obrazu z Internetu zakoÅ„czne pomyÅ›lnie. + </notification> + <notification name="UploadSnapshotDone"> + Åadowanie zdjÄ™cia zakoÅ„czone pomyÅ›lnie. + </notification> + <notification name="TerrainDownloaded"> + Plik terrain.raw Å›ciÄ…gniety. + </notification> + <notification name="GestureMissing"> + Gesturka [NAME] nie znaleziony w bazie danych. + </notification> + <notification name="UnableToLoadGesture"> + Åadowanie gesturki [NAME] nie powiodÅ‚o siÄ™. + </notification> + <notification name="LandmarkMissing"> + Miejsce (LM) nie znalezione w bazie danych. + </notification> + <notification name="UnableToLoadLandmark"> + Åadowanie miejsca (LM) nie powiodÅ‚o siÄ™. +Spróbuj jeszcze raz. + </notification> + <notification name="CapsKeyOn"> + Twój Caps Lock jest wÅ‚Ä…czony. +Ponieważ to ma wpÅ‚yw na wpisywane hasÅ‚o, możesz chcieć go wyÅ‚Ä…czyć. + </notification> + <notification name="NotecardMissing"> + Notka nie zostaÅ‚a znaleziona w bazie danych. + </notification> + <notification name="NotecardNoPermissions"> + Nie masz pozwolenia na zobaczenie notki. + </notification> + <notification name="RezItemNoPermissions"> + Nie masz pozwolenia na stworzenie obiektu. + </notification> + <notification name="UnableToLoadNotecard"> + Nie można zaÅ‚adować danych notki w tym momencie. + </notification> + <notification name="ScriptMissing"> + Skrypt nie znaleziony w bazie danych. + </notification> + <notification name="ScriptNoPermissions"> + Nie masz pozwolenia na zobaczenie skryptu. + </notification> + <notification name="UnableToLoadScript"> + Åadowanie skryptu nie powiodÅ‚o siÄ™. +Spróbuj jeszcze raz. + </notification> + <notification name="IncompleteInventory"> + Zawartość obiektów którÄ… chcesz podarować nie jest dostÄ™pna lokalnie. Spróbuj podarować te obiekty jeszcze raz za jakiÅ› czas. + </notification> + <notification name="CannotModifyProtectedCategories"> + Nie możesz zmienić chronionych kategorii. + </notification> + <notification name="CannotRemoveProtectedCategories"> + Nie możesz usunąć chronionych kategorii. + </notification> + <notification name="UnableToBuyWhileDownloading"> + Nie można kupować w trakcie Å‚adowania danych obiektu. +Spróbuj jeszcze raz. + </notification> + <notification name="UnableToLinkWhileDownloading"> + Nie można Å‚Ä…czyć w trakcie Å‚adowania danych obiektu. +Spróbuj jeszcze raz. + </notification> + <notification name="CannotBuyObjectsFromDifferentOwners"> + Nie możesz jednoczeÅ›nie kupować obiektów od różnych osób. +Wybierz jeden obiekt. + </notification> + <notification name="ObjectNotForSale"> + Obiekt nie jest na sprzedaż. + </notification> + <notification name="EnteringGodMode"> + WÅ‚Ä…cznie trybu boskiego, poziom [LEVEL] + </notification> + <notification name="LeavingGodMode"> + WyÅ‚Ä…czanie trybu boskiego, poziom [LEVEL] + </notification> + <notification name="CopyFailed"> + Nie masz praw do skopiowania wybranych obiektów. + </notification> + <notification name="InventoryAccepted"> + Podarunek od Ciebie zostaÅ‚ przyjÄ™ty przez [NAME]. + </notification> + <notification name="InventoryDeclined"> + Podarunek od Ciebie zostaÅ‚ odrzucony przez [NAME]. + </notification> + <notification name="ObjectMessage"> + [NAME]: [MESSAGE] + </notification> + <notification name="CallingCardAccepted"> + Twoja wizytówka zostaÅ‚a przyjÄ™ta. + </notification> + <notification name="CallingCardDeclined"> + Twoja wizytówka zostaÅ‚a odrzucona. + </notification> + <notification name="TeleportToLandmark"> + JesteÅ› w Głównym Regionie i możesz siÄ™ stÄ…d teleportować do innych miejsc jak '[NAME]' wybierajÄ…c Moja Szafa w prawym dolnym rogu ekranu +i wybierajÄ…c folder Zapisane Miejsca (LM). +(Kliknij dwa razy na miejsce (LM) i wybierz 'Teleport' żeby tam siÄ™ przenieść.) + </notification> + <notification name="TeleportToPerson"> + Możesz skontaktować siÄ™ z Rezydentem '[NAME]' poprzez otworzenie panelu Ludzie po prawej stronie ekranu. +Wybierz Rezydenta z listy, nastÄ™pnie kliknij 'IM' na dole panelu. +(Możesz także kliknąć podwójnie na ich imiÄ™ na liÅ›cie, lub prawym przyciskiem i wybrać 'IM'). + </notification> + <notification name="CantSelectLandFromMultipleRegions"> + Nie możesz przekraczać granic serwera wybierajÄ…c obszar. +Spróbuj wybrać mniejszy obszar. + </notification> + <notification name="SearchWordBanned"> + Pewne frazy podczas wyszukiwania zostaÅ‚y usuniÄ™te w zwiÄ…zku z restrykcjami zawartymi w Standardach SpoÅ‚ecznoÅ›ciowych (Community Standards). + </notification> + <notification name="NoContentToSearch"> + ProszÄ™ wybrać przynajmiej jeden z podanych rodzajów treÅ›ci jakÄ… zawiera region podczas wyszukiwania ('General', 'Moderate', lub 'Adult'). + </notification> + <notification name="SystemMessage"> + [MESSAGE] + </notification> + <notification name="PaymentReceived"> + [MESSAGE] + </notification> + <notification name="PaymentSent"> + [MESSAGE] + </notification> + <notification name="EventNotification"> + Zawiadomienie o imprezie: + +[NAME] +[DATE] + <form name="form"> + <button name="Details" text="Szczegóły"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="TransferObjectsHighlighted"> + Obiekty na tej posiadÅ‚oÅ›ci które zostanÄ… przekazane kupcowi tej posiadÅ‚oÅ›ci sÄ… teraz rozjaÅ›nione. + +* Drzewa i trawy które zostanÄ… przekazne nie sÄ… rozjaÅ›nione. + <form name="form"> + <button name="Done" text="Zastosuj"/> + </form> + </notification> + <notification name="DeactivatedGesturesTrigger"> + Zablokowane gesturki z jednakowym aktywowaniem: +[NAMES] + </notification> + <notification name="NoQuickTime"> + WyglÄ…da na to, że QuickTime z Apple nie jest zainstalowany na Twoim komputerze. +Jeżeli chcesz odtwarzać media na tej posiadÅ‚oÅ›ci które używajÄ… QuickTime idź do [http://www.apple.com/quicktime strona QuickTime] i zainstaluj odtwarzacz. + </notification> + <notification name="NoPlugin"> + Nie znaleziono wtyczki mediów dla "[MIME_TYPE]" typu mime. Media tego typu bÄ™dÄ… niedostÄ™pne. + </notification> + <notification name="MediaPluginFailed"> + NastÄ™pujÄ…ce wtyczki mediów nie dziaÅ‚ajÄ…: + [PLUGIN] + +Zainstaluj proszÄ™ wtyczki ponownie lub skontaktuj siÄ™ z dostawcÄ… jeÅ›li nadal problem bÄ™dzie wystÄ™powaÅ‚. + <form name="form"> + <ignore name="ignore" text="Wtyczka mediów nie dziaÅ‚a"/> + </form> + </notification> + <notification name="OwnedObjectsReturned"> + Twoje obiekty z wybranej posiadÅ‚oÅ›ci zostaÅ‚y zwrócone do Twojej Szafy. + </notification> + <notification name="OtherObjectsReturned"> + Obiekty należące do [NAME] na wybranej posiadÅ‚oÅ›ci zostaÅ‚y zwrócone do Szafy tej osoby. + </notification> + <notification name="OtherObjectsReturned2"> + Obiekty z posiadÅ‚oÅ›ci należącej do Rezydenta'[NAME]' zostaÅ‚y zwrócone do wÅ‚aÅ›ciciela. + </notification> + <notification name="GroupObjectsReturned"> + Obiekty z wybranej posiadÅ‚oÅ›ci przypisane do grupy [GROUPNAME] zostaÅ‚y zwrócone do szafy ich wÅ‚aÅ›cicieli. +Przekazywalne obiekty przekazne grupie zostaÅ‚y zwrócone do ich poprzednich wÅ‚aÅ›cicieli. +Nieprzekazywalne obiekty przekazane grupie zostaÅ‚y usuniÄ™te. + </notification> + <notification name="UnOwnedObjectsReturned"> + Obiekty z wybranej posiadÅ‚oÅ›ci które nie należą do Ciebie zostaÅ‚y zwrócone do ich wÅ‚aÅ›cicieli. + </notification> + <notification name="ServerObjectMessage"> + Wiadomość od [NAME]: +<nolink>[MSG]</nolink> + </notification> + <notification name="NotSafe"> + Ta posiadÅ‚ość pozwala na uszkodzenia. +Możesz doznać tutaj urazu. Jeżeli zginiesz nastÄ…pi teleportacja do Twojego miejsca startu. + </notification> + <notification name="NoFly"> + Ta posiadÅ‚ość nie pozwala na latanie. +Nie możesz tutaj latać. + </notification> + <notification name="PushRestricted"> + Popychanie niedozwolone. Nie możesz tutaj popychać innych, chyba, że jesteÅ› wÅ‚aÅ›cicielem tej posiadÅ‚oÅ›ci. + </notification> + <notification name="NoVoice"> + Ta posiadÅ‚ość nie pozwala na rozmowy. + </notification> + <notification name="NoBuild"> + Ta posiadÅ‚ość nie pozwala na budowanie. Nie możesz tworzyć tutaj obiektów. + </notification> + <notification name="ScriptsStopped"> + Administrator czasowo zatrzymaÅ‚ skrypty w tym regionie. + </notification> + <notification name="ScriptsNotRunning"> + Å»adne skrypty nie dziaÅ‚ajÄ… w tym regionie. + </notification> + <notification name="NoOutsideScripts"> + Ta posiadÅ‚ość nie pozwala na zewnÄ™trzne skrypty. + +Å»adne skrypty nie bÄ™dÄ… tutaj dziaÅ‚ać za wyjÄ…tkiem skryptów należących do wÅ‚aÅ›ciciela posiadÅ‚oÅ›ci. + </notification> + <notification name="ClaimPublicLand"> + Tylko publiczne posiadÅ‚oÅ›ci w tym regionie mogÄ… być przejÄ™te. + </notification> + <notification name="RegionTPAccessBlocked"> + Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. Możesz potrzebować weryfikacji wieku bÄ…dź instalacji najnowszej wersji klienta. + +Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. + </notification> + <notification name="URBannedFromRegion"> + ZostaÅ‚eÅ› zbanowany w regionie. + </notification> + <notification name="NoTeenGridAccess"> + Twoje konto nie może zostać poÅ‚Ä…czone z podanym regionem Teen Grid. + </notification> + <notification name="ImproperPaymentStatus"> + Nie posiadasz odpowiedniego statusu pÅ‚atniczego by uzyskać dostÄ™p do regionu. + </notification> + <notification name="MustGetAgeParcel"> + By móc przebywać na tej posiadÅ‚oÅ›ci wymagana jest weryfikacja Twojego wieku. + </notification> + <notification name="NoDestRegion"> + Żądana lokalizacja regionu nie zostaÅ‚a odnaleziona. + </notification> + <notification name="NotAllowedInDest"> + Brak dostÄ™pu do podanej lokalizacji. + </notification> + <notification name="RegionParcelBan"> + Nie możesz przejść przez zamkniÄ™tÄ… posiadÅ‚ość. Spróbuj skorzystać z innej drogi. + </notification> + <notification name="TelehubRedirect"> + ZostaÅ‚eÅ› przeniesiony do teleportera. + </notification> + <notification name="CouldntTPCloser"> + Brak możliwoÅ›ci teleportacji do bliższej lokacji. + </notification> + <notification name="TPCancelled"> + Teleportacja anulowana. + </notification> + <notification name="FullRegionTryAgain"> + Region, który chcesz odwiedzić jest w tej chwili peÅ‚ny. +Spróbuj ponowanie za kilka minut. + </notification> + <notification name="GeneralFailure"> + Nieudana próba. + </notification> + <notification name="RoutedWrongRegion"> + WysÅ‚ano niewÅ‚aÅ›ciwe poÅ‚Ä…czenie do regionu. ProszÄ™ spróbować ponownie. + </notification> + <notification name="NoValidAgentID"> + Nieważny identyfikator agenta. + </notification> + <notification name="NoValidSession"> + Nieważny identyfikator sesji. + </notification> + <notification name="NoValidCircuit"> + Nieważny obwód kodowania. + </notification> + <notification name="NoValidTimestamp"> + NiewÅ‚aÅ›ciwy czas zapisu. + </notification> + <notification name="NoPendingConnection"> + Brak możliwoÅ›ci wykonania poÅ‚Ä…czenia. + </notification> + <notification name="InternalUsherError"> + Podczas teleportacji nastÄ…piÅ‚ bÅ‚Ä…d wewnÄ™trzny, który może być wynikiem problemów serwera. + </notification> + <notification name="NoGoodTPDestination"> + Brak lokalizacji punktu do teleportacji w podanym regionie. + </notification> + <notification name="InternalErrorRegionResolver"> + Podczas próby odnalezienia globalnych współrzÄ™dych dla żądanej teleportacji pojawiÅ‚ siÄ™ wewnÄ™trzny bÅ‚Ä…d. Może być to wynikiem problemów serwera. + </notification> + <notification name="NoValidLanding"> + Nieważny punkt lÄ…dowania. + </notification> + <notification name="NoValidParcel"> + Nieważana posiadÅ‚ość. + </notification> + <notification name="ObjectGiveItem"> + Obiekt o nazwie <nolink>[OBJECTFROMNAME]</nolink>, którego wÅ‚aÅ›cicielem jest [NAME_SLURL] oferuje Tobie [ITEM_SLURL]. Korzystanie z tego obieku wymaga przelÄ…czenia siÄ™ na tryb zaawansowany, w którym bÄ™dzie można odszukać obiekt w Twojej Szafie. W celu przeÅ‚Ä…czenia trybu życia na zaawansowany, zamknij i uruchom ponownie aplikacjÄ™. Przed ponownym zalogowaniem zmieÅ„ tryb życia na ekranie logowania. + <form name="form"> + <button name="Keep" text="Zaakceptuj obiekt"/> + <button name="Discard" text="Odrzuć obiekt"/> + <button name="Mute" text="Zablokuj obiekt"/> + </form> + </notification> + <notification name="UserGiveItem"> + [NAME_SLURL] proponuje Tobie [ITEM_SLURL]. Korzystanie z tego obieku wymaga przelÄ…czenia siÄ™ na tryb zaawansowany, w którym bÄ™dzie można odszukać obiekt w Twojej Szafie. W celu przeÅ‚Ä…czenia trybu życia na zaawansowany, zamknij i uruchom ponownie aplikacjÄ™. Przed ponownym zalogowaniem zmieÅ„ tryb życia na ekranie logowania. + <form name="form"> + <button name="Show" text="Zaakceptuj obiekt"/> + <button name="Discard" text="Odrzuć obiekt"/> + <button name="Mute" text="Zablokuj użytkownika"/> + </form> + </notification> + <notification name="GodMessage"> + [NAME] + +[MESSAGE] + </notification> + <notification name="JoinGroup"> + [MESSAGE] + <form name="form"> + <button name="Join" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + <button name="Info" text="Info"/> + </form> + </notification> + <notification name="TeleportOffered"> + [NAME_SLURL] proponuje Ci teleportacjÄ™ do siebie: + +[MESSAGE] - [MATURITY_STR] <icon>[MATURITY_ICON]</icon> + <form name="form"> + <button name="Teleport" text="Teleportuj"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="TeleportOfferSent"> + Oferta teleportacji wysÅ‚ana do [TO_NAME] + </notification> + <notification name="GotoURL"> + [MESSAGE] +[URL] + <form name="form"> + <button name="Later" text="Póżniej"/> + <button name="GoNow..." text="Teraz..."/> + </form> + </notification> + <notification name="OfferFriendship"> + [NAME_SLURL] proponuje znajomość. + +[MESSAGE] + +(BÄ™dziecie mogli widzieć swój status online) + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + </form> + </notification> + <notification name="FriendshipOffered"> + Oferta znajomoÅ›ci dla [TO_NAME] + </notification> + <notification name="OfferFriendshipNoMessage"> + [NAME_SLURL] proponuje Ci znajomość. + +(Z zalożenia bÄ™dzie widzić swój status online.) + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + </form> + </notification> + <notification name="FriendshipAccepted"> + Twoja propozycja znajomoÅ›ci zostaÅ‚a przyjÄ™ta przez [NAME]. + </notification> + <notification name="FriendshipDeclined"> + Twoja propozycja znajomoÅ›ci zostaÅ‚a odrzucona przez [NAME]. + </notification> + <notification name="FriendshipAcceptedByMe"> + Propozycja znajomoÅ›ci zostaÅ‚a zaakceptowana. + </notification> + <notification name="FriendshipDeclinedByMe"> + Propozycja znajomoÅ›ci zostaÅ‚a odrzucona. + </notification> + <notification name="OfferCallingCard"> + [NAME] oferuje swojÄ… wizytówkÄ™. +Wizytówka w Twojej Szafie umożliwi szybki kontakt IM z tym Rezydentem. + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + </form> + </notification> + <notification name="RegionRestartMinutes"> + Restart regionu za [MINUTES] min. +NastÄ…pi wylogowanie jeżeli zostaniesz w tym regionie. + </notification> + <notification name="RegionRestartSeconds"> + Restart regionu za [SECONDS] sec. +NastÄ…pi wylogowanie jeżeli zostaniesz w tym regionie. + </notification> + <notification name="LoadWebPage"> + ZaÅ‚adować stronÄ™ [URL]? + +[MESSAGE] + +Od obiektu: <nolink>[OBJECTNAME]</nolink>, wÅ‚aÅ›ciciel wÅ‚aÅ›ciciel: [NAME]? + <form name="form"> + <button name="Gotopage" text="ZaÅ‚aduj"/> + <button name="Cancel" text="Anuluj"/> + </form> + </notification> + <notification name="FailedToFindWearableUnnamed"> + [TYPE] - nie znaleziono w bazie danych. + </notification> + <notification name="FailedToFindWearable"> + [TYPE] [DESC] - nie znaleziono w bazie danych. + </notification> + <notification name="InvalidWearable"> + Obiekt, który chcesz zaÅ‚ożyć używa narzÄ™dzia nieobecnego w wersji klienta, którÄ… używasz. By go zaÅ‚ożyć Å›ciÄ…gnij najnowszÄ… wersjÄ™ [APP_NAME]. + </notification> + <notification name="ScriptQuestion"> + Obiekt '<nolink>[OBJECTNAME]</nolink>', którego wÅ‚aÅ›cicielem jest '[NAME]', chciaÅ‚by: + +[QUESTIONS] +Czy siÄ™ zgadzasz? + <form name="form"> + <button name="Yes" text="Tak"/> + <button name="No" text="Nie"/> + <button name="Mute" text="Zablokuj"/> + </form> + </notification> + <notification name="ScriptQuestionCaution"> + Obiekt '<nolink>[OBJECTNAME]</nolink>', którego wÅ‚aÅ›cicielem jest '[NAME]' chciaÅ‚by: + +[QUESTIONS] +JeÅ›li nie ufasz temu obiektowi i jego kreatorowi, odmów. + +Czy siÄ™ zgadzasz? + <form name="form"> + <button name="Grant" text="Zaakceptuj"/> + <button name="Deny" text="Odmów"/> + <button name="Details" text="Szczegóły..."/> + </form> + </notification> + <notification name="ScriptDialog"> + [NAME]'s '<nolink>[TITLE]</nolink>' +[MESSAGE] + <form name="form"> + <button name="Ignore" text="Zignoruj"/> + </form> + </notification> + <notification name="ScriptDialogGroup"> + [GROUPNAME]'s '<nolink>[TITLE]</nolink>' +[MESSAGE] + <form name="form"> + <button name="Ignore" text="Zignoruj"/> + </form> + </notification> + <notification name="BuyLindenDollarSuccess"> + DziÄ™kujemy za wpÅ‚atÄ™! + +Twój stan konta L$ zostanie zaktualizowany w momencie zakoÅ„czenia transakcji. Jeżeli w ciÄ…gu 20 minut, Twój balans konta nie ulegnie zmianie, transakcja zostaÅ‚a anulowana. W tym przypadku, pobrana kwota zostanie zwrócona na stan konta w US$. + +Status transkacji możesz sprawdzić odwiedzajÄ…c HistoriÄ™ Transakcji swojego konta na [http://secondlife.com/account/ Dashboard] + </notification> + <notification name="FirstOverrideKeys"> + Twoje sterujÄ…ce klawisze zostaÅ‚y przejÄ™te przez obiekt. +Użyj strzaÅ‚ek lub AWSD żeby sprawdzić ich dziaÅ‚anie. +Niektóre obiekty (np broÅ„) wymagajÄ… trybu panoramicznego. +Nacisnij 'M' żeby go wybrać. + </notification> + <notification name="FirstSandbox"> + Ten region to piaskownica. + +Obiekty które tu zbudujesz mogÄ… zostać usuniÄ™te jak opuÅ›cisz ten obszar - piaskownice sÄ… regularnie czyszczone, sprawdź informacje na górze ekranu obok nazwy regionu. + </notification> + <notification name="MaxListSelectMessage"> + Maksymalnie możesz wybrać [MAX_SELECT] rzeczy +z tej listy. + </notification> + <notification name="VoiceInviteP2P"> + [NAME] zaprasza CiÄ™ do rozmowy gÅ‚osem. +Wybierz Zaakceptuj żeby rozmawiać albo Odmów żeby nie przyjąć zaproszenia. +Wybierz Zablokuj żeby wyciszyć dzwoniÄ…cÄ… osób + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + <button name="Mute" text="Zablokuj"/> + </form> + </notification> + <notification name="AutoUnmuteByIM"> + WysÅ‚ano [NAME] prywatnÄ… wiadomość i ta osoba zostaÅ‚a automatycznie odblokowana. + </notification> + <notification name="AutoUnmuteByMoney"> + Przekazano [NAME] pieniÄ…dze i ta osoba zostaÅ‚a automatycznie odblokowana. + </notification> + <notification name="AutoUnmuteByInventory"> + Zaoferowno [NAME] obiekty i ta osoba zostaÅ‚a automatycznie odblokowana. + </notification> + <notification name="VoiceInviteGroup"> + [NAME] zaczyna rozmowÄ™ z grupÄ… [GROUP]. +Wybierz Zaakceptuj żeby rozmawiać albo Odmów żeby nie przyjąć zaproszenia. Wybierz Zablokuj żeby wyciszyć dzwoniÄ…cÄ… osobÄ™. + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + <button name="Mute" text="Zablokuj"/> + </form> + </notification> + <notification name="VoiceInviteAdHoc"> + [NAME] zaczyna konferencjÄ™ gÅ‚osem. +Wybierz Zaakceptuj żeby rozmawiać albo Odmów żeby nie przyjąć zaproszenia. Wybierz Zablokuj żeby wyciszyć dzwoniÄ…cÄ… osobÄ™. + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + <button name="Mute" text="Zablokuj"/> + </form> + </notification> + <notification name="InviteAdHoc"> + [NAME] zaprasza CiÄ™ do konferencji poprzez Czat/IM. +Wybierz Zaakceptuj żeby zacząć czat albo Odmów żeby nie przyjąć zaproszenia. Wybierz Zablokuj żeby wyciszyć tÄ… osobÄ™. + <form name="form"> + <button name="Accept" text="Zaakceptuj"/> + <button name="Decline" text="Odmów"/> + <button name="Mute" text="Block"/> + </form> + </notification> + <notification name="VoiceChannelFull"> + Rozmowa w której chcesz uczestniczyć, [VOICE_CHANNEL_NAME], nie akceptuje wiÄ™cej rozmówców. Spróbuj póżniej. + </notification> + <notification name="ProximalVoiceChannelFull"> + Przepraszamy. Limit rozmów zostaÅ‚ przekroczony w tym obszarze. Spróbuj w innym miejscu. + </notification> + <notification name="VoiceChannelDisconnected"> + [VOICE_CHANNEL_NAME] odÅ‚Ä…czyÅ‚ siÄ™. PrzeÅ‚Ä…czanie do rozmowy przestrzennej. + </notification> + <notification name="VoiceChannelDisconnectedP2P"> + [VOICE_CHANNEL_NAME] skoÅ„czyÅ‚ rozmowÄ™. PrzeÅ‚Ä…czanie do rozmowy przestrzennej. + </notification> + <notification name="P2PCallDeclined"> + [VOICE_CHANNEL_NAME] odmówiÅ‚ poÅ‚Ä…czenia. PrzeÅ‚Ä…czanie do rozmowy przestrzennej. + </notification> + <notification name="P2PCallNoAnswer"> + [VOICE_CHANNEL_NAME] nie odpowiada. PrzeÅ‚Ä…czanie do rozmowy przestrzennej. + </notification> + <notification name="VoiceChannelJoinFailed"> + Brak poÅ‚Ä…czenia z [VOICE_CHANNEL_NAME], spróbuj póżniej. PrzeÅ‚Ä…czanie do rozmowy przestrzennej. + </notification> + <notification name="VoiceLoginRetry"> + Tworzymy kanaÅ‚ gÅ‚osu dla Ciebie. Moze potrwać minutÄ™. + </notification> + <notification name="VoiceEffectsExpired"> + Subskrypcja jednego lub wiÄ™cej z Voice Morph wygasÅ‚a. +[[URL] Kliknij tutaj] oby odnowić subskrypcjÄ™. + </notification> + <notification name="VoiceEffectsExpiredInUse"> + Czas aktywnoÅ›ci Voice Morph wygasÅ‚, normalne ustawienia Twojego gÅ‚osu zostaÅ‚y zastosowane. +[[URL] Kliknij tutaj] aby odnowić subskrypcjÄ™. + </notification> + <notification name="VoiceEffectsWillExpire"> + Jedno lub wiÄ™cej z Twoich Voice Morph wygaÅ›nie za mniej niż [INTERVAL] dni. +[[URL] Klinij tutaj] aby odnowić subskrypcjÄ™. + </notification> + <notification name="VoiceEffectsNew"> + Nowe Voice Morph sÄ… dostÄ™pne! + </notification> + <notification name="Cannot enter parcel: not a group member"> + Nie masz dostÄ™pu do posiadÅ‚oÅ›ci, nie należysz do wÅ‚aÅ›ciwej grupy. + </notification> + <notification name="Cannot enter parcel: banned"> + Masz wzbroniony wstÄ™p na tÄ… posiadÅ‚oÅ›ci (ban). + </notification> + <notification name="Cannot enter parcel: not on access list"> + Nie masz dostÄ™pu do posiadÅ‚oÅ›ci, nie jesteÅ› na liÅ›cie dostÄ™pu. + </notification> + <notification name="VoiceNotAllowed"> + Nie masz pozwolenia na poÅ‚Ä…czenie z rozmowÄ… [VOICE_CHANNEL_NAME]. + </notification> + <notification name="VoiceCallGenericError"> + BÅ‚Ä…d podczas Å‚Ä…czenia z rozmowÄ… [VOICE_CHANNEL_NAME]. Spróbuj póżniej. + </notification> + <notification name="UnsupportedCommandSLURL"> + Nie można otworzyć wybranego SLurl. + </notification> + <notification name="BlockedSLURL"> + SLurl zostaÅ‚ otrzymany z niesprawdzonej przeglÄ…darki i zostaÅ‚ zablokowany dla bezpieczeÅ„stwa. + </notification> + <notification name="ThrottledSLURL"> + Wiele SLurlów zostaÅ‚o otrzymanych w krótkim czasie od niesprawdzonej przeglÄ…darki. +ZostanÄ… zablokowane na kilka sekund dla bezpieczeÅ„stwa. + </notification> + <notification name="IMToast"> + [MESSAGE] + <form name="form"> + <button name="respondbutton" text="Odpowiedź"/> + </form> + </notification> + <notification name="ConfirmCloseAll"> + Czy chcesz zamknąć wszystkie wiadomoÅ›ci IM? + <usetemplate ignoretext="Potwierdź, przed zamkniÄ™ciem wszystkich wiadomoÅ›ci prywatnych (IM)." name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="AttachmentSaved"> + ZaÅ‚Ä…cznik zostaÅ‚ zapisany. + </notification> + <notification name="UnableToFindHelpTopic"> + Nie można znależć tematu pomocy dla tego elementu. + </notification> + <notification name="ObjectMediaFailure"> + BÅ‚Ä…d serwera: aktualizacja mediów nie powiodÅ‚a siÄ™. +'[ERROR]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TextChatIsMutedByModerator"> + Twój czat zostaÅ‚ wyciszony przez moderatora. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="VoiceIsMutedByModerator"> + Twoja rozmowa gÅ‚osowa zostaÅ‚a wyciszona przez moderatora. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmClearTeleportHistory"> + Czy na pewno chcesz usunąć historiÄ™ teleportacji? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="BottomTrayButtonCanNotBeShown"> + Wybrany przycisk nie może zostać wyÅ›wietlony w tej chwili. +Przycisk zostanie wyÅ›wietlony w przypadku dostatecznej iloÅ›ci przestrzeni. + </notification> + <notification name="ShareNotification"> + Zaznacz Rezydentów, z którymi chcesz siÄ™ podzielić. + </notification> + <notification name="ShareItemsConfirmation"> + Czy na pewno chcesz udostÄ™pnić nastÄ™pujÄ…ce obiekty: + +<nolink>[ITEMS]</nolink> + +nastÄ™pujÄ…cym Rezydentom: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Ok"/> + </notification> + <notification name="ItemsShared"> + Obiekty zostaÅ‚y udostÄ™pnione. + </notification> + <notification name="DeedToGroupFail"> + Przekazanie grupie nie powiodÅ‚o siÄ™. + </notification> + <notification name="AvatarRezNotification"> + ( [EXISTENCE] sekund w Second Life) +Awatar '[NAME]' rozchmurzyÅ‚ siÄ™ po [TIME] sekundach. + </notification> + <notification name="AvatarRezSelfBakedDoneNotification"> + ( [EXISTENCE] sekund w Second Life) +You finished baking your outfit after [TIME] seconds. + </notification> + <notification name="AvatarRezSelfBakedUpdateNotification"> + ( [EXISTENCE] sekund w Second Life ) +WysÅ‚ano aktualizacjÄ™ wyglÄ…du po [TIME] sekundach. +[STATUS] + </notification> + <notification name="AvatarRezCloudNotification"> + ( [EXISTENCE] sekund w Second Life ) +Awatar '[NAME]' staÅ‚ siÄ™ chmurÄ…. + </notification> + <notification name="AvatarRezArrivedNotification"> + ( [EXISTENCE] sekund w Second Life) +Awatar '[NAME]' pojawiÅ‚ siÄ™. + </notification> + <notification name="AvatarRezLeftCloudNotification"> + ( [EXISTENCE] sekund w Second Life ) +Awatar '[NAME]' pozostaÅ‚ [TIME] sekund chmurÄ…. + </notification> + <notification name="AvatarRezEnteredAppearanceNotification"> + ( [EXISTENCE] sekund w Second Life ) +Awatar '[NAME]' rozpoczÄ…Å‚ edycjÄ™ wyglÄ…du. + </notification> + <notification name="AvatarRezLeftAppearanceNotification"> + ( [EXISTENCE] sekund w Second Life ) +Awatar '[NAME]' opuÅ›ciÅ‚ edycjÄ™ wyglÄ…du. + </notification> + <notification name="NoConnect"> + WystÄ™puje problem z poÅ‚Ä…czeniem [PROTOCOL] [HOSTID]. +ProszÄ™ sprawdź swojÄ… sieć i ustawienia firewall. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="NoVoiceConnect"> + WystÄ™puje problem z Twoim poÅ‚Ä…czniem gÅ‚osowym: + +[HOSTID] + +Komunikacja gÅ‚osowa nie bÄ™dzie dostÄ™pna. +ProszÄ™ sprawdź swojÄ… sieć i ustawienia firewall. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AvatarRezLeftNotification"> + ( [EXISTENCE] sekund w Second Life) +Awatar '[NAME]' pozostaÅ‚ w peÅ‚ni zaÅ‚adowany. + </notification> + <notification name="AvatarRezSelfBakedTextureUploadNotification"> + ( [EXISTENCE] sekund w Second Life ) +Zbakowane tekstury [RESOLUTION] dla '[BODYREGION]' zostaÅ‚y zaÅ‚adowane po[TIME] sekundach. + </notification> + <notification name="AvatarRezSelfBakedTextureUpdateNotification"> + ( [EXISTENCE] sekund w Second Life ) +Zbakowane tekstury zostaÅ‚y lokalnie zaktualizowane [RESOLUTION] dla '[BODYREGION]' po [TIME] sekundach. + </notification> + <notification name="ConfirmLeaveCall"> + Czy jestes pewien/pewna, że chcesz zakoÅ„czyć rozmowÄ™? + <usetemplate ignoretext="Potwierdź zanim rozmowa gÅ‚osowa zostanie zakoÅ„czona" name="okcancelignore" notext="Nie" yestext="Tak"/> + </notification> + <notification name="ConfirmMuteAll"> + Wybrano wyciszenie wszystkich uczestników rozmowy gÅ‚osowej w grupie. +To spowoduje również wyciszenie wszystkich Rezydentów, którzy doÅ‚Ä…czÄ… póżniej do rozmowy, nawet jeÅ›li zakoÅ„czysz rozmowÄ™. + +Wyciszyć wszystkich? + <usetemplate ignoretext="Potwierdź zanim zostanÄ… wyciszeni wszyscy uczestnicy rozmowy gÅ‚osowej w grupie" name="okcancelignore" notext="Anuluj" yestext="Ok"/> + </notification> + <notification label="Czat" name="HintChat"> + W celu przylÄ…czenia siÄ™ do rozmowy zacznij pisać w poniższym polu czatu. + </notification> + <notification label="WstaÅ„" name="HintSit"> + Aby wstać i opuÅ›cić pozycjÄ™ siedzÄ…cÄ…, kliknij przycisk WstaÅ„. + </notification> + <notification label="Odkrywaj Åšwiat" name="HintDestinationGuide"> + Destination Guide zawiera tysiÄ…ce nowych miejsc do odkrycia. Wybierz lokalizacjÄ™ i teleportuj siÄ™ aby rozpocząć zwiedzanie. + </notification> + <notification label="Schowek" name="HintSidePanel"> + Schowek umożliwia szybki dostÄ™p do Twojej Szafy, ubraÅ„, profili i innych w panelu bocznym. + </notification> + <notification label="Ruch" name="HintMove"> + Aby chodzić lub biegać, otwórz panel ruchu i użyj strzaÅ‚ek do nawigacji. Możesz także używać strzaÅ‚ek z klawiatury. + </notification> + <notification label="WyÅ›wietlana nazwa" name="HintDisplayName"> + Ustaw wyÅ›wietlanÄ… nazwÄ™, którÄ… możesz zmieniać tutaj. Jest ona dodatkiem do unikatowej nazwy użytkownika, która nie może być zmieniona. Możesz zmienić sposób w jaki widzisz nazwy innych osób w Twoich Ustawieniach. + </notification> + <notification label="Ruch" name="HintMoveArrows"> + Użyj przycisków ze strzaÅ‚kami z klawiatury aby chodzić. JeÅ›li wciÅ›niesz strzaÅ‚kÄ™ 'do góry' podwójnie, zaczniesz biec. + </notification> + <notification label="Widok" name="HintView"> + To change your camera view, use the Orbit and Pan controls. Zresetuj widok poprzez wciÅ›niÄ™cie klawisza Esc lub chodzenie. + </notification> + <notification label="Szafa" name="HintInventory"> + Sprawdź swojÄ… SzafÄ™ aby znaleźć obiekty. Najnowsze obiekty mogÄ… być Å‚atwo odnalezione w zakÅ‚adce Nowe obiekty. + </notification> + <notification label="Otrzymano L$!" name="HintLindenDollar"> + Tutaj znajduje siÄ™ Twoj bieżący bilans L$. Kliknij Kup aby kupić wiÄ™cej L$. + </notification> + <notification name="PopupAttempt"> + WyskakujÄ…ce okienko zostaÅ‚o zablokowane. + <form name="form"> + <ignore name="ignore" text="Zezwól na wyskakujÄ…ce okienka"/> + <button name="open" text="Otwórz wyskakujÄ…ce okno."/> + </form> + </notification> + <notification name="AuthRequest"> + Strpna '<nolink>[HOST_NAME]</nolink>' w domenie '[REALM]' wymaga nazwy użytkownika i hasÅ‚a. + <form name="form"> + <input name="username" text="Nazwa użytkownika"/> + <input name="password" text="HasÅ‚o"/> + <button name="ok" text="WyÅ›lij"/> + <button name="cancel" text="Anuluj"/> + </form> + </notification> + <notification label="" name="ModeChange"> + Zmiana trybu wymaga restartu. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoClassifieds"> + Tworzenie i edycja reklam jest możliwa tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoGroupInfo"> + Tworzenie i edycja grup jest możliwa tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoPicks"> + Tworzenie i edycja Ulubionych jest możliwa jedynie w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoWorldMap"> + OglÄ…danie mapy Å›wiata jest możliwe tylko w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoVoiceCall"> + Rozmowy gÅ‚osowe sÄ… możliwe tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoAvatarShare"> + UdostÄ™pnienie jest możliwe tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <notification label="" name="NoAvatarPay"> + PÅ‚acenie innym Rezydentom jest możliwe tylko w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. + <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> + </notification> + <global name="UnsupportedCPU"> + - PrÄ™dkość Twojego CPU nie speÅ‚nia minimalnych wymagaÅ„. + </global> + <global name="UnsupportedGLRequirements"> + WyglÄ…da na to, że Twój system nie speÅ‚nia wymagaÅ„ sprzÄ™towych [APP_NAME]. [APP_NAME] wymaga karty graficznej kompatybilnej z OpenGL z multiteksturami. Jeżeli masz takÄ… kartÄ™ zainstaluj najnowsze sterowniki do niej i uaktualnienia systemu operacyjnego. + +Jeżeli wciąż masz problemy sprawdź: [SUPPORT_SITE]. + </global> + <global name="UnsupportedCPUAmount"> + 796 + </global> + <global name="UnsupportedRAMAmount"> + 510 + </global> + <global name="UnsupportedGPU"> + - Twoja karta graficzna nie speÅ‚nia minimalnych wymagaÅ„. + </global> + <global name="UnsupportedRAM"> + - Pamięć Twojego systemu nie speÅ‚nia minimalnych wymagaÅ„. + </global> + <global name="You can only set your 'Home Location' on your land or at a mainland Infohub."> + JeÅ›li jesteÅ› wÅ‚aÅ›cicielem posiadÅ‚oÅ›ci, możesz ustawić na niej miejsce startu. +W innym przypadku możesz poszukać na mapie miejsca oznaczone jako "Infohub". + </global> + <global name="You died and have been teleported to your home location"> + NastÄ…piÅ‚a Å›mierć i teleportacja do Miejsca Startu. + </global> +</notifications> diff --git a/indra/newview/skins/minimal/xui/pl/panel_adhoc_control_panel.xml b/indra/newview/skins/minimal/xui/pl/panel_adhoc_control_panel.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba0c85e4ef4811297922b339dd327d344648224d --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_adhoc_control_panel.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_im_control_panel"> + <layout_stack name="vertical_stack"> + <layout_panel name="call_btn_panel"> + <button label="DzwoÅ„" name="call_btn"/> + </layout_panel> + <layout_panel name="end_call_btn_panel"> + <button label="ZakoÅ„cz rozmowÄ™" name="end_call_btn"/> + </layout_panel> + <layout_panel name="voice_ctrls_btn_panel"> + <button label="PrzeÅ‚Ä…czniki gÅ‚osu" name="voice_ctrls_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/pl/panel_bottomtray.xml new file mode 100644 index 0000000000000000000000000000000000000000..f49d8209382702c24ad4cfb2d1bca5851cc2b494 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_bottomtray.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="bottom_tray"> + <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off"/> + <string name="SpeakBtnToolTip" value="WÅ‚Ä…cza/wyÅ‚Ä…cza mikrofon"/> + <string name="VoiceControlBtnToolTip" value="Pokazuje/Ukrywa panel kontroli gÅ‚osu"/> + <layout_stack name="toolbar_stack"> + <layout_panel name="gesture_panel"> + <gesture_combo_list label="Gesturki" name="Gesture" tool_tip="Pokazuje/Ukrywa gesturki"/> + </layout_panel> + <layout_panel name="cam_panel"> + <bottomtray_button label="Widok" name="camera_btn" tool_tip="Pokaż/Ukryj ustawienia kamery"/> + </layout_panel> + <layout_panel name="avatar_and_destinations_panel"> + <bottomtray_button label="Atrakcje turystyczne" name="destination_btn" tool_tip="Pokaż okno dotyczÄ…ce ludzi"/> + </layout_panel> + <layout_panel name="avatar_and_destinations_panel"> + <bottomtray_button label="Mój awatar" name="avatar_btn"/> + </layout_panel> + <layout_panel name="people_panel"> + <bottomtray_button label="Ludzie" name="show_people_button" tool_tip="Pokazuje okno dotyczÄ…ce ludzi"/> + </layout_panel> + <layout_panel name="profile_panel"> + <bottomtray_button label="Profil" name="show_profile_btn" tool_tip="Pokazuje okno profilu."/> + </layout_panel> + <layout_panel name="howto_panel"> + <bottomtray_button label="POMOC" name="show_help_btn" tool_tip="Otwiera temat pomocy Second Life"/> + </layout_panel> + <layout_panel name="im_well_panel"> + <chiclet_im_well name="im_well"> + <button name="Unread IM messages" tool_tip="Rozmowy"/> + </chiclet_im_well> + </layout_panel> + <layout_panel name="notification_well_panel"> + <chiclet_notification name="notification_well"> + <button name="Unread" tool_tip="OgÅ‚oszenia"/> + </chiclet_notification> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/pl/panel_group_control_panel.xml new file mode 100644 index 0000000000000000000000000000000000000000..074f572a4c9a3a7c593cfe152d681337e00db29c --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_group_control_panel.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_im_control_panel"> + <layout_stack name="vertical_stack"> + <layout_panel name="group_info_btn_panel"> + <button label="Grupa" name="group_info_btn"/> + </layout_panel> + <layout_panel name="call_btn_panel"> + <button label="DzwoÅ„" name="call_btn"/> + </layout_panel> + <layout_panel name="end_call_btn_panel"> + <button label="ZakoÅ„cz rozmowÄ™" name="end_call_btn"/> + </layout_panel> + <layout_panel name="voice_ctrls_btn_panel"> + <button label="Otwórz kontroler gÅ‚osu" name="voice_ctrls_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/pl/panel_im_control_panel.xml new file mode 100644 index 0000000000000000000000000000000000000000..4aadd3b93b24d3c1203d14f246dadeb20a625773 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_im_control_panel.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_im_control_panel"> + <layout_stack name="button_stack"> + <layout_panel name="view_profile_btn_panel"> + <button label="Profil" name="view_profile_btn"/> + </layout_panel> + <layout_panel name="add_friend_btn_panel"> + <button label="Poznaj" name="add_friend_btn"/> + </layout_panel> + <layout_panel name="teleport_btn_panel"> + <button label="Teleportuj" name="teleport_btn" tool_tip="Teleportuj"/> + </layout_panel> + <layout_panel name="share_btn_panel"> + <button label="UdostÄ™pnij" name="share_btn"/> + </layout_panel> + <layout_panel name="pay_btn_panel"> + <button label="ZapÅ‚ać" name="pay_btn"/> + </layout_panel> + <layout_panel name="call_btn_panel"> + <button label="DzwoÅ„" name="call_btn"/> + </layout_panel> + <layout_panel name="end_call_btn_panel"> + <button label="ZakoÅ„cz rozmowÄ™" name="end_call_btn"/> + </layout_panel> + <layout_panel name="voice_ctrls_btn_panel"> + <button label="PrzeÅ‚Ä…czniki gÅ‚osu" name="voice_ctrls_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_login.xml b/indra/newview/skins/minimal/xui/pl/panel_login.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc8e7399af15b2129f95fc182df736de6cf1f1c1 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_login.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_login"> + <panel.string name="forgot_password_url"> + http://secondlife.com/account/request.php + </panel.string> + <layout_stack name="login_widgets"> + <layout_panel name="login"> + <text name="username_text"> + Użytkownik: + </text> + <combo_box name="username_combo" tool_tip="NazwÄ™ użytkownika wybierasz przy rejestracji, np. bobsmith12 lub Steller Sunshine"/> + <text name="password_text"> + HasÅ‚o: + </text> + <check_box label="ZapamiÄ™taj hasÅ‚o" name="remember_check"/> + <button label="PoÅ‚Ä…cz" name="connect_btn"/> + <text name="mode_selection_text"> + Tryb życia: + </text> + <combo_box name="mode_combo" tool_tip="Wybierz tryb życia. Wybierz tryb turystyczny dla Å‚atwego zwiedzania i czatowania. Wybierz tryb zaawansowany aby mieć dostÄ™p do wiÄ™kszej iloÅ›ci opcji."> + <combo_box.item label="Turystyczny" name="Basic"/> + <combo_box.item label="Zaawansowany" name="Advanced"/> + </combo_box> + <text name="start_location_text"> + Rozpocznij w: + </text> + <combo_box name="start_location_combo"> + <combo_box.item label="Ostatnie Miejsce" name="MyLastLocation"/> + <combo_box.item label="Moje Miejsce Startu" name="MyHome"/> + <combo_box.item label="<Wpisz Region>" name="Typeregionname"/> + </combo_box> + </layout_panel> + <layout_panel name="links"> + <text name="create_new_account_text"> + Utwórz nowe konto + </text> + <text name="forgot_password_text"> + ZapomniaÅ‚eÅ› swojej nazwy użytkownika lub hasÅ‚a? + </text> + <text name="login_help"> + Potrzebujesz pomocy z logowaniem siÄ™? + </text> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/pl/panel_navigation_bar.xml new file mode 100644 index 0000000000000000000000000000000000000000..b01e686c4193476fddda1f038ecd0c9e369d1112 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_navigation_bar.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="navigation_bar"> + <panel name="navigation_panel"> + <pull_button name="back_btn" tool_tip="Wróć do poprzedniej lokalizacji"/> + <pull_button name="forward_btn" tool_tip="Idź do nastÄ™pnej lokalizacji"/> + <button name="home_btn" tool_tip="Teleportuj do miejsca startu"/> + <location_input label="Lokalizacja" name="location_combo"/> + <search_combo_box label="Szukaj" name="search_combo_box" tool_tip="Szukaj"> + <combo_editor label="Szukaj [SECOND_LIFE]" name="search_combo_editor"/> + </search_combo_box> + </panel> + <favorites_bar name="favorite" tool_tip="PrzeciÄ…gnij swoje landmarki tutaj by szybko dostać siÄ™ do swoich ulubionych miejsc w Second Life!"> + <label name="favorites_bar_label" tool_tip="PrzeciÄ…gnij swoje landmarki tutaj by szybko dostać siÄ™ do swoich ulubionych miejsc w Second Life!"> + Pasek Ulubionych + </label> + <chevron_button name=">>" tool_tip="Pokaż wiÄ™cej Moich Ulubionych"/> + </favorites_bar> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_people.xml b/indra/newview/skins/minimal/xui/pl/panel_people.xml new file mode 100644 index 0000000000000000000000000000000000000000..dbfee739f4a13e59352379695977f539d22dff99 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_people.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Side tray panel --> +<panel label="Ludzie" name="people_panel"> + <string name="no_recent_people" value="Brak ostatnich rozmówców. Chcesz spotkać ludzi? Skorzystaj z przycisku "Atrakcje turystyczne" poniżej."/> + <string name="no_filtered_recent_people" value="Brak ostatnich rozmówców posiadajÄ…cych wskazane imiÄ™."/> + <string name="no_one_near" value="Nie ma nikogo w pobliżu. Chcesz spotkać ludzi? Skorzystaj z przycisku "Atrakcje turystyczne" poniżej."/> + <string name="no_one_filtered_near" value="Nie ma nikogo o wskazanym imieniu w pobliżu."/> + <string name="no_friends_online" value="Brak dostÄ™pnych znajomych"/> + <string name="no_friends" value="Brak znajomych"/> + <string name="no_friends_msg"> + Kliknij prawym przyciskiem na Rezydenta aby dodać go do listy znajomych. +Chcesz spotkać ludzi? Skorzystaj z przycisku "Atrakcje turystyczne" poniżej. + </string> + <string name="no_filtered_friends_msg"> + Nie znaleziono tego czego szukasz? Skorzystaj z przycisku "Atrakcje turystyczne" poniżej. + </string> + <string name="people_filter_label" value="Filtruj ludzi"/> + <string name="groups_filter_label" value="Filtruj grupy"/> + <string name="no_filtered_groups_msg" value="Nie znaleziono tego czego szukasz? Spróbuj [secondlife:///app/search/groups/[SEARCH_TERM] Szukaj]."/> + <string name="no_groups_msg" value="Chcesz doÅ‚Ä…czyć do grup? Spróbuj [secondlife:///app/search/groups Szukaj]."/> + <string name="MiniMapToolTipMsg" value="[REGION](Podwójne klikniÄ™cie otwiera mapÄ™, wciÅ›nij Shift i przeciÄ…gnij myszkÄ… aby przesunąć)"/> + <string name="AltMiniMapToolTipMsg" value="[REGION](Podwójne klikniÄ™cie aktywuje teleportacjÄ™, wciÅ›nij Shift i przeciÄ…gnij myszkÄ… aby przesunąć)"/> + <filter_editor label="Filtr" name="filter_input"/> + <tab_container name="tabs"> + <panel label="W POBLIÅ»U" name="nearby_panel"> + <panel label="bottom_panel" name="bottom_panel"> + <menu_button name="nearby_view_sort_btn" tool_tip="Opcje"/> + <button name="add_friend_btn" tool_tip="Dodaj wybranego Rezydenta do znajomych"/> + </panel> + </panel> + <panel label="ZNAJOMI" name="friends_panel"> + <accordion name="friends_accordion"> + <accordion_tab name="tab_online" title="DostÄ™pni"/> + <accordion_tab name="tab_all" title="Wszyscy"/> + </accordion> + <panel label="bottom_panel" name="bottom_panel"> + <layout_stack name="bottom_panel"> + <layout_panel name="options_gear_btn_panel"> + <menu_button name="friends_viewsort_btn" tool_tip="Pokaż opcje dodatkowe"/> + </layout_panel> + <layout_panel name="add_btn_panel"> + <button name="add_btn" tool_tip="Dodaj wybranego Rezydenta do znajomych"/> + </layout_panel> + <layout_panel name="trash_btn_panel"> + <dnd_button name="del_btn" tool_tip="UsuÅ„ zaznaczonÄ… osobÄ™ ze swojej listy znajomych"/> + </layout_panel> + </layout_stack> + </panel> + </panel> + <panel label="GRUPY" name="groups_panel"> + <panel label="bottom_panel" name="bottom_panel"> + <menu_button name="groups_viewsort_btn" tool_tip="Opcje"/> + <button name="plus_btn" tool_tip="DoÅ‚Ä…cz do grupy/Stwórz nowÄ… grupÄ™"/> + <button name="activate_btn" tool_tip="Aktywuj wybranÄ… grupÄ™"/> + </panel> + </panel> + <panel label="OSTATNIE" name="recent_panel"> + <panel label="bottom_panel" name="bottom_panel"> + <menu_button name="recent_viewsort_btn" tool_tip="Opcje"/> + <button name="add_friend_btn" tool_tip="Dodaj wybranego Rezydenta do znajomych"/> + </panel> + </panel> + </tab_container> + <panel name="button_bar"> + <layout_stack name="bottom_bar_ls"> + <layout_panel name="view_profile_btn_lp"> + <button label="Profil" name="view_profile_btn" tool_tip="Pokaż zdjÄ™cie, grupy i inne informacje o Rezydencie"/> + </layout_panel> + <layout_panel name="chat_btn_lp"> + <button label="IM" name="im_btn" tool_tip="Otwórz wiadomoÅ›ci IM"/> + </layout_panel> + <layout_panel name="chat_btn_lp"> + <button label="DzwoÅ„" name="call_btn" tool_tip="ZadzwoÅ„ do tego Rezydenta"/> + </layout_panel> + <layout_panel name="chat_btn_lp"> + <button label="UdostÄ™pnij" name="share_btn" tool_tip="UdostÄ™pnij obiekt z Szafy"/> + </layout_panel> + <layout_panel name="chat_btn_lp"> + <button label="Teleportuj" name="teleport_btn" tool_tip="Zaproponuj teleport"/> + </layout_panel> + </layout_stack> + <layout_stack name="bottom_bar_ls1"> + <layout_panel name="group_info_btn_lp"> + <button label="Profil grupy" name="group_info_btn" tool_tip="Pokaż informacje o grupie"/> + </layout_panel> + <layout_panel name="chat_btn_lp"> + <button label="Czat grupy" name="chat_btn" tool_tip="Otwórz sesjÄ™ czatu"/> + </layout_panel> + <layout_panel name="group_call_btn_lp"> + <button label="Rozmowa gÅ‚osowa w grupie" name="group_call_btn" tool_tip="Rozmowa gÅ‚osowa w tej grupie"/> + </layout_panel> + </layout_stack> + </panel> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/pl/panel_side_tray_tab_caption.xml new file mode 100644 index 0000000000000000000000000000000000000000..95cd7c53dc357fb92c74f2134f622536642357a6 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_side_tray_tab_caption.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="sidetray_tab_panel"> + <text name="sidetray_tab_title" value="Schowek"/> + <button name="undock" tool_tip="OdÅ‚Ä…cz"/> + <button name="dock" tool_tip="PrzyÅ‚Ä…cz"/> + <button name="show_help" tool_tip="Pomoc"/> +</panel> diff --git a/indra/newview/skins/minimal/xui/pl/panel_status_bar.xml b/indra/newview/skins/minimal/xui/pl/panel_status_bar.xml new file mode 100644 index 0000000000000000000000000000000000000000..6aa0d27bb80881b6f0b102f7b8c8847251da9846 --- /dev/null +++ b/indra/newview/skins/minimal/xui/pl/panel_status_bar.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="status"> + <panel.string name="StatBarDaysOfWeek"> + Niedziela:PoniedziaÅ‚ek:Wtorek:Åšroda:Czwartek:PiÄ…tek:Sobota + </panel.string> + <panel.string name="StatBarMonthsOfYear"> + StyczeÅ„:Luty:Marzec:KwiecieÅ„:Maj:Czerwiec:Lipiec:StyczeÅ„:WrzesieÅ„:Październik:Listopad:GrudzieÅ„ + </panel.string> + <panel.string name="packet_loss_tooltip"> + Utracone pakiety + </panel.string> + <panel.string name="bandwidth_tooltip"> + Przepustowość + </panel.string> + <panel.string name="time"> + [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] + </panel.string> + <panel.string name="timeTooltip"> + [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] + </panel.string> + <panel.string name="buycurrencylabel"> + L$ [AMT] + </panel.string> + <panel name="balance_bg"> + <text name="balance" tool_tip="Kliknij aby odÅ›wieżyć bilans L$" value="L$20"/> + <button label="Kup L$" name="buyL" tool_tip="Kliknij aby kupić wiÄ™cej L$"/> + </panel> + <text name="TimeText" tool_tip="Obecny czas (Pacyficzny)"> + 24:00 AM PST + </text> + <button name="media_toggle_btn" tool_tip="Start/Stop wszystkie media (Muzyka, Video, WWW)"/> + <button name="volume_btn" tool_tip="Regulacja gÅ‚oÅ›noÅ›ci"/> +</panel> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index cb7c04cd1512a7e3383bfea6d9aa32d0ad9bf4ef..a04b4a9ca0c4121a6672b6a65c2a4b1da8902b3c 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -977,8 +977,9 @@ def construct(self): self.path("libopenal.so", "libopenal.so.1") self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname self.path("libfontconfig.so.1.4.4") - self.path("libtcmalloc_minimal.so", "libtcmalloc_minimal.so") #formerly called google perf tools - self.path("libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.0") #formerly called google perf tools + self.path("libtcmalloc.so", "libtcmalloc.so") #formerly called google perf tools + self.path("libtcmalloc.so.0", "libtcmalloc.so.0") #formerly called google perf tools + self.path("libtcmalloc.so.0.1.0", "libtcmalloc.so.0.1.0") #formerly called google perf tools try: self.path("libfmod-3.75.so") pass diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 7164934b263f0e3349423a2ecc982772e514ed90..884b00f0ccba6f96325047e51614638ffa24eb9d 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -2154,6 +2154,10 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e } break; + case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: + std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE, uri is: " << self->getClickURL() << std::endl; + break; + case MEDIA_EVENT_CLICK_LINK_HREF: { std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl;