summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/CMakeLists.txt2
-rw-r--r--indra/cmake/00-Common.cmake6
-rw-r--r--indra/cmake/APR.cmake27
-rw-r--r--indra/cmake/Boost.cmake94
-rw-r--r--indra/cmake/CEFPlugin.cmake229
-rw-r--r--indra/cmake/CURL.cmake16
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake60
-rw-r--r--indra/cmake/Discord.cmake20
-rw-r--r--indra/cmake/FMODSTUDIO.cmake32
-rw-r--r--indra/cmake/GLM.cmake2
-rw-r--r--indra/cmake/LLPrimitive.cmake249
-rw-r--r--indra/cmake/LibVLCPlugin.cmake9
-rw-r--r--indra/cmake/Meshoptimizer.cmake14
-rw-r--r--indra/cmake/OPENAL.cmake36
-rw-r--r--indra/cmake/OpenGL.cmake5
-rw-r--r--indra/cmake/OpenJPEG.cmake70
-rw-r--r--indra/cmake/Python.cmake67
-rw-r--r--indra/cmake/UI.cmake32
-rw-r--r--indra/cmake/UnixInstall.cmake28
-rw-r--r--indra/cmake/ViewerMiscLibs.cmake12
-rw-r--r--indra/cmake/WebRTC.cmake30
-rw-r--r--indra/llappearance/lltexlayer.cpp18
-rw-r--r--indra/llappearance/lltexlayerparams.h1
-rw-r--r--indra/llaudio/llaudioengine.cpp1
-rw-r--r--indra/llcharacter/CMakeLists.txt4
-rw-r--r--indra/llcharacter/llkeyframemotionparam.cpp436
-rw-r--r--indra/llcharacter/llkeyframemotionparam.h169
-rw-r--r--indra/llcharacter/llmotioncontroller.h1
-rw-r--r--indra/llcharacter/llstatemachine.cpp384
-rw-r--r--indra/llcharacter/llstatemachine.h147
-rw-r--r--indra/llcommon/CMakeLists.txt3
-rw-r--r--indra/llcommon/indra_constants.h22
-rw-r--r--indra/llcommon/llapp.cpp1
-rw-r--r--indra/llcommon/llapp.h3
-rw-r--r--indra/llcommon/lldate.cpp7
-rw-r--r--indra/llcommon/llerror.cpp6
-rw-r--r--indra/llcommon/llerrorcontrol.h1
-rw-r--r--indra/llcommon/llfasttimer.h3
-rw-r--r--indra/llcommon/llfile.cpp29
-rw-r--r--indra/llcommon/llheteromap.cpp2
-rw-r--r--indra/llcommon/llheteromap.h27
-rw-r--r--indra/llcommon/llinitparam.h129
-rw-r--r--indra/llcommon/llmemory.cpp119
-rw-r--r--indra/llcommon/llmemory.h17
-rwxr-xr-xindra/llcommon/llpointer.cpp43
-rw-r--r--indra/llcommon/llpointer.h291
-rw-r--r--indra/llcommon/llpounceable.h4
-rw-r--r--indra/llcommon/llprocess.cpp13
-rw-r--r--indra/llcommon/llregistry.h26
-rw-r--r--indra/llcommon/llsd.cpp162
-rw-r--r--indra/llcommon/llsd.h39
-rw-r--r--indra/llcommon/llsdjson.cpp4
-rw-r--r--indra/llcommon/llsdserialize.cpp52
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp32
-rw-r--r--indra/llcommon/llsingleton.h4
-rw-r--r--indra/llcommon/llstaticstringtable.h5
-rw-r--r--indra/llcommon/llstl.h38
-rw-r--r--indra/llcommon/llsys.cpp80
-rw-r--r--indra/llcommon/llsys.h9
-rw-r--r--indra/llcommon/lluuid.h19
-rw-r--r--indra/llcommon/llwatchdog.cpp79
-rw-r--r--indra/llcommon/llwatchdog.h27
-rw-r--r--indra/llcommon/workqueue.cpp22
-rw-r--r--indra/llfilesystem/lldir.cpp59
-rw-r--r--indra/llfilesystem/lldir.h3
-rw-r--r--indra/llfilesystem/lldiskcache.cpp14
-rw-r--r--indra/llfilesystem/llfilesystem.cpp26
-rw-r--r--indra/llimage/llimage.h5
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp2
-rw-r--r--indra/llinventory/llinventory.cpp18
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp47
-rw-r--r--indra/llmath/llvolume.cpp31
-rw-r--r--indra/llmath/llvolumemgr.cpp1
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.cpp1
-rw-r--r--indra/llmessage/llassetstorage.cpp3
-rw-r--r--indra/llmessage/llavatarnamecache.cpp18
-rw-r--r--indra/llmessage/llavatarnamecache.h10
-rw-r--r--indra/llmessage/llcachename.cpp15
-rw-r--r--indra/llmessage/llcachename.h3
-rw-r--r--indra/llmessage/llcorehttputil.cpp132
-rw-r--r--indra/llmessage/llcorehttputil.h9
-rw-r--r--indra/llmessage/lldatapacker.cpp67
-rw-r--r--indra/llmessage/lldatapacker.h8
-rw-r--r--indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp165
-rw-r--r--indra/llphysicsextensionsos/llconvexdecompositionvhacd.h20
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp15
-rw-r--r--indra/llplugin/llpluginclassmedia.h4
-rw-r--r--indra/llplugin/slplugin/CMakeLists.txt9
-rw-r--r--indra/llprimitive/llgltfmaterial.cpp145
-rw-r--r--indra/llprimitive/llgltfmaterial.h8
-rw-r--r--indra/llprimitive/llmaterialid.h30
-rw-r--r--indra/llprimitive/llprimitive.cpp2
-rw-r--r--indra/llprimitive/llprimitive.h9
-rw-r--r--indra/llprimitive/lltextureanim.cpp2
-rw-r--r--indra/llrender/CMakeLists.txt7
-rw-r--r--indra/llrender/llfontfreetype.cpp184
-rw-r--r--indra/llrender/llfontfreetype.h20
-rw-r--r--indra/llrender/llfontgl.cpp13
-rw-r--r--indra/llrender/llfontgl.h3
-rw-r--r--indra/llrender/llfontregistry.cpp66
-rw-r--r--indra/llrender/llfontregistry.h31
-rw-r--r--indra/llrender/llfontvertexbuffer.cpp77
-rw-r--r--indra/llrender/llfontvertexbuffer.h46
-rw-r--r--indra/llrender/llgl.cpp6
-rw-r--r--indra/llrender/llgl.h4
-rw-r--r--indra/llrender/llimagegl.cpp4
-rw-r--r--indra/llrender/llrender.cpp14
-rw-r--r--indra/llrender/llshadermgr.cpp19
-rw-r--r--indra/llrender/lltexturemanagerbridge.cpp2
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbutton.cpp25
-rw-r--r--indra/llui/llbutton.h9
-rw-r--r--indra/llui/llcallbackmap.h6
-rw-r--r--indra/llui/llcombobox.cpp33
-rw-r--r--indra/llui/llcombobox.h4
-rw-r--r--indra/llui/llconsole.cpp11
-rw-r--r--indra/llui/lldraghandle.cpp12
-rw-r--r--indra/llui/lldraghandle.h8
-rw-r--r--indra/llui/llfloater.cpp14
-rw-r--r--indra/llui/llfloater.h6
-rw-r--r--indra/llui/llfloaterreg.cpp19
-rw-r--r--indra/llui/llfloaterreg.h13
-rw-r--r--indra/llui/llfloaterreglistener.cpp9
-rw-r--r--indra/llui/llfloaterreglistener.h1
-rw-r--r--indra/llui/llfocusmgr.cpp5
-rw-r--r--indra/llui/llfocusmgr.h2
-rw-r--r--indra/llui/llfolderviewitem.cpp27
-rw-r--r--indra/llui/llfolderviewitem.h4
-rw-r--r--indra/llui/llfunctorregistry.h5
-rw-r--r--indra/llui/llkeywords.h2
-rw-r--r--indra/llui/lllayoutstack.cpp11
-rw-r--r--indra/llui/lllayoutstack.h6
-rw-r--r--indra/llui/lllineeditor.cpp8
-rw-r--r--indra/llui/lllineeditor.h6
-rw-r--r--indra/llui/llmenugl.cpp17
-rw-r--r--indra/llui/llnotifications.cpp7
-rw-r--r--indra/llui/llnotifications.h5
-rw-r--r--indra/llui/llpanel.cpp43
-rw-r--r--indra/llui/llpanel.h4
-rw-r--r--indra/llui/llradiogroup.cpp2
-rw-r--r--indra/llui/llrngwriter.cpp2
-rw-r--r--indra/llui/llscrollcontainer.cpp1
-rw-r--r--indra/llui/llscrolllistcolumn.cpp2
-rw-r--r--indra/llui/llscrolllistctrl.cpp1
-rw-r--r--indra/llui/lltabcontainer.cpp41
-rw-r--r--indra/llui/lltabcontainer.h2
-rw-r--r--indra/llui/lltextbase.cpp88
-rw-r--r--indra/llui/lltextbase.h15
-rw-r--r--indra/llui/lltexteditor.cpp2
-rw-r--r--indra/llui/lltooltip.cpp2
-rw-r--r--indra/llui/lltrans.h2
-rw-r--r--indra/llui/llui.cpp2
-rw-r--r--indra/llui/llui.h2
-rw-r--r--indra/llui/lluicolortable.cpp9
-rw-r--r--indra/llui/lluicolortable.h4
-rw-r--r--indra/llui/lluictrl.cpp2
-rw-r--r--indra/llui/lluictrlfactory.cpp4
-rw-r--r--indra/llui/lluictrlfactory.h23
-rw-r--r--indra/llui/llurlregistry.cpp77
-rw-r--r--indra/llui/llviewborder.cpp2
-rw-r--r--indra/llui/llxuiparser.cpp46
-rw-r--r--indra/llui/llxuiparser.h6
-rw-r--r--indra/llwebrtc/CMakeLists.txt25
-rw-r--r--indra/llwebrtc/llwebrtc.cpp693
-rw-r--r--indra/llwebrtc/llwebrtc.h14
-rw-r--r--indra/llwebrtc/llwebrtc_impl.h92
-rw-r--r--indra/llwindow/llkeyboardmacosx.cpp34
-rw-r--r--indra/llwindow/llopenglview-objc.mm18
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp2
-rw-r--r--indra/llwindow/llwindowcallbacks.h2
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h2
-rw-r--r--indra/llwindow/llwindowmacosx-objc.mm6
-rw-r--r--indra/llwindow/llwindowmacosx.cpp9
-rw-r--r--indra/llwindow/llwindowwin32.cpp436
-rw-r--r--indra/llwindow/llwindowwin32.h13
-rw-r--r--indra/llxml/llcontrol.cpp31
-rw-r--r--indra/llxml/llcontrol.h6
-rw-r--r--indra/media_plugins/cef/CMakeLists.txt91
-rw-r--r--indra/media_plugins/cef/linux/volume_catcher_linux.cpp2
-rwxr-xr-xindra/media_plugins/cef/linux/volume_catcher_pipewire.cpp4
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp16
-rw-r--r--indra/media_plugins/libvlc/CMakeLists.txt29
-rw-r--r--indra/media_plugins/libvlc/media_plugin_libvlc.cpp50
-rw-r--r--indra/newview/CMakeLists.txt76
-rw-r--r--indra/newview/FixBundle.cmake.in441
-rw-r--r--indra/newview/FixPackage.cmake.in440
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/PKGBUILD.in2
-rw-r--r--indra/newview/SignBundle.cmake.in430
-rw-r--r--indra/newview/SignBundleMmxSse2.cmake.in11
-rw-r--r--indra/newview/SignPackage.cmake.in430
-rw-r--r--indra/newview/SignPackageMmxSse2.cmake.in11
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/ViewerInstall.cmake147
-rw-r--r--indra/newview/app_settings/commands.xml11
-rw-r--r--indra/newview/app_settings/settings.xml469
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/CASF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl9
-rw-r--r--indra/newview/featuretable_mac.txt3
-rw-r--r--indra/newview/gltf/asset.cpp6
-rw-r--r--indra/newview/gltf/buffer_util.h44
-rw-r--r--indra/newview/gltf/llgltfloader.cpp112
-rw-r--r--indra/newview/installers/windows/installer_template.nsi3
-rw-r--r--indra/newview/licenses-linux.txt44
-rw-r--r--indra/newview/licenses-mac.txt45
-rwxr-xr-xindra/newview/linux_tools/megapahit.desktop1
-rw-r--r--indra/newview/llagent.cpp41
-rw-r--r--indra/newview/llagent.h1
-rw-r--r--indra/newview/llagentcamera.cpp94
-rw-r--r--indra/newview/llagentcamera.h9
-rw-r--r--indra/newview/llagentlistener.cpp42
-rw-r--r--indra/newview/llagentlistener.h1
-rw-r--r--indra/newview/llaisapi.cpp28
-rw-r--r--indra/newview/llaisapi.h14
-rw-r--r--indra/newview/llappcorehttp.cpp2
-rw-r--r--indra/newview/llappdelegate-objc.mm2
-rw-r--r--indra/newview/llappearancemgr.cpp189
-rw-r--r--indra/newview/llappearancemgr.h3
-rw-r--r--indra/newview/llappviewer.cpp295
-rw-r--r--indra/newview/llappviewer.h5
-rw-r--r--indra/newview/llappviewerlinux.cpp4
-rw-r--r--indra/newview/llappviewermacosx.cpp10
-rw-r--r--indra/newview/llappviewerwin32.cpp78
-rw-r--r--indra/newview/llappviewerwin32.h1
-rw-r--r--indra/newview/llattachmentsmgr.cpp146
-rw-r--r--indra/newview/llattachmentsmgr.h11
-rw-r--r--indra/newview/llavataractions.cpp87
-rw-r--r--indra/newview/llavataractions.h6
-rw-r--r--indra/newview/llavatarlistitem.cpp2
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp26
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h25
-rw-r--r--indra/newview/llblocklist.cpp35
-rw-r--r--indra/newview/llblocklist.h7
-rw-r--r--indra/newview/llcallingcard.cpp2
-rw-r--r--indra/newview/llcapabilityprovider.h4
-rw-r--r--indra/newview/llchannelmanager.cpp1
-rw-r--r--indra/newview/llchannelmanager.h3
-rw-r--r--indra/newview/llcofwearables.cpp2
-rw-r--r--indra/newview/llcolorswatch.cpp18
-rw-r--r--indra/newview/llconversationloglist.cpp65
-rw-r--r--indra/newview/llconversationloglist.h10
-rw-r--r--indra/newview/llconversationview.cpp53
-rw-r--r--indra/newview/llconversationview.h3
-rw-r--r--indra/newview/lldebugview.cpp6
-rw-r--r--indra/newview/lldebugview.h1
-rw-r--r--indra/newview/lldrawable.cpp8
-rw-r--r--indra/newview/lldrawpoolalpha.cpp2
-rw-r--r--indra/newview/lldrawpoolwater.cpp8
-rw-r--r--indra/newview/lleventpoll.cpp25
-rw-r--r--indra/newview/llexpandabletextbox.cpp2
-rw-r--r--indra/newview/llface.cpp101
-rw-r--r--indra/newview/llface.h2
-rw-r--r--indra/newview/llfavoritesbar.cpp5
-rw-r--r--indra/newview/llfilepicker_mac.mm7
-rw-r--r--indra/newview/llfloater360capture.cpp2
-rw-r--r--indra/newview/llfloaterbigpreview.cpp110
-rw-r--r--indra/newview/llfloaterbigpreview.h54
-rw-r--r--indra/newview/llfloaterchangeitemthumbnail.cpp151
-rw-r--r--indra/newview/llfloaterchangeitemthumbnail.h4
-rw-r--r--indra/newview/llfloatercolorpicker.cpp16
-rw-r--r--indra/newview/llfloatercolorpicker.h3
-rw-r--r--indra/newview/llfloaterconversationlog.cpp8
-rw-r--r--indra/newview/llfloatereditenvironmentbase.cpp2
-rw-r--r--indra/newview/llfloaterexperiences.cpp5
-rw-r--r--indra/newview/llfloaterimcontainer.cpp129
-rw-r--r--indra/newview/llfloaterimcontainer.h3
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp22
-rw-r--r--indra/newview/llfloaterimnearbychat.h1
-rw-r--r--indra/newview/llfloaterimsession.cpp4
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp20
-rw-r--r--indra/newview/llfloaterimsessiontab.h2
-rw-r--r--indra/newview/llfloaterinspect.cpp1
-rw-r--r--indra/newview/llfloaterlinkreplace.cpp31
-rw-r--r--indra/newview/llfloatermarketplace.cpp52
-rw-r--r--indra/newview/llfloatermarketplace.h3
-rw-r--r--indra/newview/llfloatermarketplacelistings.cpp24
-rw-r--r--indra/newview/llfloaterobjectweights.cpp2
-rw-r--r--indra/newview/llfloaterpay.cpp2
-rw-r--r--indra/newview/llfloaterpostprocess.cpp229
-rw-r--r--indra/newview/llfloaterpostprocess.h72
-rw-r--r--indra/newview/llfloaterpreference.cpp21
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterregioninfo.cpp15
-rw-r--r--indra/newview/llfloatersearch.cpp21
-rw-r--r--indra/newview/llfloatersimplesnapshot.cpp197
-rw-r--r--indra/newview/llfloatersnapshot.cpp2
-rw-r--r--indra/newview/llfloatersounddevices.cpp86
-rw-r--r--indra/newview/llfloatervoiceeffect.cpp289
-rw-r--r--indra/newview/llfloatervoiceeffect.h72
-rw-r--r--indra/newview/llgltfmateriallist.cpp2
-rw-r--r--indra/newview/llgroupcolormap.cpp150
-rw-r--r--indra/newview/llgroupcolormap.h64
-rw-r--r--indra/newview/llgrouplist.cpp2
-rw-r--r--indra/newview/llhudnametag.cpp2
-rw-r--r--indra/newview/llimprocessing.cpp6
-rw-r--r--indra/newview/llimview.cpp12
-rw-r--r--indra/newview/llinventorybridge.cpp27
-rw-r--r--indra/newview/llinventoryfunctions.cpp22
-rw-r--r--indra/newview/llinventorygallery.cpp10
-rw-r--r--indra/newview/llinventorygallerymenu.cpp8
-rw-r--r--indra/newview/llinventorylistitem.cpp2
-rw-r--r--indra/newview/llinventorymodel.cpp123
-rw-r--r--indra/newview/llinventorymodel.h16
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp37
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.h6
-rw-r--r--indra/newview/llinventorypanel.cpp19
-rw-r--r--indra/newview/llinventorypanel.h2
-rw-r--r--indra/newview/lllocalbitmaps.cpp2
-rw-r--r--indra/newview/lllogininstance.cpp3
-rw-r--r--indra/newview/llmachineid.cpp2
-rw-r--r--indra/newview/llmarketplacefunctions.cpp4
-rw-r--r--indra/newview/llmaterialmgr.h76
-rw-r--r--indra/newview/llmediactrl.cpp2
-rw-r--r--indra/newview/llmeshrepository.cpp108
-rw-r--r--indra/newview/llmeshrepository.h14
-rw-r--r--indra/newview/llmodelpreview.cpp2
-rw-r--r--indra/newview/llmutelist.cpp206
-rw-r--r--indra/newview/llmutelist.h40
-rw-r--r--indra/newview/llnavigationbar.cpp9
-rw-r--r--indra/newview/llnearbyvoicemoderation.cpp220
-rw-r--r--indra/newview/llnearbyvoicemoderation.h50
-rw-r--r--indra/newview/llnetmap.cpp69
-rw-r--r--indra/newview/llnotificationlistitem.cpp4
-rw-r--r--indra/newview/llnotificationofferhandler.cpp7
-rw-r--r--indra/newview/lloutfitgallery.cpp19
-rw-r--r--indra/newview/lloutfitgallery.h2
-rw-r--r--indra/newview/lloutfitslist.cpp17
-rw-r--r--indra/newview/lloutfitslist.h13
-rw-r--r--indra/newview/llpanelblockedlist.cpp4
-rw-r--r--indra/newview/llpanelface.cpp23
-rw-r--r--indra/newview/llpanelgenerictip.cpp8
-rw-r--r--indra/newview/llpanelgroup.cpp34
-rw-r--r--indra/newview/llpanelgroup.h9
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp76
-rw-r--r--indra/newview/llpanelgroupgeneral.h8
-rw-r--r--indra/newview/llpanellogin.cpp196
-rw-r--r--indra/newview/llpanellogin.h18
-rw-r--r--indra/newview/llpanelmaininventory.cpp54
-rw-r--r--indra/newview/llpanelmaininventory.h1
-rw-r--r--indra/newview/llpanelobject.cpp37
-rw-r--r--indra/newview/llpanelobjectinventory.cpp2
-rw-r--r--indra/newview/llpanelobjectinventory.h2
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp16
-rw-r--r--indra/newview/llpanelpeoplemenus.h1
-rw-r--r--indra/newview/llpanelpermissions.cpp4
-rw-r--r--indra/newview/llpanelplaces.cpp6
-rw-r--r--indra/newview/llpanelplacestab.cpp6
-rw-r--r--indra/newview/llpanelprofile.cpp158
-rw-r--r--indra/newview/llpanelteleporthistory.cpp5
-rw-r--r--indra/newview/llpanelvoicedevicesettings.cpp7
-rw-r--r--indra/newview/llpanelvoiceeffect.cpp165
-rw-r--r--indra/newview/llpanelvoiceeffect.h67
-rw-r--r--indra/newview/llpanelvolume.cpp10
-rw-r--r--indra/newview/llperfstats.h2
-rw-r--r--indra/newview/llpreviewnotecard.cpp3
-rw-r--r--indra/newview/llquickprefs.cpp228
-rw-r--r--indra/newview/llquickprefs.h86
-rw-r--r--indra/newview/llreflectionmap.cpp5
-rw-r--r--indra/newview/llreflectionmapmanager.cpp34
-rw-r--r--indra/newview/llreflectionmapmanager.h7
-rw-r--r--indra/newview/llremoteparcelrequest.cpp1
-rw-r--r--indra/newview/llscriptruntimeperms.h13
-rw-r--r--indra/newview/llselectmgr.cpp10
-rw-r--r--indra/newview/llsidepanelinventory.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp8
-rw-r--r--indra/newview/llspatialpartition.h2
-rw-r--r--indra/newview/llspeakers.cpp2
-rw-r--r--indra/newview/llstartup.cpp27
-rw-r--r--indra/newview/llstatslistener.cpp200
-rw-r--r--indra/newview/llstatslistener.h (renamed from indra/newview/llfloatersounddevices.h)32
-rw-r--r--indra/newview/lltexturecache.cpp70
-rw-r--r--indra/newview/lltexturecache.h3
-rw-r--r--indra/newview/lltexturectrl.cpp114
-rw-r--r--indra/newview/lltexturectrl.h4
-rw-r--r--indra/newview/lltextureview.cpp2
-rw-r--r--indra/newview/lltoastnotifypanel.cpp59
-rw-r--r--indra/newview/lltoastnotifypanel.h2
-rw-r--r--indra/newview/lltoastscriptquestion.cpp73
-rw-r--r--indra/newview/lltoolcomp.cpp55
-rw-r--r--indra/newview/lltoolcomp.h2
-rw-r--r--indra/newview/lltooldraganddrop.cpp2
-rw-r--r--indra/newview/lltoolmgr.cpp62
-rw-r--r--indra/newview/lltoolpie.cpp6
-rw-r--r--indra/newview/lltoolpipette.cpp21
-rw-r--r--indra/newview/lltoolpipette.h7
-rw-r--r--indra/newview/lltoolselect.cpp9
-rw-r--r--indra/newview/lluilistener.cpp24
-rw-r--r--indra/newview/lluilistener.h1
-rw-r--r--indra/newview/llvelopack.cpp230
-rw-r--r--indra/newview/llvelopack.h5
-rw-r--r--indra/newview/llviewerassetupload.cpp95
-rw-r--r--indra/newview/llvieweraudio.cpp59
-rw-r--r--indra/newview/llviewerchat.cpp2
-rw-r--r--indra/newview/llviewercontrol.cpp1
-rw-r--r--indra/newview/llviewerdisplay.cpp33
-rw-r--r--indra/newview/llviewerfloaterreg.cpp12
-rw-r--r--indra/newview/llviewergenericmessage.cpp3
-rw-r--r--indra/newview/llviewerjointattachment.cpp1
-rw-r--r--indra/newview/llviewermedia.cpp56
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermenu.cpp252
-rw-r--r--indra/newview/llviewermessage.cpp53
-rw-r--r--indra/newview/llviewernetwork.cpp4
-rw-r--r--indra/newview/llviewernetwork.h1
-rw-r--r--indra/newview/llviewerobject.cpp238
-rw-r--r--indra/newview/llviewerobject.h70
-rw-r--r--indra/newview/llviewerobjectlist.cpp5
-rw-r--r--indra/newview/llviewerobjectlist.h4
-rw-r--r--indra/newview/llvieweroctree.cpp2
-rw-r--r--indra/newview/llvieweroctree.h1
-rw-r--r--indra/newview/llviewerparcelmgr.cpp13
-rw-r--r--indra/newview/llviewerparcelmgr.h6
-rw-r--r--indra/newview/llviewerprecompiledheaders.h2
-rwxr-xr-xindra/newview/llviewerregion.cpp45
-rw-r--r--indra/newview/llviewerregion.h10
-rw-r--r--indra/newview/llviewerstats.cpp19
-rw-r--r--indra/newview/llviewerstats.h40
-rw-r--r--indra/newview/llviewertexteditor.cpp12
-rw-r--r--indra/newview/llviewertexture.cpp78
-rw-r--r--indra/newview/llviewertexture.h1
-rw-r--r--indra/newview/llviewertexturelist.cpp47
-rw-r--r--indra/newview/llviewerwearable.cpp1
-rw-r--r--indra/newview/llviewerwindow.cpp106
-rw-r--r--indra/newview/llviewerwindow.h11
-rw-r--r--indra/newview/llvlmanager.cpp6
-rw-r--r--indra/newview/llvoavatar.cpp674
-rw-r--r--indra/newview/llvoavatar.h107
-rw-r--r--indra/newview/llvocache.cpp6
-rw-r--r--indra/newview/llvoicechannel.cpp8
-rw-r--r--indra/newview/llvoiceclient.cpp255
-rw-r--r--indra/newview/llvoiceclient.h11
-rw-r--r--indra/newview/llvoicevivox.cpp7935
-rw-r--r--indra/newview/llvoicevivox.h1095
-rw-r--r--indra/newview/llvoicewebrtc.cpp335
-rw-r--r--indra/newview/llvoicewebrtc.h12
-rw-r--r--indra/newview/llvovolume.cpp187
-rw-r--r--indra/newview/llvovolume.h5
-rw-r--r--indra/newview/llwearableitemslist.cpp10
-rw-r--r--indra/newview/llweb.cpp13
-rw-r--r--indra/newview/llwindowlistener.cpp105
-rw-r--r--indra/newview/llwindowlistener.h1
-rw-r--r--indra/newview/llworld.cpp1
-rw-r--r--indra/newview/llworldmap.cpp101
-rw-r--r--indra/newview/llworldmap.h12
-rw-r--r--indra/newview/llworldmapmessage.cpp3
-rwxr-xr-xindra/newview/llworldmapview.cpp47
-rw-r--r--indra/newview/net.megapahit.Viewer.metainfo.xml.in21
-rw-r--r--indra/newview/pipeline.cpp14
-rw-r--r--indra/newview/rlvdefines.h1
-rw-r--r--indra/newview/rlvhandler.cpp16
-rw-r--r--indra/newview/rlvhelper.cpp1
-rw-r--r--indra/newview/skins/classic/colors.xml1022
-rw-r--r--indra/newview/skins/classic/textures/3p_icons/fmod_logo.pngbin0 -> 14486 bytes
-rw-r--r--indra/newview/skins/classic/textures/3p_icons/havok_logo.pngbin0 -> 41488 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Avatar_Off.pngbin0 -> 527 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_FreeCam_Off.pngbin0 -> 365 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Orbit_Off.pngbin0 -> 532 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Pan_Off.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_Off.pngbin0 -> 49285 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_On.pngbin0 -> 50855 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Eye_Off.pngbin0 -> 914 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_Off.pngbin0 -> 50394 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_On.pngbin0 -> 50127 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_Off.pngbin0 -> 49268 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_On.pngbin0 -> 50209 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Center.pngbin0 -> 3438 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_In.pngbin0 -> 4238 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Out.pngbin0 -> 8388 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Center.pngbin0 -> 4365 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_In.pngbin0 -> 4365 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Out.pngbin0 -> 5711 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/ChatBarHandle.pngbin0 -> 260 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/DownArrow.pngbin0 -> 139 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Mouselook_View_Off.pngbin0 -> 51189 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Mouselook_View_On.pngbin0 -> 53113 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Move_Fly_Off.pngbin0 -> 609 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Move_Run_Off.pngbin0 -> 496 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Move_Walk_Off.pngbin0 -> 515 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Backward_Off.pngbin0 -> 354 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Backward_On.pngbin0 -> 3473 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Down_Off.pngbin0 -> 51706 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Down_On.pngbin0 -> 4134 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Forward_Off.pngbin0 -> 322 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Forward_On.pngbin0 -> 3392 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Left_Off.pngbin0 -> 51016 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Left_On.pngbin0 -> 3191 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Right_Off.pngbin0 -> 49845 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Right_On.pngbin0 -> 3212 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_Off.pngbin0 -> 431 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_On.pngbin0 -> 4514 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_Off.pngbin0 -> 432 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_On.pngbin0 -> 4447 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Up_Off.pngbin0 -> 53763 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Movement_Up_On.pngbin0 -> 4134 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Notices_Unread.pngbin0 -> 436 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Object_View_Off.pngbin0 -> 55000 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Object_View_On.pngbin0 -> 51183 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/PanOrbit_Off.pngbin0 -> 51539 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Snapshot_Off.pngbin0 -> 549 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/Unread_Chiclet.pngbin0 -> 334 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl1.pngbin0 -> 6625 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl2.pngbin0 -> 6879 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl3.pngbin0 -> 607 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/VoicePTT_Off.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/VoicePTT_On.pngbin0 -> 5521 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/WellButton_Lit.pngbin0 -> 5762 bytes
-rw-r--r--indra/newview/skins/classic/textures/bottomtray/WellButton_Lit_Selected.pngbin0 -> 5762 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cone.pngbin0 -> 481 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cone_Selected.pngbin0 -> 5269 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cube.pngbin0 -> 370 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cube_Selected.pngbin0 -> 4505 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cylinder.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Cylinder_Selected.pngbin0 -> 4451 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Grass.pngbin0 -> 456 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Grass_Selected.pngbin0 -> 7922 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Cone.pngbin0 -> 441 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Cone_Selected.pngbin0 -> 5001 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder.pngbin0 -> 378 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder_Selected.pngbin0 -> 4497 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Sphere.pngbin0 -> 545 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Hemi_Sphere_Selected.pngbin0 -> 5224 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Prism.pngbin0 -> 395 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Prism_Selected.pngbin0 -> 4747 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Pyramid.pngbin0 -> 452 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Pyramid_Selected.pngbin0 -> 5137 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Ring.pngbin0 -> 615 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Ring_Selected.pngbin0 -> 6066 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Sphere.pngbin0 -> 737 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Sphere_Selected.pngbin0 -> 7005 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tetrahedron.pngbin0 -> 411 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tetrahedron_Selected.pngbin0 -> 5201 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Torus.pngbin0 -> 803 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Torus_Selected.pngbin0 -> 6125 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tree.pngbin0 -> 737 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tree_Selected.pngbin0 -> 6377 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tube.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Object_Tube_Selected.pngbin0 -> 5131 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Tool_Create.pngbin0 -> 705 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Tool_Dozer.pngbin0 -> 492 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Tool_Face.pngbin0 -> 304 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Tool_Grab.pngbin0 -> 417 bytes
-rw-r--r--indra/newview/skins/classic/textures/build/Tool_Zoom.pngbin0 -> 533 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Off.pngbin0 -> 175 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Press.pngbin0 -> 175 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Off.pngbin0 -> 169 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Press.pngbin0 -> 169 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_Off.pngbin0 -> 239 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_Over.pngbin0 -> 206 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_Press.pngbin0 -> 200 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Accordion_Selected.pngbin0 -> 2235 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Container.pngbin0 -> 673 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Left_Off.pngbin0 -> 6072 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Left_Selected.pngbin0 -> 3385 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Middle_Off.pngbin0 -> 5999 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Middle_Selected.pngbin0 -> 3049 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Right_Flashing.pngbin0 -> 252 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Right_Off.pngbin0 -> 5638 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/TabTop_Right_Selected.pngbin0 -> 3403 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Left_Flash.pngbin0 -> 356 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Left_Off.pngbin0 -> 4894 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Left_Over.pngbin0 -> 4903 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Left_Selected.pngbin0 -> 3734 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Middle_Flash.pngbin0 -> 316 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Middle_Off.pngbin0 -> 4812 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Middle_Over.pngbin0 -> 4818 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Middle_Selected.pngbin0 -> 3527 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Right_Flash.pngbin0 -> 428 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Right_Off.pngbin0 -> 4917 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Right_Over.pngbin0 -> 4921 bytes
-rw-r--r--indra/newview/skins/classic/textures/containers/Toolbar_Right_Selected.pngbin0 -> 4120 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/AddItem_Disabled.pngbin0 -> 403 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/AddItem_Off.pngbin0 -> 397 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/AddItem_Press.pngbin0 -> 392 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/AudioMute_Off.pngbin0 -> 800 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/AudioMute_Over.pngbin0 -> 787 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Audio_Off.pngbin0 -> 596 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Audio_Press.pngbin0 -> 585 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/BackArrow_Off.pngbin0 -> 434 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardMenu_Disabled.pngbin0 -> 406 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardMenu_Off.pngbin0 -> 392 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardMenu_Press.pngbin0 -> 403 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Disabled.pngbin0 -> 395 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Off.pngbin0 -> 386 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Press.pngbin0 -> 395 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_log_inbox.pngbin0 -> 544 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_add_person.pngbin0 -> 522 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_ne.pngbin0 -> 428 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_sw.pngbin0 -> 428 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_call_log.pngbin0 -> 592 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_close.pngbin0 -> 479 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_collapse.pngbin0 -> 538 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_expand.pngbin0 -> 533 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_hang_up.pngbin0 -> 609 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_open_call.pngbin0 -> 546 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_plus.pngbin0 -> 368 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Conv_toolbar_sort.pngbin0 -> 424 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Copy.pngbin0 -> 588 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/CopyBright.pngbin0 -> 615 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Default_Outfit_Photo.pngbin0 -> 13832 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/DownArrow_Off.pngbin0 -> 431 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Edit_Wrench.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ExternalBrowser_Off.pngbin0 -> 476 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Facebook.pngbin0 -> 576 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Female.pngbin0 -> 489 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ForSale_Badge.pngbin0 -> 5896 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ForwardArrow_Off.pngbin0 -> 424 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/ForwardArrow_Press.pngbin0 -> 424 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Generic_Group.pngbin0 -> 2683 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Generic_Group_Large.pngbin0 -> 2772 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Generic_Object_Small.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Generic_Person.pngbin0 -> 544 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Generic_Person_Large.pngbin0 -> 2510 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Group_Notices.pngbin0 -> 3502 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Hierarchy_View_Disabled.pngbin0 -> 401 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Hierarchy_View_On.pngbin0 -> 356 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Attachment_Large.pngbin0 -> 1593 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Attachment_Small.pngbin0 -> 1383 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Color_Palette.pngbin0 -> 3419 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Font_Size.pngbin0 -> 2994 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_For_Sale.pngbin0 -> 729 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Notification_Condense.pngbin0 -> 465 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Notification_Expand.pngbin0 -> 427 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Icon_Pointer.pngbin0 -> 294 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Info.pngbin0 -> 535 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Info_Over.pngbin0 -> 2654 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Info_Small.pngbin0 -> 478 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Alpha.pngbin0 -> 494 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Animation.pngbin0 -> 708 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_BodyShape.pngbin0 -> 828 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_CallingCard.pngbin0 -> 462 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Clothing.pngbin0 -> 463 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Eye.pngbin0 -> 654 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Content.pngbin0 -> 620 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Full.pngbin0 -> 485 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_FolderClosed.pngbin0 -> 441 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_FolderOpen.pngbin0 -> 614 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Gesture.pngbin0 -> 615 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Gloves.pngbin0 -> 582 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Hair.pngbin0 -> 551 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Invalid.pngbin0 -> 539 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Jacket.pngbin0 -> 893 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Landmark.pngbin0 -> 965 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Link.pngbin0 -> 367 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LinkFolder.pngbin0 -> 508 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LinkItem.pngbin0 -> 508 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LookFolderClosed.pngbin0 -> 538 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LookFolderOpen.pngbin0 -> 697 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LostClosed.pngbin0 -> 495 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_LostOpen.pngbin0 -> 745 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Material.pngbin0 -> 1008 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Mesh.pngbin0 -> 977 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Notecard.pngbin0 -> 414 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Object.pngbin0 -> 575 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Object_Multi.pngbin0 -> 976 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Pants.pngbin0 -> 611 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Physics.pngbin0 -> 758 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Script.pngbin0 -> 551 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Settings.pngbin0 -> 1623 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_SettingsDay.pngbin0 -> 1812 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_SettingsSky.pngbin0 -> 1811 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_SettingsWater.pngbin0 -> 1621 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Shape.pngbin0 -> 693 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Shirt.pngbin0 -> 612 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Shoe.pngbin0 -> 3875 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Skin.pngbin0 -> 627 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Skirt.pngbin0 -> 702 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Snapshot.pngbin0 -> 722 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Socks.pngbin0 -> 565 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Sound.pngbin0 -> 584 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_StockFolderClosed.pngbin0 -> 1120 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_StockFolderOpen.pngbin0 -> 1282 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_SysClosed.pngbin0 -> 4558 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_SysOpen.pngbin0 -> 4649 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Tattoo.pngbin0 -> 559 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Texture.pngbin0 -> 379 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Toolbar_SearchVisibility.pngbin0 -> 722 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_TrashClosed.pngbin0 -> 480 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_TrashOpen.pngbin0 -> 479 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Underpants.pngbin0 -> 577 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Undershirt.pngbin0 -> 423 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_Universal.pngbin0 -> 1081 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_UnknownObject.pngbin0 -> 1752 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_VersionFolderClosed.pngbin0 -> 1120 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Inv_VersionFolderOpen.pngbin0 -> 1438 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/List_View_Disabled.pngbin0 -> 374 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/List_View_On.pngbin0 -> 379 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Lock.pngbin0 -> 577 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Locked_Icon.pngbin0 -> 471 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/MP_Logo.pngbin0 -> 1106 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Male.pngbin0 -> 494 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Microphone_On.pngbin0 -> 520 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/MinusItem_Disabled.pngbin0 -> 370 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/MinusItem_Off.pngbin0 -> 377 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/MinusItem_Press.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/MusicNote.pngbin0 -> 764 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OptionsMenu_Disabled.pngbin0 -> 520 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OptionsMenu_Off.pngbin0 -> 523 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OptionsMenu_Press.pngbin0 -> 506 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Disabled.pngbin0 -> 5520 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Off.pngbin0 -> 5495 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_On.pngbin0 -> 5570 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_On_Over.pngbin0 -> 5556 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Over.pngbin0 -> 5274 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Press.pngbin0 -> 5563 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_1.pngbin0 -> 5529 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_2.pngbin0 -> 5483 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_3.pngbin0 -> 5486 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_4.pngbin0 -> 5557 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_5.pngbin0 -> 5593 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Progress_6.pngbin0 -> 5526 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Selected.pngbin0 -> 5596 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Disabled.pngbin0 -> 5554 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Over.pngbin0 -> 5576 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Press.pngbin0 -> 5628 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Dark.pngbin0 -> 721 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Light.pngbin0 -> 730 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Build_Dark.pngbin0 -> 527 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_DamageNo_Dark.pngbin0 -> 636 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Damage_Dark.pngbin0 -> 511 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Exp_Color.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Dark.pngbin0 -> 943 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Light.pngbin0 -> 934 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Fly_Dark.pngbin0 -> 524 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_ForSale_Light.pngbin0 -> 652 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Health_Dark.pngbin0 -> 600 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_M_Dark.pngbin0 -> 490 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_M_Light.pngbin0 -> 488 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_PG_Dark.pngbin0 -> 495 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_PG_Light.pngbin0 -> 492 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_PushNo_Dark.pngbin0 -> 683 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_PushNo_Light.pngbin0 -> 654 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Push_Dark.pngbin0 -> 596 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_R_Dark.pngbin0 -> 490 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_R_Light.pngbin0 -> 487 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_ScriptsNo_Dark.pngbin0 -> 723 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Scripts_Dark.pngbin0 -> 553 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Dark.pngbin0 -> 660 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Light.pngbin0 -> 655 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Dark.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Light.pngbin0 -> 503 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Dark.pngbin0 -> 710 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Light.pngbin0 -> 710 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Voice_Dark.pngbin0 -> 550 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Parcel_Voice_Light.pngbin0 -> 599 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Pathfinding_Dirty.pngbin0 -> 713 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Pathfinding_Disabled.pngbin0 -> 579 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Pause_Off.pngbin0 -> 385 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Pause_Over.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Pause_Press.pngbin0 -> 376 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Permission_Ungranted.pngbin0 -> 834 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Person_Check.pngbin0 -> 855 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Person_Star.pngbin0 -> 690 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Play_Off.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Play_Over.pngbin0 -> 443 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Play_Press.pngbin0 -> 448 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Presets_Icon.pngbin0 -> 1069 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Presets_Icon_Graphic.pngbin0 -> 535 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Friend_Offline.pngbin0 -> 420 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Friend_Online.pngbin0 -> 433 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Disabled.pngbin0 -> 1008 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Enabled.pngbin0 -> 1051 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Disabled.pngbin0 -> 888 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Enabled.pngbin0 -> 949 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Disabled.pngbin0 -> 897 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Enabled.pngbin0 -> 939 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_1.pngbin0 -> 678 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_10.pngbin0 -> 671 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_11.pngbin0 -> 674 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_12.pngbin0 -> 685 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_2.pngbin0 -> 675 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_3.pngbin0 -> 679 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_4.pngbin0 -> 673 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_5.pngbin0 -> 671 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_6.pngbin0 -> 684 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_7.pngbin0 -> 674 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_8.pngbin0 -> 680 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Progress_9.pngbin0 -> 680 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Refresh_Off.pngbin0 -> 624 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/SL_Logo.pngbin0 -> 1484 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Search_Icon.pngbin0 -> 628 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Shirt_Large.pngbin0 -> 641 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Shop.pngbin0 -> 523 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/SkipBackward_Off.pngbin0 -> 477 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/SkipForward_Off.pngbin0 -> 469 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/StopReload_Off.pngbin0 -> 639 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/StopReload_Over.pngbin0 -> 626 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Stop_Off.pngbin0 -> 363 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Disabled.pngbin0 -> 1089 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Enabled.pngbin0 -> 4636 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_1.pngbin0 -> 1080 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_2.pngbin0 -> 1077 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_3.pngbin0 -> 1114 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_4.pngbin0 -> 1108 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_5.pngbin0 -> 1070 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Sync_Progress_6.pngbin0 -> 1095 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/System_Notification_Large.pngbin0 -> 1170 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/System_Notification_Small.pngbin0 -> 593 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/TrashItem_Disabled.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/TrashItem_Off.pngbin0 -> 415 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/TrashItem_Press.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/UnZoom_Off.pngbin0 -> 587 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/UpArrow_Off.pngbin0 -> 428 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Video_URL_Off.pngbin0 -> 466 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoiceMute_Off.pngbin0 -> 753 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoicePTT_Lvl1.pngbin0 -> 6625 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoicePTT_Lvl2.pngbin0 -> 6879 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoicePTT_Lvl3.pngbin0 -> 952 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoicePTT_Off.pngbin0 -> 583 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/VoicePTT_On.pngbin0 -> 5521 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Web_Profile_Off.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/YouAreHere_Badge.pngbin0 -> 6385 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/Zoom_Off.pngbin0 -> 598 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/add_icon.pngbin0 -> 691 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/back_arrow_off.pngbin0 -> 7213 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/back_arrow_over.pngbin0 -> 7162 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/back_arrow_press.pngbin0 -> 7041 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/check_mark.pngbin0 -> 2517 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/collapse_to_one_line.pngbin0 -> 621 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/copy_clipboard.pngbin0 -> 811 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/delete_icon.pngbin0 -> 809 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/edit_mine.pngbin0 -> 896 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/edit_theirs.pngbin0 -> 902 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/emoji_picker_icon.pngbin0 -> 787 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/expand_one_liner.pngbin0 -> 627 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/file_upload.pngbin0 -> 640 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/hand.pngbin0 -> 899 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/map_placeholder.pngbin0 -> 8718 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/multi_folder_mode.pngbin0 -> 329 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/nearby_chat_icon.pngbin0 -> 586 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/object_icon.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/paste_clipboard.pngbin0 -> 792 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/pop_up_caution.pngbin0 -> 765 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_beta.pngbin0 -> 644 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_beta_lifetime.pngbin0 -> 641 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_lifetime.pngbin0 -> 780 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_linden.pngbin0 -> 1065 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_pplus_lifetime.pngbin0 -> 780 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_badge_premium_lifetime.pngbin0 -> 777 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off.pngbin0 -> 656 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off_pressed.pngbin0 -> 656 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on.pngbin0 -> 616 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on_pressed.pngbin0 -> 646 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/remove_icon.pngbin0 -> 705 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/see_me_online.pngbin0 -> 2315 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/see_on_map.pngbin0 -> 2665 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/see_them_on_map.pngbin0 -> 2679 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/see_them_online.pngbin0 -> 2469 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/single_folder_back.pngbin0 -> 607 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/single_folder_forward.pngbin0 -> 608 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/single_folder_mode.pngbin0 -> 320 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/single_folder_up.pngbin0 -> 545 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/snapshot_icon.pngbin0 -> 717 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/texture_icon.pngbin0 -> 349 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/thumbnail_fallback_icon.pngbin0 -> 2203 bytes
-rw-r--r--indra/newview/skins/classic/textures/icons/unknown_icon.pngbin0 -> 1177 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/fps_button.pngbin0 -> 195 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_blue_bullet.pngbin0 -> 654 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_green_bullet.pngbin0 -> 626 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_help_bullet.pngbin0 -> 704 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_info_bullet.pngbin0 -> 490 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_red_bullet.pngbin0 -> 629 bytes
-rw-r--r--indra/newview/skins/classic/textures/megapahit/mp_yellow_bullet.pngbin0 -> 648 bytes
-rw-r--r--indra/newview/skins/classic/textures/model_wizard/progress_bar_bg.pngbin0 -> 556 bytes
-rw-r--r--indra/newview/skins/classic/textures/model_wizard/progress_light.pngbin0 -> 3771 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Arrow_Left_Off.pngbin0 -> 382 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Arrow_Right_Off.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/BuyArrow_Over.pngbin0 -> 4935 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/BuyArrow_Press.pngbin0 -> 4937 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Favorite_Link_Over.pngbin0 -> 191 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Favorite_Star_Active.pngbin0 -> 6979 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Favorite_Star_Off.pngbin0 -> 444 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Favorite_Star_Over.pngbin0 -> 6596 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Favorite_Star_Press.pngbin0 -> 616 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/FileMenu_Divider.pngbin0 -> 116 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Flag.pngbin0 -> 338 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Help_Press.pngbin0 -> 384 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Home_Off.pngbin0 -> 379 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Info_Off.pngbin0 -> 2654 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Info_Over.pngbin0 -> 675 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Info_Press.pngbin0 -> 700 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Landmarks.pngbin0 -> 15870 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Lock.pngbin0 -> 302 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/NavBar_BG.pngbin0 -> 6334 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/NavBar_BG_NoFav_Bevel.pngbin0 -> 5658 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/NavBar_BG_NoNav_Bevel.pngbin0 -> 5130 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Row_Selection.pngbin0 -> 1197 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/Search.pngbin0 -> 516 bytes
-rw-r--r--indra/newview/skins/classic/textures/navbar/separator.pngbin0 -> 330 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/Activate_Checkmark.pngbin0 -> 435 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Foreground.pngbin0 -> 355 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Press.pngbin0 -> 339 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Foreground.pngbin0 -> 341 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Press.pngbin0 -> 344 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Close_Off.pngbin0 -> 305 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Home_Selected.pngbin0 -> 790 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Me_Off.pngbin0 -> 297 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Open_Off.pngbin0 -> 294 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_People_Off.pngbin0 -> 367 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Places_Off.pngbin0 -> 405 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TabIcon_Things_Off.pngbin0 -> 223 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Off.pngbin0 -> 272 bytes
-rw-r--r--indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Selected.pngbin0 -> 325 bytes
-rw-r--r--indra/newview/skins/classic/textures/textures.xml931
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/360_capture.pngbin0 -> 793 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/appearance.pngbin0 -> 1205 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/avatars.pngbin0 -> 1432 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/build.pngbin0 -> 1246 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/caret_bottom.pngbin0 -> 195 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/caret_left.pngbin0 -> 948 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/caret_right.pngbin0 -> 949 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/chat.pngbin0 -> 1277 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/destinations.pngbin0 -> 1297 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/environments.pngbin0 -> 1630 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/facebook.pngbin0 -> 424 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/favorite_folder.pngbin0 -> 572 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/flickr.pngbin0 -> 15530 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/gestures.pngbin0 -> 1675 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/grid_status.pngbin0 -> 483 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/highlighting.pngbin0 -> 500 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/highlighting_selected.pngbin0 -> 2732 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/howto.pngbin0 -> 1306 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/inventory.pngbin0 -> 1114 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/land.pngbin0 -> 1123 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/map.pngbin0 -> 1206 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/marketplace.pngbin0 -> 1311 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/mini_cart.pngbin0 -> 474 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/mini_map.pngbin0 -> 1766 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/mktlistings.pngbin0 -> 579 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/move.pngbin0 -> 1328 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/nearbyvoice.pngbin0 -> 1479 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/outbox.pngbin0 -> 1521 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/people.pngbin0 -> 1313 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/performance.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/picks.pngbin0 -> 1396 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/places.pngbin0 -> 1391 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/preferences.pngbin0 -> 1587 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/profile.pngbin0 -> 1180 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/report_abuse.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/resync_animations.pngbin0 -> 3627 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/search.pngbin0 -> 1406 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/snapshot.pngbin0 -> 1142 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/speak.pngbin0 -> 1253 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/twitter.pngbin0 -> 5696 bytes
-rw-r--r--indra/newview/skins/classic/textures/toolbar_icons/view.pngbin0 -> 1487 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Down.pngbin0 -> 517 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Left.pngbin0 -> 485 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Right.pngbin0 -> 487 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Small_Down.pngbin0 -> 478 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Small_Left.pngbin0 -> 414 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Small_Right.pngbin0 -> 414 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Small_Up.pngbin0 -> 493 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Arrow_Up.pngbin0 -> 528 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Badge_Background.pngbin0 -> 1266 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Badge_Border.pngbin0 -> 1392 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Disabled.pngbin0 -> 851 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Off.pngbin0 -> 4239 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Over.pngbin0 -> 4393 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Press.pngbin0 -> 4138 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Disabled.pngbin0 -> 796 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Off.pngbin0 -> 4052 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Over.pngbin0 -> 4242 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Press.pngbin0 -> 4123 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Disabled.pngbin0 -> 588 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Off.pngbin0 -> 3724 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Over.pngbin0 -> 3916 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Press.pngbin0 -> 3711 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_Disabled.pngbin0 -> 470 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_Off.pngbin0 -> 480 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_On.pngbin0 -> 635 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_On_Disabled.pngbin0 -> 621 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_On_Press.pngbin0 -> 647 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Checkbox_Press.pngbin0 -> 515 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_Disabled.pngbin0 -> 575 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_Hover.pngbin0 -> 552 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_Off.pngbin0 -> 5629 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_On.pngbin0 -> 6104 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_Selected.pngbin0 -> 6401 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_UpOff.pngbin0 -> 5555 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ComboButton_UpSelected.pngbin0 -> 6324 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DisclosureArrow_Opened_Off.pngbin0 -> 392 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DropDown_Disabled.pngbin0 -> 669 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DropDown_Off.pngbin0 -> 678 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DropDown_On.pngbin0 -> 3450 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DropDown_Press.pngbin0 -> 3264 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/DropTarget.pngbin0 -> 604 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Error_Tag_Background.pngbin0 -> 1317 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Linden_Dollar_Alert.pngbin0 -> 68647 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Linden_Dollar_Background.pngbin0 -> 130520 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ListItem_Over.pngbin0 -> 1209 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ListItem_Select.pngbin0 -> 1217 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Off.pngbin0 -> 911 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Selected.pngbin0 -> 6198 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Marketplace_Dropzone_Background.pngbin0 -> 639 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/New_Tag_Background.pngbin0 -> 948 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/New_Tag_Border.pngbin0 -> 963 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ProgressBar.pngbin0 -> 4577 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ProgressBarSolid.pngbin0 -> 378 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ProgressTrack.pngbin0 -> 399 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Disabled.pngbin0 -> 569 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Login.pngbin0 -> 1437 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Login_Over.pngbin0 -> 1516 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Login_Pressed.pngbin0 -> 1493 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Off.pngbin0 -> 4809 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_On.pngbin0 -> 2643 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_On_Selected.pngbin0 -> 2700 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Over.pngbin0 -> 4815 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Press.pngbin0 -> 2700 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Selected.pngbin0 -> 2700 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Selected_Disabled.pngbin0 -> 2643 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/PushButton_Selected_Press.pngbin0 -> 2700 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_Disabled.pngbin0 -> 606 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_Off.pngbin0 -> 628 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_On.pngbin0 -> 679 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_On_Disabled.pngbin0 -> 652 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_On_Press.pngbin0 -> 688 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/RadioButton_Press.pngbin0 -> 666 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Down.pngbin0 -> 443 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Opaque.pngbin0 -> 470 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Over_Opaque.pngbin0 -> 445 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Left.pngbin0 -> 454 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Opaque.pngbin0 -> 418 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Over_Opaque.pngbin0 -> 431 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Right.pngbin0 -> 445 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Opaque.pngbin0 -> 420 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Over_Opaque.pngbin0 -> 429 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Up.pngbin0 -> 465 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Opaque.pngbin0 -> 458 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Over_Opaque.pngbin0 -> 468 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollThumb_Horiz.pngbin0 -> 509 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollThumb_Vert.pngbin0 -> 494 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollTrack_Horiz.pngbin0 -> 364 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/ScrollTrack_Vert.pngbin0 -> 361 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Disabled.pngbin0 -> 4673 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Off.pngbin0 -> 4680 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Over.pngbin0 -> 4619 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Press.pngbin0 -> 4786 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected.pngbin0 -> 4786 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Disabled.pngbin0 -> 4850 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Over.pngbin0 -> 4388 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Press.pngbin0 -> 5438 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Disabled.pngbin0 -> 4542 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected.pngbin0 -> 4574 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.pngbin0 -> 4601 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Press.pngbin0 -> 5348 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Disabled.pngbin0 -> 4922 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Off.pngbin0 -> 4921 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_On_Selected.pngbin0 -> 5725 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Over.pngbin0 -> 4844 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Press.pngbin0 -> 4926 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected.pngbin0 -> 4926 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Disabled.pngbin0 -> 5112 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Press.pngbin0 -> 5725 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SliderThumb_Disabled.pngbin0 -> 592 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SliderThumb_Off.pngbin0 -> 579 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SliderThumb_Press.pngbin0 -> 582 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SliderTrack_Horiz.pngbin0 -> 420 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/SliderTrack_Vert.pngbin0 -> 417 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Stepper_Down_Off.pngbin0 -> 4901 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Stepper_Down_Press.pngbin0 -> 506 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Stepper_Up_Off.pngbin0 -> 4909 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Stepper_Up_Press.pngbin0 -> 2171 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Active.pngbin0 -> 4359 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Disabled.pngbin0 -> 4356 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Off.pngbin0 -> 4359 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Search_Active.pngbin0 -> 903 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Search_Disabled.pngbin0 -> 886 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Search_Highlight.pngbin0 -> 3250 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/TextField_Search_Off.pngbin0 -> 901 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/Tooltip.pngbin0 -> 404 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/bevel_background.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/buy_off.pngbin0 -> 2914 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/buy_over.pngbin0 -> 3026 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/buy_press.pngbin0 -> 2652 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/horizontal_drag_handle.pngbin0 -> 389 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/jump_left_in.pngbin0 -> 434 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/jump_left_out.pngbin0 -> 422 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/jump_right_in.pngbin0 -> 426 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/jump_right_out.pngbin0 -> 423 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_moon_back.pngbin0 -> 1767 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_moon_front.pngbin0 -> 2060 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom.pngbin0 -> 1125 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom_active.pngbin0 -> 617 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side.pngbin0 -> 1107 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side_active.pngbin0 -> 561 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side.pngbin0 -> 1121 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side_active.pngbin0 -> 591 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_top.pngbin0 -> 1133 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_rotate_top_active.pngbin0 -> 627 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_sphere.pngbin0 -> 14927 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_sun_back.pngbin0 -> 1626 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/track_control_sun_front.pngbin0 -> 1911 bytes
-rw-r--r--indra/newview/skins/classic/textures/widgets/vertical_drag_handle.pngbin0 -> 396 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Dragbar.pngbin0 -> 503 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Flyout_Left.pngbin0 -> 421 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Flyout_Pointer.pngbin0 -> 436 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Flyout_Right.pngbin0 -> 423 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Close_Foreground.pngbin0 -> 402 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Close_Press.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Close_Toast.pngbin0 -> 579 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Dock_Foreground.pngbin0 -> 413 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Dock_Press.pngbin0 -> 428 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Gear.pngbin0 -> 4355 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Gear_Background.pngbin0 -> 515 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Gear_Foreground.pngbin0 -> 516 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Gear_Press.pngbin0 -> 510 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Help_Foreground.pngbin0 -> 501 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Help_Press.pngbin0 -> 501 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Minimize_Foreground.pngbin0 -> 351 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Minimize_Press.pngbin0 -> 351 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Restore_Foreground.pngbin0 -> 450 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Restore_Press.pngbin0 -> 456 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Icon_Undock_Foreground.pngbin0 -> 415 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Inspector_Background.pngbin0 -> 462 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Inspector_Hover.pngbin0 -> 645 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Inspector_I.pngbin0 -> 2654 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Resize_Corner.pngbin0 -> 4679 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Toast_Background.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Toast_CloseBtn.pngbin0 -> 579 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Toast_Over.pngbin0 -> 647 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Volume_Background.pngbin0 -> 674 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Wearables_Divider.pngbin0 -> 311 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Window_Background.pngbin0 -> 6780 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/Window_Foreground.pngbin0 -> 6900 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/add_payment_image_center.pngbin0 -> 36083 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/add_payment_image_left.pngbin0 -> 34181 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/add_payment_image_right.pngbin0 -> 33753 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/first_login_image.jpgbin0 -> 104529 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_arrow_down.pngbin0 -> 623 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_arrow_left.pngbin0 -> 532 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_arrow_lower_left.pngbin0 -> 540 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_arrow_right.pngbin0 -> 563 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_arrow_up.pngbin0 -> 637 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/hint_background.pngbin0 -> 1582 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/login_mp_logo.pngbin0 -> 23425 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/login_mp_logo_small.pngbin0 -> 17032 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/login_sl_logo.pngbin0 -> 6180 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/login_sl_logo_small.png (renamed from indra/newview/skins/default/textures/windows/login_sl_logo_small.png)bin5204 -> 5204 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/startup_logo.pngbin0 -> 3446 bytes
-rw-r--r--indra/newview/skins/classic/textures/windows/yellow_gradient.pngbin0 -> 1733 bytes
-rw-r--r--indra/newview/skins/classic/textures/world/BeaconArrow.pngbin0 -> 994 bytes
-rw-r--r--indra/newview/skins/classic/textures/world/CameraDragDot.pngbin0 -> 563 bytes
-rw-r--r--indra/newview/skins/classic/textures/world/NoEntryLines.pngbin0 -> 4829 bytes
-rw-r--r--indra/newview/skins/classic/textures/world/NoEntryPassLines.pngbin0 -> 5263 bytes
-rw-r--r--indra/newview/skins/default/colors.xml1528
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Up_On.pngbin4134 -> 2282 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.pngbin6625 -> 1960 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.pngbin6879 -> 2053 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_On.pngbin5521 -> 1842 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/WellButton_Lit.pngbin5762 -> 557 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.pngbin5762 -> 559 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cone_Selected.pngbin5269 -> 2394 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cube_Selected.pngbin4505 -> 2278 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cylinder_Selected.pngbin4451 -> 2273 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Grass_Selected.pngbin7922 -> 2538 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.pngbin5001 -> 2357 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.pngbin4497 -> 2292 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.pngbin5224 -> 2530 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Prism_Selected.pngbin4747 -> 2419 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Pyramid_Selected.pngbin5137 -> 2389 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Ring_Selected.pngbin6066 -> 2560 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Sphere_Selected.pngbin7005 -> 2799 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.pngbin5201 -> 2394 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Torus_Selected.pngbin6125 -> 2645 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tree_Selected.pngbin6377 -> 2794 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tube_Selected.pngbin5131 -> 2506 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Selected.pngbin2235 -> 15050 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabLeft_Flat_Off.pngbin0 -> 18169 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabLeft_Flat_Selected.pngbin0 -> 221 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_First_Flat_Off.pngbin0 -> 253 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_First_Flat_Selected.pngbin0 -> 259 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Off.pngbin0 -> 250 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Selected.pngbin0 -> 256 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Off.pngbin0 -> 221 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Selected.pngbin0 -> 226 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Flash.pngbin356 -> 225 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Off.pngbin4894 -> 254 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Over.pngbin4903 -> 256 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.pngbin3734 -> 235 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Flash.pngbin316 -> 197 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.pngbin4812 -> 196 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.pngbin4818 -> 195 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.pngbin3527 -> 15778 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Flash.pngbin428 -> 225 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Off.pngbin4917 -> 257 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Over.pngbin4921 -> 255 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.pngbin4120 -> 231 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Info_Over.pngbin2654 -> 1974 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_SysClosed.pngbin4558 -> 2266 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_SysOpen.pngbin4649 -> 2361 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/SL_Logo.pngbin1484 -> 1136 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/back_arrow_off.pngbin7213 -> 920 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/back_arrow_over.pngbin7162 -> 921 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/back_arrow_press.pngbin7041 -> 920 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/check_mark.pngbin2517 -> 2136 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/hand.pngbin899 -> 2337 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/see_me_online.pngbin2315 -> 1843 bytes
-rw-r--r--indra/newview/skins/default/textures/locked_image_dark.pngbin0 -> 18122 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Active.pngbin6979 -> 2241 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Over.pngbin6596 -> 1967 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Off.pngbin2654 -> 582 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Over.pngbin675 -> 543 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Press.pngbin700 -> 602 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.pngbin5658 -> 216 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Row_Selection.pngbin1197 -> 1736 bytes
-rw-r--r--indra/newview/skins/default/textures/square_selection.pngbin0 -> 18061 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml34
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Disabled.pngbin470 -> 204 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Off.pngbin480 -> 213 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On.pngbin635 -> 486 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.pngbin621 -> 360 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On_Press.pngbin647 -> 465 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Press.pngbin515 -> 199 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Slim_Off.pngbin0 -> 18115 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Slim_On.pngbin0 -> 17762 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Arrow.pngbin0 -> 16236 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Disabled.pngbin575 -> 15356 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Off.pngbin5629 -> 338 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Selected.pngbin6401 -> 15216 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Transparent.pngbin0 -> 18116 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_UpOff.pngbin5555 -> 16654 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.pngbin6324 -> 16828 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Disabled.pngbin669 -> 15771 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Off.pngbin678 -> 15125 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_On.pngbin3450 -> 443 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Press.pngbin3264 -> 15322 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ListItem_Over.pngbin1209 -> 15029 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ListItem_Select.pngbin1217 -> 15029 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.pngbin911 -> 513 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.pngbin6198 -> 555 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ProgressBar.pngbin4577 -> 414 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Disabled.pngbin569 -> 238 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Login.pngbin1437 -> 396 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Login_Over.pngbin1516 -> 399 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Login_Pressed.pngbin1493 -> 399 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Off.pngbin4809 -> 233 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_On.pngbin2643 -> 304 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Over.pngbin4815 -> 363 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Press.pngbin2700 -> 232 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.pngbin2700 -> 15333 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Sign.pngbin0 -> 18631 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Sign_Over.pngbin0 -> 18631 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Sign_Pressed.pngbin0 -> 18631 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Disabled.pngbin606 -> 316 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Off.pngbin628 -> 293 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On.pngbin679 -> 332 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.pngbin652 -> 344 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On_Press.pngbin688 -> 371 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Press.pngbin666 -> 327 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.pngbin509 -> 15228 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.pngbin494 -> 15233 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.pngbin4673 -> 208 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.pngbin4680 -> 203 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.pngbin4619 -> 315 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.pngbin4786 -> 203 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.pngbin4786 -> 302 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.pngbin4542 -> 15261 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.pngbin4574 -> 15265 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.pngbin4601 -> 15279 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.pngbin5348 -> 15359 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.pngbin592 -> 316 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Off.pngbin579 -> 293 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Press.pngbin582 -> 327 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.pngbin420 -> 15033 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Down_Off.pngbin4901 -> 270 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Down_Press.pngbin506 -> 359 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Up_Off.pngbin4909 -> 259 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Up_Press.pngbin2171 -> 345 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Active.pngbin4359 -> 305 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Disabled.pngbin4356 -> 315 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Highlight.pngbin0 -> 329 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Off.pngbin4359 -> 295 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Active.pngbin903 -> 698 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.pngbin886 -> 679 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.pngbin3250 -> 498 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Off.pngbin901 -> 696 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Transparent.pngbin0 -> 15031 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/track_control_moon_back.pngbin1767 -> 2587 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/track_control_moon_front.pngbin2060 -> 2479 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/track_control_sphere.pngbin14927 -> 9705 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/track_control_sun_back.pngbin1626 -> 2439 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_I.pngbin2654 -> 1974 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Background.pngbin6780 -> 321 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Foreground.pngbin6900 -> 323 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_NoTitle_Background.pngbin0 -> 278 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.pngbin0 -> 277 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/login_mp_logo.pngbin23425 -> 31160 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/login_mp_logo_horizontal.pngbin0 -> 10788 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/login_mp_logo_small.pngbin17032 -> 10162 bytes
-rw-r--r--indra/newview/skins/default/xui/da/floater_joystick.xml14
-rw-r--r--indra/newview/skins/default/xui/da/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/da/floater_voice_effect.xml30
-rw-r--r--indra/newview/skins/default/xui/da/floater_whitelist_entry.xml2
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_alerts.xml1
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_sound.xml2
-rw-r--r--indra/newview/skins/default/xui/da/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/de/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/de/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/de/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/de/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/de/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml26
-rw-r--r--indra/newview/skins/default/xui/en/floater_add_payment_method.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_adjust_environment.xml26
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_picker.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_big_preview.xml25
-rw-r--r--indra/newview/skins/default/xui/en/floater_bulk_perms.xml12
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml13
-rw-r--r--indra/newview/skins/default/xui/en/floater_create_landmark.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_edit_hover_height.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_god_tools.xml58
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_settings.xml13
-rw-r--r--indra/newview/skins/default/xui/en/floater_live_material_editor.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml21
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_environments.xml11
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_new_feature_notification.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_performance.xml8
-rw-r--r--indra/newview/skins/default/xui/en/floater_post_process.xml426
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml32
-rw-r--r--indra/newview/skins/default/xui/en/floater_profile.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_quick_prefs.xml209
-rw-r--r--indra/newview/skins/default/xui/en/floater_script.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_sound_devices.xml48
-rw-r--r--indra/newview/skins/default/xui/en/floater_stats.xml58
-rw-r--r--indra/newview/skins/default/xui/en/floater_telehub.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_combobox.xml32
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_slapp.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml668
-rw-r--r--indra/newview/skins/default/xui/en/floater_toybox.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_voice_effect.xml162
-rw-r--r--indra/newview/skins/default/xui/en/floater_whitelist_entry.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml75
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml140
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_attachment_self.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_other.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_conversation.xml107
-rw-r--r--indra/newview/skins/default/xui/en/menu_conversation_log_view.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_view_default.xml48
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml27
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml67
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_blocked_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_chiclet_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_conversation_list_item.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_shape.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_experience_search.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_gltf_material.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_general.xml63
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notices.xml5
-rw-r--r--indra/newview/skins/default/xui/en/panel_hint.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_hint_image.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml549
-rw-r--r--indra/newview/skins/default/xui/en/panel_login_first.xml262
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_marketplace_listings.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_navigation_bar.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification_list_item.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_edit.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml5
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_preferences.xml19
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml26
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_colors.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml61
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml38
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_move.xml224
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml21
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml31
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_experiences.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml61
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_terrain.xml26
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_question_toast.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml14
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml256
-rw-r--r--indra/newview/skins/default/xui/en/panel_voice_effect.xml33
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml20
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml11
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/filter_editor.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/floater.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/folder_view_item.xml13
-rw-r--r--indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inbox_folder_view_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/line_editor.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_editor.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tab_container.xml31
-rw-r--r--indra/newview/skins/default/xui/en/widgets/toolbar.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml10
-rw-r--r--indra/newview/skins/default/xui/es/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/es/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/es/floater_voice_effect.xml138
-rw-r--r--indra/newview/skins/default/xui/es/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/es/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/fr/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_post_process.xml54
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/fr/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/fr/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/it/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/it/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/it/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/it/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/it/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/ja/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/ja/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/ja/fonts.xml78
-rw-r--r--indra/newview/skins/default/xui/ja/panel_login_first.xml54
-rw-r--r--indra/newview/skins/default/xui/ja/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/pl/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_post_process.xml49
-rw-r--r--indra/newview/skins/default/xui/pl/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/pl/floater_voice_effect.xml98
-rw-r--r--indra/newview/skins/default/xui/pl/panel_login_first.xml30
-rw-r--r--indra/newview/skins/default/xui/pl/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/pt/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/pt/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/pt/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/pt/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/pt/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/ru/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/ru/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/ru/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/ru/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/ru/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/tr/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/tr/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/tr/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/tr/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/tr/panel_voice_effect.xml15
-rw-r--r--indra/newview/skins/default/xui/zh/floater_big_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/zh/floater_post_process.xml53
-rw-r--r--indra/newview/skins/default/xui/zh/floater_sound_devices.xml7
-rw-r--r--indra/newview/skins/default/xui/zh/floater_voice_effect.xml159
-rw-r--r--indra/newview/skins/default/xui/zh/panel_login_first.xml39
-rw-r--r--indra/newview/skins/default/xui/zh/panel_voice_effect.xml15
-rw-r--r--indra/newview/tests/lldateutil_test.cpp6
-rw-r--r--indra/newview/tests/llviewernetwork_test.cpp10
-rw-r--r--indra/newview/tests/llworldmap_test.cpp73
-rwxr-xr-xindra/newview/viewer_manifest.py56
-rw-r--r--indra/test/lldatapacker_tut.cpp8
1470 files changed, 18141 insertions, 21774 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 58e637f290..aacbfe6496 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -74,7 +74,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llphysicsextensionsos)
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem)
-if (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64) OR (${LINUX_DISTRO} MATCHES gentoo) OR (${LINUX_DISTRO} MATCHES debian AND CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)))
+if (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64)))
add_subdirectory(${LIBS_OPEN_PREFIX}llwebrtc)
endif ()
add_subdirectory(${LIBS_OPEN_PREFIX}llwindow)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 42e211c84d..3e1dab7c00 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -16,6 +16,7 @@ include_guard()
include(Variables)
include(Linker)
+include(UnixInstall)
# We go to some trouble to set LL_BUILD to the set of relevant compiler flags.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}")
@@ -127,7 +128,7 @@ endif (NOT CMAKE_CXX_COMPILER_ID MATCHES GNU AND WINDOWS)
if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set( CMAKE_BUILD_WITH_INSTALL_RPATH TRUE )
- set( CMAKE_INSTALL_RPATH $ORIGIN $ORIGIN/../lib )
+ set( CMAKE_INSTALL_RPATH ${INSTALL_LIBRARY_DIR} )
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-libs,ALL")
find_program(CCACHE_EXE ccache)
@@ -153,7 +154,7 @@ if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
--param asan-stack=0
)
add_link_options(-fsanitize=address)
- else()
+ elseif( NOT (${LINUX_DISTRO} MATCHES freedesktop) )
add_compile_definitions( _FORTIFY_SOURCE=2 )
endif()
@@ -190,6 +191,7 @@ if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(CLANG_WARNINGS
${GCC_CLANG_COMPATIBLE_WARNINGS}
# Put clang specific warning configuration here
+ -Wno-inconsistent-missing-override
)
set(GCC_WARNINGS
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index 4ce0d47f7f..ef541388d8 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -5,21 +5,22 @@ include_guard()
add_library( ll::apr INTERFACE IMPORTED )
-if (WINDOWS)
- target_include_directories(ll::apr SYSTEM INTERFACE ${prefix_result}/../include)
- target_link_directories(ll::apr INTERFACE ${prefix_result})
- target_link_libraries(ll::apr INTERFACE libapr-1 libaprutil-1)
-else ()
- include(FindPkgConfig)
- pkg_check_modules(Apr REQUIRED apr-1 apr-util-1)
- target_include_directories(ll::apr SYSTEM INTERFACE ${Apr_INCLUDE_DIRS})
- target_link_directories(ll::apr INTERFACE ${Apr_LIBRARY_DIRS})
- target_link_libraries(ll::apr INTERFACE ${Apr_LIBRARIES})
+if (NOT (${LINUX_DISTRO} MATCHES freedesktop))
+ if (WINDOWS)
+ target_include_directories(ll::apr SYSTEM INTERFACE ${prefix_result}/../include)
+ target_link_directories(ll::apr INTERFACE ${prefix_result})
+ target_link_libraries(ll::apr INTERFACE libapr-1 libaprutil-1)
+ else ()
+ include(FindPkgConfig)
+ pkg_check_modules(Apr REQUIRED apr-1 apr-util-1)
+ target_include_directories(ll::apr SYSTEM INTERFACE ${Apr_INCLUDE_DIRS})
+ target_link_directories(ll::apr INTERFACE ${Apr_LIBRARY_DIRS})
+ target_link_libraries(ll::apr INTERFACE ${Apr_LIBRARIES})
+ endif ()
+ return ()
endif ()
-return ()
-
-use_system_binary( apr apr-util )
+#use_system_binary( apr apr-util )
use_prebuilt_binary(apr_suite)
if (WINDOWS)
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index 8e6764c93b..9746704907 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -12,32 +12,45 @@ if (DARWIN)
elseif (WINDOWS)
target_include_directories( ll::boost SYSTEM INTERFACE ${prefix_result}/../include)
target_link_directories( ll::boost INTERFACE ${prefix_result})
- if ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
- set(sfx -vc143-mt-a64-1_91)
+ # Detect the actual toolset/version suffix from whatever vcpkg installed.
+ # Glob for boost_context-*.lib and strip the known prefix to get the suffix.
+ file(GLOB _boost_context_libs "${prefix_result}/boost_context-*.lib")
+ if (_boost_context_libs)
+ list(GET _boost_context_libs 0 _boost_context_lib)
+ get_filename_component(_boost_context_name "${_boost_context_lib}" NAME_WE)
+ string(REPLACE "boost_context" "" sfx "${_boost_context_name}")
else ()
- set(sfx -vc143-mt-x64-1_91)
+ if ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
+ set(sfx -vc143-mt-a64-1_91)
+ else ()
+ set(sfx -vc143-mt-x64-1_91)
+ endif ()
+ message(WARNING "Could not detect Boost suffix via glob; using fallback '${sfx}'. "
+ "Check that vcpkg installed boost into ${prefix_result}.")
endif ()
-else ()
+elseif (NOT (${LINUX_DISTRO} MATCHES freedesktop))
find_package( Boost )
endif ()
-target_link_libraries( ll::boost INTERFACE
- boost_context${sfx}
- boost_fiber${sfx}
- boost_filesystem${sfx}
- boost_program_options${sfx}
- boost_thread${sfx}
- boost_url${sfx}
- )
-if (WINDOWS)
- target_link_libraries( ll::boost INTERFACE boost_json${sfx})
-else ()
- target_link_libraries( ll::boost INTERFACE boost_regex${sfx})
-endif ()
-if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES fedora) OR DARWIN)
- target_link_libraries( ll::boost INTERFACE boost_system${sfx})
+if (NOT (${LINUX_DISTRO} MATCHES freedesktop))
+ target_link_libraries( ll::boost INTERFACE
+ boost_context${sfx}
+ boost_fiber${sfx}
+ boost_filesystem${sfx}
+ boost_program_options${sfx}
+ boost_thread${sfx}
+ boost_url${sfx}
+ )
+ if (WINDOWS)
+ target_link_libraries( ll::boost INTERFACE boost_json${sfx})
+ else ()
+ target_link_libraries( ll::boost INTERFACE boost_regex${sfx})
+ endif ()
+ if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES fedora) OR DARWIN)
+ target_link_libraries( ll::boost INTERFACE boost_system${sfx})
+ endif ()
+ target_compile_definitions( ll::boost INTERFACE BOOST_BIND_GLOBAL_PLACEHOLDERS )
+ return()
endif ()
-target_compile_definitions( ll::boost INTERFACE BOOST_BIND_GLOBAL_PLACEHOLDERS )
-return()
if( USE_CONAN )
target_link_libraries( ll::boost INTERFACE CONAN_PKG::boost )
@@ -55,48 +68,42 @@ if (WINDOWS)
find_library(BOOST_CONTEXT_LIBRARY
NAMES
+ libboost_context
libboost_context-mt
libboost_context-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FIBER_LIBRARY
NAMES
+ libboost_fiber
libboost_fiber-mt
libboost_fiber-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FILESYSTEM_LIBRARY
NAMES
+ libboost_filesystem
libboost_filesystem-mt
libboost_filesystem-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_PROGRAMOPTIONS_LIBRARY
NAMES
+ libboost_program_options
libboost_program_options-mt
libboost_program_options-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
- find_library(BOOST_REGEX_LIBRARY
- NAMES
- libboost_regex-mt
- libboost_regex-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
- find_library(BOOST_SYSTEM_LIBRARY
- NAMES
- libboost_system-mt
- libboost_system-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
find_library(BOOST_THREAD_LIBRARY
NAMES
+ libboost_thread
libboost_thread-mt
libboost_thread-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_URL_LIBRARY
NAMES
+ libboost_url
libboost_url-mt
libboost_url-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
@@ -105,48 +112,42 @@ else (WINDOWS)
find_library(BOOST_CONTEXT_LIBRARY
NAMES
+ boost_context
boost_context-mt
boost_context-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FIBER_LIBRARY
NAMES
+ boost_fiber
boost_fiber-mt
boost_fiber-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FILESYSTEM_LIBRARY
NAMES
+ boost_filesystem
boost_filesystem-mt
boost_filesystem-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_PROGRAMOPTIONS_LIBRARY
NAMES
+ boost_program_options
boost_program_options-mt
boost_program_options-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
- find_library(BOOST_REGEX_LIBRARY
- NAMES
- boost_regex-mt
- boost_regex-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
- find_library(BOOST_SYSTEM_LIBRARY
- NAMES
- boost_system-mt
- boost_system-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
find_library(BOOST_THREAD_LIBRARY
NAMES
+ boost_thread
boost_thread-mt
boost_thread-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_URL_LIBRARY
NAMES
+ boost_url
boost_url-mt
boost_url-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
@@ -158,8 +159,6 @@ target_link_libraries(ll::boost INTERFACE
${BOOST_CONTEXT_LIBRARY}
${BOOST_FILESYSTEM_LIBRARY}
${BOOST_PROGRAMOPTIONS_LIBRARY}
- ${BOOST_REGEX_LIBRARY}
- ${BOOST_SYSTEM_LIBRARY}
${BOOST_THREAD_LIBRARY}
${BOOST_URL_LIBRARY})
@@ -167,3 +166,4 @@ if (LINUX)
target_link_libraries(ll::boost INTERFACE rt)
endif (LINUX)
+target_include_directories(ll::boost SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake
index 31ed86213a..269afcc456 100644
--- a/indra/cmake/CEFPlugin.cmake
+++ b/indra/cmake/CEFPlugin.cmake
@@ -5,50 +5,212 @@ include(Prebuilt)
include_guard()
add_library( ll::cef INTERFACE IMPORTED )
-if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
+if (${LINUX_DISTRO} MATCHES arch AND (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64))
if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0)
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/v1.14.0-r3.tar.gz)
+ file(
+ COPY /usr/src/cef/libcef_dll
+ DESTINATION ${CMAKE_BINARY_DIR}
+ )
+ execute_process(
+ COMMAND sed -i "s/macro(L/cmake_minimum_required(VERSION 3.28)\\nmacro(SET_LIBRARY_TARGET_PROPERTIES)\\nendmacro()\\nmacro(L/" CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/libcef_dll
+ )
+ try_compile(LIBCEF_DLL_RESULT
+ PROJECT libcef_dll
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/libcef_dll
+ BINARY_DIR ${CMAKE_BINARY_DIR}/libcef_dll
+ CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ "-DCMAKE_CXX_FLAGS:STRING=-I/usr/include/cef -I/usr/src/cef -fPIC"
+ )
+ if (${LIBCEF_DLL_RESULT})
+ file(
+ COPY ${CMAKE_BINARY_DIR}/libcef_dll/libcef_dll_wrapper.a
+ DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
+ )
+ endif ()
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme.tar.gz)
file(DOWNLOAD
- https://github.com/secondlife/dullahan/archive/refs/tags/v1.14.0-r3.tar.gz
- ${CMAKE_BINARY_DIR}/v1.14.0-r3.tar.gz
+ https://github.com/secondlife/dullahan/archive/refs/tags/v1.40.0-CEF_150.0.19.embed_scheme.tar.gz
+ ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme.tar.gz
+ )
+ endif ()
+ file(ARCHIVE_EXTRACT
+ INPUT ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme.tar.gz
+ DESTINATION ${CMAKE_BINARY_DIR}
+ )
+ try_compile(DULLAHAN_RESULT
+ PROJECT dullahan
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme
+ BINARY_DIR ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme
+ CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
+ -DCMAKE_INSTALL_LIBDIR:PATH=${ARCH_PREBUILT_DIRS_RELEASE}
+ -DCEF_WRAPPER_DIR:PATH=/usr/include/cef
+ -DCEF_WRAPPER_BUILD_DIR:PATH=${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme
+ -DCEF_LIBRARY_RELEASE:FILEPATH=${INSTALL_PREFIX}/lib/cef/libcef.so
+ -DCEF_DLL_LIBRARY_RELEASE:FILEPATH=${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
+ "-DCMAKE_CXX_FLAGS:STRING=-I/usr/include/cef -I/usr/src/cef -DWRAPPING_CEF_SHARED"
+ )
+ if (${DULLAHAN_RESULT})
+ file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release)
+ file(
+ COPY ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme/dullahan_host
+ DESTINATION ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ if (CMAKE_BUILD_TYPE MATCHES Release)
+ execute_process(
+ COMMAND ${CMAKE_STRIP} dullahan_host
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release
)
+ endif ()
+ file(
+ COPY ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme/libdullahan.a
+ DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
+ )
+ file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/cef)
+ file(
+ COPY
+ ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme/src/dullahan.h
+ ${CMAKE_BINARY_DIR}/dullahan-1.40.0-CEF_150.0.19.embed_scheme/src/dullahan_version.h
+ DESTINATION ${LIBS_PREBUILT_DIR}/include/cef
+ )
+ file(WRITE ${PREBUILD_TRACKING_DIR}/dullahan_installed "0")
+ endif ()
+ endif ()
+elseif (${LINUX_DISTRO} MATCHES fedora)
+ if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0)
+ file(
+ COPY /usr/src/cef-146.0.11/libcef_dll
+ DESTINATION ${CMAKE_BINARY_DIR}
+ )
+ execute_process(
+ COMMAND sed -i "s/macro(L/cmake_minimum_required(VERSION 3.28)\\nmacro(SET_LIBRARY_TARGET_PROPERTIES)\\nendmacro()\\nmacro(L/" CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/libcef_dll
+ )
+ try_compile(LIBCEF_DLL_RESULT
+ PROJECT libcef_dll
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/libcef_dll
+ BINARY_DIR ${CMAKE_BINARY_DIR}/libcef_dll
+ CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ "-DCMAKE_CXX_FLAGS:STRING=-I/usr/include/cef -I/usr/src/cef-146.0.11 -fPIC"
+ )
+ if (${LIBCEF_DLL_RESULT})
+ file(
+ COPY ${CMAKE_BINARY_DIR}/libcef_dll/libcef_dll_wrapper.a
+ DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
+ )
+ endif ()
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12.tar.gz)
+ file(DOWNLOAD
+ https://github.com/secondlife/dullahan/archive/refs/tags/v1.29.0-CEF_146.0.12.tar.gz
+ ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12.tar.gz
+ )
endif ()
file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/v1.14.0-r3.tar.gz
+ INPUT ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12.tar.gz
+ DESTINATION ${CMAKE_BINARY_DIR}
+ )
+ try_compile(DULLAHAN_RESULT
+ PROJECT dullahan
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12
+ BINARY_DIR ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12
+ CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
+ -DCMAKE_INSTALL_LIBDIR:PATH=${ARCH_PREBUILT_DIRS_RELEASE}
+ -DCEF_WRAPPER_DIR:PATH=/usr/include/cef
+ -DCEF_WRAPPER_BUILD_DIR:PATH=${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12
+ -DCEF_LIBRARY_RELEASE:FILEPATH=${INSTALL_PREFIX}/lib${ADDRESS_SIZE}/cef/libcef.so
+ -DCEF_DLL_LIBRARY_RELEASE:FILEPATH=${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
+ "-DCMAKE_CXX_FLAGS:STRING=-I/usr/include/cef -I/usr/src/cef-146.0.11 -DWRAPPING_CEF_SHARED"
+ )
+ if (${DULLAHAN_RESULT})
+ file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release)
+ file(
+ COPY ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12/dullahan_host
+ DESTINATION ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ if (CMAKE_BUILD_TYPE MATCHES Release)
+ execute_process(
+ COMMAND ${CMAKE_STRIP} dullahan_host
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ endif ()
+ file(
+ COPY ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12/libdullahan.a
+ DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
+ )
+ file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/cef)
+ file(
+ COPY
+ ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12/src/dullahan.h
+ ${CMAKE_BINARY_DIR}/dullahan-1.29.0-CEF_146.0.12/src/dullahan_version.h
+ DESTINATION ${LIBS_PREBUILT_DIR}/include/cef
+ )
+ file(WRITE ${PREBUILD_TRACKING_DIR}/dullahan_installed "0")
+ endif ()
+ endif ()
+elseif (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
+ if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0)
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40.tar.gz)
+ file(DOWNLOAD
+ https://github.com/secondlife/dullahan/archive/refs/tags/v1.24.0-CEF_139.0.40.tar.gz
+ ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40.tar.gz
+ )
+ endif ()
+ file(ARCHIVE_EXTRACT
+ INPUT ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40.tar.gz
DESTINATION ${CMAKE_BINARY_DIR}
)
execute_process(
COMMAND sed -i "/#include <vector>/a #include <cstdint>" dullahan.h
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3/src
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40/src
)
file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/cef)
try_compile(DULLAHAN_RESULT
PROJECT dullahan
- SOURCE_DIR ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3
- BINARY_DIR ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40
+ BINARY_DIR ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40
CMAKE_FLAGS
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
- -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
- -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
-DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
-DCMAKE_INSTALL_LIBDIR:PATH=${ARCH_PREBUILT_DIRS_RELEASE}
-DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON
- -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS}
-DUSE_SPOTIFY_CEF:BOOL=ON
- -DSPOTIFY_CEF_URL:STRING=https://cef-builds.spotifycdn.com/cef_binary_118.4.1%2Bg3dd6078%2Bchromium-118.0.5993.54_linuxarm64_beta_minimal.tar.bz2
+ -DSPOTIFY_CEF_URL:STRING=https://cef-builds.spotifycdn.com/cef_binary_139.0.40%2Bg465474a%2Bchromium-139.0.7258.139_linuxarm64_minimal.tar.bz2
-DPROJECT_ARCH:STRING=${CMAKE_SYSTEM_PROCESSOR}
- -DENABLE_CXX11_ABI:BOOL=ON
)
if (${DULLAHAN_RESULT})
+ if (CMAKE_BUILD_TYPE MATCHES Release)
+ execute_process(
+ COMMAND ${CMAKE_STRIP}
+ chrome-sandbox
+ libEGL.so
+ libGLESv2.so
+ libcef.so
+ libvk_swiftshader.so
+ libvulkan.so.1
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40/_deps/cef_prebuild-src/${CMAKE_BUILD_TYPE}
+ )
+ endif ()
execute_process(
COMMAND ${CMAKE_MAKE_PROGRAM} install
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40
OUTPUT_VARIABLE dullahan_installed
)
+ if (CMAKE_BUILD_TYPE MATCHES Release)
+ execute_process(
+ COMMAND ${CMAKE_STRIP} dullahan_host
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ endif ()
file(
COPY
- ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3/src/dullahan.h
- ${CMAKE_BINARY_DIR}/dullahan-1.14.0-r3/src/dullahan_version.h
+ ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40/src/dullahan.h
+ ${CMAKE_BINARY_DIR}/dullahan-1.24.0-CEF_139.0.40/src/dullahan_version.h
DESTINATION ${LIBS_PREBUILT_DIR}/include/cef
)
file(WRITE ${PREBUILD_TRACKING_DIR}/dullahan_installed "${dullahan_installed}")
@@ -57,12 +219,6 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
else ()
use_prebuilt_binary(dullahan)
endif ()
-
-execute_process(
- COMMAND patchelf --remove-rpath bin/release/dullahan_host
- WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}
- )
-
target_include_directories( ll::cef SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/cef)
if (WINDOWS)
@@ -127,8 +283,35 @@ elseif (DARWIN)
-output libdullahan.a
WORKING_DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE}
)
-
elseif (LINUX)
+ if (NOT (${LINUX_DISTRO} MATCHES freedesktop))
+ execute_process(
+ COMMAND patchelf --set-rpath ${INSTALL_LIBRARY_DIR} dullahan_host
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ endif ()
+ if (${LINUX_DISTRO} MATCHES arch AND (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64) OR (${LINUX_DISTRO} MATCHES fedora))
+ target_include_directories( ll::cef SYSTEM INTERFACE /usr/include/cef/include)
+ if (${LINUX_DISTRO} MATCHES fedora)
+ set(LIB_SUFFIX ${ADDRESS_SIZE})
+ endif ()
+ target_link_directories( ll::cef INTERFACE ${INSTALL_PREFIX}/lib${LIB_SUFFIX}/cef )
+ execute_process(
+ COMMAND patchelf --add-rpath ${INSTALL_PREFIX}/lib${LIB_SUFFIX}/cef dullahan_host
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}/bin/release
+ )
+ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64 AND (CMAKE_BUILD_TYPE MATCHES Release))
+ execute_process(
+ COMMAND ${CMAKE_STRIP}
+ bin/release/chrome-sandbox
+ bin/release/dullahan_host
+ lib/release/libEGL.so
+ lib/release/libGLESv2.so
+ lib/release/libvk_swiftshader.so
+ lib/release/libvulkan.so.1
+ WORKING_DIRECTORY ${LIBS_PREBUILT_DIR}
+ )
+ endif ()
target_link_libraries( ll::cef INTERFACE
libdullahan.a
cef
diff --git a/indra/cmake/CURL.cmake b/indra/cmake/CURL.cmake
index 99045e3aa3..09fc43dff4 100644
--- a/indra/cmake/CURL.cmake
+++ b/indra/cmake/CURL.cmake
@@ -27,20 +27,20 @@ use_prebuilt_binary(curl)
endif ()
endif ()
elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/curl_installed OR NOT ${curl_installed} EQUAL 0)
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3.tar.gz)
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4.tar.gz)
file(DOWNLOAD
- https://github.com/secondlife/3p-curl/archive/refs/tags/v7.54.1-r3.tar.gz
- ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3.tar.gz
+ https://github.com/secondlife/3p-curl/archive/refs/tags/v7.54.1-r4.tar.gz
+ ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4.tar.gz
)
endif ()
file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3.tar.gz
+ INPUT ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4.tar.gz
DESTINATION ${CMAKE_BINARY_DIR}
)
if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
execute_process(
COMMAND sed -i netrc.c -e "s/defined(HAVE_GETPWUID_R)/0/g" netrc.c
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3/curl/lib
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4/curl/lib
)
endif ()
file(
@@ -60,16 +60,16 @@ elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRA
set(ENV{CFLAGS} "-std=c90")
execute_process(
COMMAND ./configure --disable-alt-svc --disable-dict --disable-doh --disable-file --disable-gopher --disable-headers-api --disable-hsts --disable-imap --disable-ldap --disable-ldaps --disable-libcurl-option --disable-manual --disable-mqtt --disable-ntlm --disable-ntlm-wb --disable-pop3 --disable-rtsp --disable-shared --disable-smb --disable-smtp --disable-sspi --disable-telnet --disable-tftp --disable-tls-srp --disable-unix-sockets --disable-verbose --disable-versioned-symbols --enable-threaded-resolver --with-ssl=${LIBS_PREBUILT_DIR} --without-libidn2 --without-libpsl --without-libssh2 --prefix=${LIBS_PREBUILT_DIR} --libdir=${ARCH_PREBUILT_DIRS_RELEASE}
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3/curl
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4/curl
)
execute_process(
COMMAND make -j${MAKE_JOBS}
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3/curl
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4/curl
)
unset(ENV{CFLAGS})
execute_process(
COMMAND make install
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r3/curl
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r4/curl
RESULT_VARIABLE curl_installed
)
if (CMAKE_SYSTEM_NAME MATCHES FreeBSD)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 680f2f3ac2..667a04a1c5 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -29,29 +29,6 @@ endmacro()
###################################################################
if(WINDOWS)
#*******************************
- # VIVOX - *NOTE: no debug version
- set(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
-
- # ND, it seems there is no such thing defined. At least when building a viewer
- # Does this maybe matter on some LL buildserver? Otherwise this and the snippet using slvoice_src_dir
- # can all go
- if( ARCH_PREBUILT_BIN_RELEASE )
- set(slvoice_src_dir "${ARCH_PREBUILT_BIN_RELEASE}")
- endif()
- set(slvoice_files SLVoice.exe )
- if (ADDRESS_SIZE EQUAL 64)
- list(APPEND vivox_libs
- vivoxsdk_x64.dll
- ortp_x64.dll
- )
- else (ADDRESS_SIZE EQUAL 64)
- list(APPEND vivox_libs
- vivoxsdk.dll
- ortp.dll
- )
- endif (ADDRESS_SIZE EQUAL 64)
-
- #*******************************
# Misc shared libs
set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
@@ -159,12 +136,6 @@ if(WINDOWS)
endforeach()
elseif(DARWIN)
- set(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(slvoice_files SLVoice)
- set(vivox_libs
- libortp.dylib
- libvivoxsdk.dylib
- )
set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
set(debug_files
)
@@ -188,15 +159,6 @@ elseif(LINUX)
set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}")
set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}")
- set(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(vivox_libs
- libsndfile.so.1
- libortp.so
- libvivoxoal.so.1
- libvivoxsdk.so
- )
- set(slvoice_files SLVoice)
-
# *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
# or ARCH_PREBUILT_DIRS
set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
@@ -226,8 +188,6 @@ elseif(LINUX)
else(WINDOWS)
message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
- set(vivox_lib_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
- set(vivox_libs "")
# *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
# or ARCH_PREBUILT_DIRS
set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/debug")
@@ -249,26 +209,6 @@ endif(WINDOWS)
# Done building the file lists, now set up the copy commands.
################################################################
-# Curiously, slvoice_files are only copied to SHARED_LIB_STAGING_DIR_RELEASE.
-# It's unclear whether this is oversight or intentional, but anyway leave the
-# single copy_if_different command rather than using to_staging_dirs.
-
-if( slvoice_src_dir )
- copy_if_different(
- ${slvoice_src_dir}
- "${SHARED_LIB_STAGING_DIR_RELEASE}"
- out_targets
- ${slvoice_files}
- )
- list(APPEND third_party_targets ${out_targets})
-endif()
-
-to_staging_dirs(
- ${vivox_lib_dir}
- third_party_targets
- ${vivox_libs}
- )
-
to_staging_dirs(
${release_src_dir}
third_party_targets
diff --git a/indra/cmake/Discord.cmake b/indra/cmake/Discord.cmake
index f474457b03..4893886afc 100644
--- a/indra/cmake/Discord.cmake
+++ b/indra/cmake/Discord.cmake
@@ -8,8 +8,13 @@ target_compile_definitions(ll::discord_sdk INTERFACE LL_DISCORD=1)
#use_prebuilt_binary(discord_sdk)
if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/discord_sdk_installed OR NOT ${discord_sdk_installed} EQUAL 0)
+ if (${LINUX_DISTRO} MATCHES gentoo)
+ set(PREFIX_PATH /var/cache/distfiles)
+ else ()
+ set(PREFIX_PATH $ENV{HOME}/Downloads)
+ endif ()
file(ARCHIVE_EXTRACT
- INPUT $ENV{HOME}/Downloads/DiscordSocialSdk-1.8.13395.zip
+ INPUT ${PREFIX_PATH}/DiscordSocialSdk-1.10.18687.zip
DESTINATION ${CMAKE_BINARY_DIR}
)
file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/discord_sdk)
@@ -19,9 +24,12 @@ if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKIN
${CMAKE_BINARY_DIR}/discord_social_sdk/include/discordpp.h
DESTINATION ${LIBS_PREBUILT_DIR}/include/discord_sdk
)
+ if ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
+ set(DISCORD_PLATFORM /arm64)
+ endif ()
if (WINDOWS)
file(
- COPY ${CMAKE_BINARY_DIR}/discord_social_sdk/bin/release/discord_partner_sdk.dll
+ COPY ${CMAKE_BINARY_DIR}/discord_social_sdk/bin/release${DISCORD_PLATFORM}/discord_partner_sdk.dll
DESTINATION ${LIBS_PREBUILT_DIR}/bin/release
)
set(LIBRARY_EXTENSION lib)
@@ -39,9 +47,15 @@ if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKIN
)
else ()
file(
- COPY ${CMAKE_BINARY_DIR}/discord_social_sdk/lib/release/${LIBRARY_PREFIX}discord_partner_sdk.${LIBRARY_EXTENSION}
+ COPY ${CMAKE_BINARY_DIR}/discord_social_sdk/lib/release${DISCORD_PLATFORM}/${LIBRARY_PREFIX}discord_partner_sdk.${LIBRARY_EXTENSION}
DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
)
+ if (CMAKE_BUILD_TYPE MATCHES Release AND LINUX)
+ execute_process(
+ COMMAND ${CMAKE_STRIP} libdiscord_partner_sdk.so
+ WORKING_DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE}
+ )
+ endif ()
endif ()
file(WRITE ${PREBUILD_TRACKING_DIR}/discord_sdk_installed "0")
endif ()
diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake
index ad8dc38c70..ec0b8a07d6 100644
--- a/indra/cmake/FMODSTUDIO.cmake
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -34,7 +34,7 @@ if (USE_FMODSTUDIO)
file(MAKE_DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE})
if (DARWIN)
execute_process(
- COMMAND hdiutil attach -noverify fmodstudioapi20234mac-installer.dmg
+ COMMAND hdiutil attach -noverify fmodstudioapi20235mac-installer.dmg
WORKING_DIRECTORY $ENV{HOME}/Downloads
)
file(
@@ -64,36 +64,36 @@ if (USE_FMODSTUDIO)
file(WRITE ${PREBUILD_TRACKING_DIR}/fmodstudio_installed "${fmodstudio_installed}")
else ()
file(ARCHIVE_EXTRACT
- INPUT $ENV{HOME}/Downloads/fmodstudioapi20234linux.tar.gz
+ INPUT $ENV{HOME}/Downloads/fmodstudioapi20235linux.tar.gz
DESTINATION ${CMAKE_BINARY_DIR}
)
file(
COPY
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod.hpp
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_codec.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_common.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_dsp.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_dsp_effects.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_errors.h
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/inc/fmod_output.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod.hpp
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_codec.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_common.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_dsp.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_dsp_effects.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_errors.h
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/inc/fmod_output.h
DESTINATION ${LIBS_PREBUILT_DIR}/include/fmodstudio
)
if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
file(
COPY
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/arm64/libfmod.so
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/arm64/libfmod.so.13
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/arm64/libfmod.so.13.34
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/arm64/libfmod.so
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/arm64/libfmod.so.13
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/arm64/libfmod.so.13.35
DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
FOLLOW_SYMLINK_CHAIN
)
else ()
file(
COPY
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13
- ${CMAKE_BINARY_DIR}/fmodstudioapi20234linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13.34
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13
+ ${CMAKE_BINARY_DIR}/fmodstudioapi20235linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13.35
DESTINATION ${ARCH_PREBUILT_DIRS_RELEASE}
FOLLOW_SYMLINK_CHAIN
)
diff --git a/indra/cmake/GLM.cmake b/indra/cmake/GLM.cmake
index db6acc065e..c7d0ec3aed 100644
--- a/indra/cmake/GLM.cmake
+++ b/indra/cmake/GLM.cmake
@@ -4,7 +4,7 @@ include(Prebuilt)
add_library( ll::glm INTERFACE IMPORTED )
#use_system_binary( glm )
-if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed))
+if (${LINUX_DISTRO} MATCHES freedesktop OR (${LINUX_DISTRO} MATCHES debian) OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64))
use_prebuilt_binary(glm)
elseif (NOT WINDOWS)
find_package( glm REQUIRED )
diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake
index 81b40cb0b5..144f92118b 100644
--- a/indra/cmake/LLPrimitive.cmake
+++ b/indra/cmake/LLPrimitive.cmake
@@ -18,155 +18,176 @@ if( USE_CONAN )
"${CONAN_INCLUDE_DIRS_COLLADADOM}/collada-dom/1.4/" )
endif()
-if (TRUE)
- include(FindPkgConfig)
- pkg_check_modules(Minizip REQUIRED minizip)
- if (${LINUX_DISTRO} MATCHES arch OR (${LINUX_DISTRO} MATCHES gentoo) OR DARWIN)
+#use_system_binary( colladadom )
+
+#use_prebuilt_binary(colladadom)
+if (${LINUX_DISTRO} MATCHES freedesktop)
+use_prebuilt_binary(minizip-ng) # needed for colladadom
+#use_prebuilt_binary(libxml2)
+
+find_library(MINIZIPNG_LIBRARY
+ NAMES
+ minizip.lib
+ libminizip.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::minizip-ng INTERFACE ${MINIZIPNG_LIBRARY})
+endif ()
+
+if (FALSE)
+find_library(LIBXML2_LIBRARY
+ NAMES
+ libxml2.lib
+ libxml2.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libxml INTERFACE ${LIBXML2_LIBRARY})
+
+if (WINDOWS)
+ target_link_libraries( ll::libxml INTERFACE Bcrypt.lib)
+endif()
+endif (FALSE)
+
+include(FindPkgConfig)
+if (NOT (${LINUX_DISTRO} MATCHES freedesktop))
+ pkg_search_module(Minizip REQUIRED minizip)
+endif ()
+if (${LINUX_DISTRO} MATCHES arch OR (${LINUX_DISTRO} MATCHES gentoo) OR DARWIN OR WINDOWS)
set(Minizip_INCLUDE_DIRS ${Minizip_INCLUDE_DIRS}/minizip)
- endif ()
- pkg_check_modules(Libxml2 REQUIRED libxml-2.0)
- target_link_libraries( ll::minizip-ng INTERFACE ${Minizip_LIBRARIES} )
- target_link_libraries( ll::libxml INTERFACE ${Libxml2_LIBRARIES} )
- if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/colladadom_installed OR NOT ${colladadom_installed} EQUAL 0)
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10.tar.gz)
- file(DOWNLOAD
- https://github.com/secondlife/3p-colladadom/archive/refs/tags/v2.3-r10.tar.gz
- ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10.tar.gz
+elseif (${LINUX_DISTRO} MATCHES freedesktop)
+ set(Minizip_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/minizip-ng)
+ set(Minizip_LIBRARY_DIRS ${ARCH_PREBUILT_DIRS_RELEASE})
+endif ()
+pkg_search_module(Libxml2 REQUIRED libxml-2.0)
+target_link_libraries( ll::minizip-ng INTERFACE ${Minizip_LIBRARIES} )
+target_link_libraries( ll::libxml INTERFACE ${Libxml2_LIBRARIES} )
+if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/colladadom_installed OR NOT ${colladadom_installed} EQUAL 0)
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11.tar.gz)
+ file(DOWNLOAD
+ https://github.com/secondlife/3p-colladadom/archive/refs/tags/v2.3-r11.tar.gz
+ ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11.tar.gz
)
endif ()
file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10.tar.gz
- DESTINATION ${CMAKE_BINARY_DIR}
+ INPUT ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11.tar.gz
+ DESTINATION ${CMAKE_BINARY_DIR}
)
if (WINDOWS OR CMAKE_COMMAND MATCHES /usr/bin/cmake)
- execute_process(
- COMMAND sed -i "s/include_directories/cmake_minimum_required(VERSION 3.28)\\ninclude_directories/" CMakeLists.txt
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
+ execute_process(
+ COMMAND sed -i "s/include_directories/cmake_minimum_required(VERSION 3.28)\\ninclude_directories/" CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
)
else ()
- execute_process(
- COMMAND sed -i "" -e "s/include_directories/cmake_minimum_required(VERSION 3.28)\\ninclude_directories/" CMakeLists.txt
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
+ execute_process(
+ COMMAND sed -i "" -e "s/include_directories/cmake_minimum_required(VERSION 3.28)\\ninclude_directories/" CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
)
endif ()
if (WINDOWS)
- execute_process(
- COMMAND sed -i "s/SHARED/STATIC/" 1.4/CMakeLists.txt
- COMMAND sed -i "/#include <cstdarg>/a #define WIN32" dae/daeUtils.cpp
- COMMAND sed -i "/using namespace cdom;/a namespace boost{void boost::throw_exception(class std::exception const &){}}" dae/daeURI.cpp
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10/src
+ execute_process(
+ COMMAND sed -i "s/SHARED/STATIC/" 1.4/CMakeLists.txt
+ COMMAND sed -i "/#include <cstdarg>/a #define WIN32" dae/daeUtils.cpp
+ COMMAND sed -i "/using namespace cdom;/a namespace boost{void boost::throw_exception(class std::exception const &){}}" dae/daeURI.cpp
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11/src
+ )
+ elseif (CMAKE_COMMAND MATCHES /usr/bin/cmake)
+ execute_process(
+ COMMAND sed -i "s/SHARED/STATIC/" src/1.4/CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
)
else ()
- execute_process(
- COMMAND sed -i "" -e "s/SHARED/STATIC/" src/1.4/CMakeLists.txt
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
+ execute_process(
+ COMMAND sed -i "" -e "s/SHARED/STATIC/" src/1.4/CMakeLists.txt
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
)
endif ()
if (DARWIN)
- set(BOOST_CFLAGS -I${Libxml2_LIBRARY_DIRS}exec/boost/1.88/include)
- set(BOOST_LIBS -L${Minizip_LIBRARY_DIRS}exec/boost/1.88/lib)
- set(BOOST_LIBRARY_SUFFIX -mt)
+ set(BOOST_CFLAGS -I${Libxml2_LIBRARY_DIRS}exec/boost/1.88/include)
+ set(BOOST_LIBS -L${Minizip_LIBRARY_DIRS}exec/boost/1.88/lib)
+ set(BOOST_LIBRARY_SUFFIX -mt)
elseif (WINDOWS)
- set(BOOST_CFLAGS -I${prefix_result}/../include)
- set(BOOST_LIBS -L${prefix_result})
- if ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
- set(BOOST_LIBRARY_SUFFIX -vc143-mt-a64-1_91)
+ set(BOOST_CFLAGS -I${prefix_result}/../include)
+ set(BOOST_LIBS -L${prefix_result})
+ # Detect actual toolset/version suffix from vcpkg-installed libs.
+ file(GLOB _boost_context_libs "${prefix_result}/boost_context-*.lib")
+ if (_boost_context_libs)
+ list(GET _boost_context_libs 0 _boost_context_lib)
+ get_filename_component(_boost_context_name "${_boost_context_lib}" NAME_WE)
+ string(REPLACE "boost_context" "" BOOST_LIBRARY_SUFFIX "${_boost_context_name}")
else ()
- set(BOOST_LIBRARY_SUFFIX -vc143-mt-x64-1_91)
+ if ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
+ set(BOOST_LIBRARY_SUFFIX -vc143-mt-a64-1_91)
+ else ()
+ set(BOOST_LIBRARY_SUFFIX -vc143-mt-x64-1_91)
+ endif ()
+ message(WARNING "Could not detect Boost suffix via glob in LLPrimitive; using fallback.")
endif ()
elseif (CMAKE_SYSTEM_NAME MATCHES FreeBSD)
- set(BOOST_CFLAGS -I/usr/local/include)
- execute_process(
- COMMAND sed -i "" -e "s/endif 0/endif/" dae/daeUtils.cpp
- COMMAND sed -i "" -e "s/linux/FreeBSD/" dae/daeUtils.cpp
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10/src
+ set(BOOST_CFLAGS -I/usr/local/include)
+ execute_process(
+ COMMAND sed -i "" -e "s/endif 0/endif/" dae/daeUtils.cpp
+ COMMAND sed -i "" -e "s/linux/FreeBSD/" dae/daeUtils.cpp
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11/src
)
+ elseif (${LINUX_DISTRO} MATCHES freedesktop)
+ set(BOOST_CFLAGS -I${LIBS_PREBUILT_DIR}/include)
+ set(BOOST_LIBS -L${ARCH_PREBUILT_DIRS_RELEASE})
endif ()
file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/collada/1.4)
try_compile(COLLADADOM_RESULT
- PROJECT colladadom
- SOURCE_DIR ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
- BINARY_DIR ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
- TARGET collada14dom
- CMAKE_FLAGS
- -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
- -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
- -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
- -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
- -DCMAKE_CXX_STANDARD:STRING=17
- -DCMAKE_CXX_FLAGS:STRING=-I${Minizip_INCLUDE_DIRS}
- -DBoost_CFLAGS:STRING=${BOOST_CFLAGS}
- -DEXTRA_COMPILE_FLAGS:STRING=-I${Libxml2_INCLUDE_DIRS}
- "-DCMAKE_SHARED_LINKER_FLAGS:STRING=-L${Minizip_LIBRARY_DIRS} ${BOOST_LIBS}"
- -DBoost_FILESYSTEM_LIBRARY:STRING=boost_filesystem${BOOST_LIBRARY_SUFFIX}
- -DBoost_SYSTEM_LIBRARY:STRING=boost_system${BOOST_LIBRARY_SUFFIX}
- -DZLIB_LIBRARIES:STRING=${Libxml2_LIBRARIES}
- -DOPT_COLLADA14:BOOL=ON
- -DCOLLADA_DOM_INCLUDE_INSTALL_DIR:PATH=${LIBS_PREBUILT_DIR}/include/collada
+ PROJECT colladadom
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
+ BINARY_DIR ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
+ TARGET collada14dom
+ CMAKE_FLAGS
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
+ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
+ -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
+ -DCMAKE_CXX_STANDARD:STRING=17
+ -DCMAKE_CXX_FLAGS:STRING=-I${Minizip_INCLUDE_DIRS}
+ -DBoost_CFLAGS:STRING=${BOOST_CFLAGS}
+ -DEXTRA_COMPILE_FLAGS:STRING=-I${Libxml2_INCLUDE_DIRS}
+ "-DCMAKE_SHARED_LINKER_FLAGS:STRING=-L${Minizip_LIBRARY_DIRS} ${BOOST_LIBS}"
+ -DBoost_FILESYSTEM_LIBRARY:STRING=boost_filesystem${BOOST_LIBRARY_SUFFIX}
+ -DBoost_SYSTEM_LIBRARY:STRING=boost_system${BOOST_LIBRARY_SUFFIX}
+ -DZLIB_LIBRARIES:STRING=${Libxml2_LIBRARIES}
+ -DOPT_COLLADA14:BOOL=ON
+ -DCOLLADA_DOM_INCLUDE_INSTALL_DIR:PATH=${LIBS_PREBUILT_DIR}/include/collada
)
if (WINDOWS)
- execute_process(
- COMMAND MSBuild.exe ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10/Project.slnx -p:Configuration=${CMAKE_BUILD_TYPE}
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
- OUTPUT_VARIABLE colladadom_installed
+ execute_process(
+ COMMAND MSBuild.exe ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11/Project.slnx -p:Configuration=${CMAKE_BUILD_TYPE}
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
+ OUTPUT_VARIABLE colladadom_installed
)
- file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/include/collada)
- file(
- COPY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10/include
- DESTINATION ${LIBS_PREBUILT_DIR}/include
+ file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/include/collada)
+ file(
+ COPY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11/include
+ DESTINATION ${LIBS_PREBUILT_DIR}/include
)
- file(RENAME
- ${LIBS_PREBUILT_DIR}/include/include
- ${LIBS_PREBUILT_DIR}/include/collada
+ file(RENAME
+ ${LIBS_PREBUILT_DIR}/include/include
+ ${LIBS_PREBUILT_DIR}/include/collada
)
- file(MAKE_DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE})
- file(RENAME
- ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10/src/1.4/${CMAKE_BUILD_TYPE}/collada14dom.lib
- ${ARCH_PREBUILT_DIRS_RELEASE}/libcollada14dom23-s.lib
+ file(MAKE_DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE})
+ file(RENAME
+ ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11/src/1.4/${CMAKE_BUILD_TYPE}/collada14dom.lib
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libcollada14dom23-s.lib
)
elseif (${COLLADADOM_RESULT})
- execute_process(
- COMMAND ${CMAKE_MAKE_PROGRAM} install
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r10
- OUTPUT_VARIABLE colladadom_installed
+ execute_process(
+ COMMAND ${CMAKE_MAKE_PROGRAM} install
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-colladadom-2.3-r11
+ OUTPUT_VARIABLE colladadom_installed
)
- file(RENAME
- ${ARCH_PREBUILT_DIRS}/libcollada14dom.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libcollada14dom.a
+ file(RENAME
+ ${ARCH_PREBUILT_DIRS}/libcollada14dom.a
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libcollada14dom.a
)
endif ()
file(WRITE ${PREBUILD_TRACKING_DIR}/colladadom_installed "${colladadom_installed}")
- endif ()
-
-else (TRUE)
-
-use_system_binary( colladadom )
-
-use_prebuilt_binary(colladadom)
-use_prebuilt_binary(minizip-ng) # needed for colladadom
-use_prebuilt_binary(libxml2)
-
-find_library(MINIZIPNG_LIBRARY
- NAMES
- minizip.lib
- libminizip.a
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
-target_link_libraries(ll::minizip-ng INTERFACE ${MINIZIPNG_LIBRARY})
-
-find_library(LIBXML2_LIBRARY
- NAMES
- libxml2.lib
- libxml2.a
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
-target_link_libraries(ll::libxml INTERFACE ${LIBXML2_LIBRARY})
-
-if (WINDOWS)
- target_link_libraries( ll::libxml INTERFACE Bcrypt.lib)
-endif()
-
-endif (TRUE)
+endif ()
target_include_directories( ll::colladadom SYSTEM INTERFACE
${LIBS_PREBUILT_DIR}/include/collada
diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake
index 981f020745..7ff9a9e651 100644
--- a/indra/cmake/LibVLCPlugin.cmake
+++ b/indra/cmake/LibVLCPlugin.cmake
@@ -27,11 +27,14 @@ if (DARWIN)
target_include_directories( ll::libvlc SYSTEM INTERFACE /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/include)
target_link_directories( ll::libvlc INTERFACE /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib)
target_link_libraries( ll::libvlc INTERFACE vlc vlccore )
-elseif (WINDOWS)
+elseif (WINDOWS OR (${LINUX_DISTRO} MATCHES freedesktop))
use_prebuilt_binary(vlc-bin)
+ if (WINDOWS)
+ set(LIB_SUFFIX lib)
+ endif ()
target_link_libraries( ll::libvlc INTERFACE
- libvlc.lib
- libvlccore.lib
+ ${LIB_SUFFIX}vlc
+ ${LIB_SUFFIX}vlccore
)
else ()
include(FindPkgConfig)
diff --git a/indra/cmake/Meshoptimizer.cmake b/indra/cmake/Meshoptimizer.cmake
index 225f44b1fb..e65d0cac71 100644
--- a/indra/cmake/Meshoptimizer.cmake
+++ b/indra/cmake/Meshoptimizer.cmake
@@ -16,20 +16,20 @@ if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR CMAKE_
elseif (LINUX AND CMAKE_SYSTEM_PROCESSOR MATCHES x86_64 AND NOT (${LINUX_DISTRO} MATCHES gentoo))
use_prebuilt_binary(meshoptimizer)
elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/meshoptimizer_installed OR NOT ${meshoptimizer_installed} EQUAL 0)
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1.tar.gz)
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/meshoptimizer-1.2.tar.gz)
file(DOWNLOAD
- https://github.com/zeux/meshoptimizer/archive/refs/tags/v1.0.1.tar.gz
- ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1.tar.gz
+ https://github.com/zeux/meshoptimizer/archive/refs/tags/v1.2.tar.gz
+ ${CMAKE_BINARY_DIR}/meshoptimizer-1.2.tar.gz
)
endif ()
file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1.tar.gz
+ INPUT ${CMAKE_BINARY_DIR}/meshoptimizer-1.2.tar.gz
DESTINATION ${CMAKE_BINARY_DIR}
)
try_compile(MESHOPTIMIZER_RESULT
PROJECT meshoptimizer
- SOURCE_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1
- BINARY_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-1.2
+ BINARY_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-1.2
TARGET meshoptimizer
CMAKE_FLAGS
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
@@ -42,7 +42,7 @@ elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRA
if (${MESHOPTIMIZER_RESULT})
execute_process(
COMMAND ${CMAKE_MAKE_PROGRAM} install
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/meshoptimizer-1.0.1
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/meshoptimizer-1.2
OUTPUT_VARIABLE meshoptimizer_installed
)
file(WRITE ${PREBUILD_TRACKING_DIR}/meshoptimizer_installed "${meshoptimizer_installed}")
diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
index 1b7f9b9071..94c3b0fcf6 100644
--- a/indra/cmake/OPENAL.cmake
+++ b/indra/cmake/OPENAL.cmake
@@ -18,19 +18,26 @@ endif()
if (USE_OPENAL)
add_library( ll::openal INTERFACE IMPORTED )
-
- target_compile_definitions( ll::openal INTERFACE LL_OPENAL=1)
- include(FindPkgConfig)
- pkg_check_modules(Openal REQUIRED freealut)
- target_include_directories(ll::openal SYSTEM INTERFACE ${Openal_INCLUDE_DIRS})
- target_link_directories(ll::openal INTERFACE ${Openal_LIBRARY_DIRS})
- target_link_libraries(ll::openal INTERFACE ${Openal_LIBRARIES})
- return ()
-
+ if (${LINUX_DISTRO} MATCHES freedesktop)
target_include_directories( ll::openal SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/AL")
+ endif ()
target_compile_definitions( ll::openal INTERFACE LL_OPENAL=1)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
use_prebuilt_binary(openal)
+ file(REMOVE
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libopenal.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libopenal.so.1
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libopenal.so.1.24.2
+ ${LIBS_PREBUILT_DIR}/include/AL/al.h
+ ${LIBS_PREBUILT_DIR}/include/AL/alc.h
+ ${LIBS_PREBUILT_DIR}/include/AL/alext.h
+ ${LIBS_PREBUILT_DIR}/include/AL/efx-creative.h
+ ${LIBS_PREBUILT_DIR}/include/AL/efx-presets.h
+ ${LIBS_PREBUILT_DIR}/include/AL/efx.h
+ )
+ endif ()
+ if (FALSE)
find_library(OPENAL_LIBRARY
NAMES
OpenAL32
@@ -38,7 +45,11 @@ if (USE_OPENAL)
libopenal.dylib
libopenal.so
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+ endif ()
+ include(FindPkgConfig)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ pkg_search_module(Openal REQUIRED openal)
find_library(ALUT_LIBRARY
NAMES
alut
@@ -47,5 +58,12 @@ if (USE_OPENAL)
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
target_link_libraries(ll::openal INTERFACE ${OPENAL_LIBRARY} ${ALUT_LIBRARY})
+ else ()
+ pkg_search_module(Openal REQUIRED freealut)
+ endif ()
+
+ target_include_directories(ll::openal SYSTEM INTERFACE ${Openal_INCLUDE_DIRS})
+ target_link_directories(ll::openal INTERFACE ${Openal_LIBRARY_DIRS})
+ target_link_libraries(ll::openal INTERFACE ${Openal_LIBRARIES})
endif ()
diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake
index bf7cd8366a..feaedf16e5 100644
--- a/indra/cmake/OpenGL.cmake
+++ b/indra/cmake/OpenGL.cmake
@@ -4,3 +4,8 @@ include(Variables)
include(Prebuilt)
include(FindOpenGL)
+if (${LINUX_DISTRO} MATCHES freedesktop)
+ add_library(ll::glu INTERFACE IMPORTED)
+ use_prebuilt_binary(glu)
+ target_link_libraries(ll::glu INTERFACE GLU)
+endif ()
diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake
index 125f32e711..fbe028a199 100644
--- a/indra/cmake/OpenJPEG.cmake
+++ b/indra/cmake/OpenJPEG.cmake
@@ -6,70 +6,10 @@ include(Linking)
add_library( ll::openjpeg INTERFACE IMPORTED )
-#use_system_binary(openjpeg)
-#use_prebuilt_binary(openjpeg)
+include(FindPkgConfig)
+pkg_check_modules(Openjpeg REQUIRED libopenjp2)
+target_include_directories(ll::openjpeg SYSTEM INTERFACE ${Openjpeg_INCLUDE_DIRS})
+target_link_directories(ll::openjpeg INTERFACE ${Openjpeg_LIBRARY_DIRS})
+target_link_libraries(ll::openjpeg INTERFACE ${Openjpeg_LIBRARIES})
-if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/openjpeg_installed OR NOT ${openjpeg_installed} EQUAL 0)
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/openjpeg-2.5.3.tar.gz)
- file(DOWNLOAD
- https://github.com/uclouvain/openjpeg/archive/refs/tags/v2.5.3.tar.gz
- ${CMAKE_BINARY_DIR}/openjpeg-2.5.3.tar.gz
- )
- endif ()
- file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/openjpeg-2.5.3.tar.gz
- DESTINATION ${CMAKE_BINARY_DIR}
- )
-
- if (${LINUX_DISTRO} MATCHES ubuntu)
- try_compile(OPENJPEG_RESULT
- PROJECT OPENJPEG
- SOURCE_DIR ${CMAKE_BINARY_DIR}/openjpeg-2.5.3
- BINARY_DIR ${CMAKE_BINARY_DIR}/openjpeg-2.5.3
- TARGET openjp2
- CMAKE_FLAGS
- -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
- -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
- -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
- -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR}
- -DCMAKE_INSTALL_LIBDIR:PATH=${ARCH_PREBUILT_DIRS_RELEASE}
- -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON
- -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS}
- -DBUILD_CODEC:BOOL=OFF
- )
- if (${OPENJPEG_RESULT})
- execute_process(
- COMMAND ${CMAKE_MAKE_PROGRAM} install
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/openjpeg-2.5.3
- OUTPUT_VARIABLE openjpeg_installed
- )
- endif ()
-
- else ()
- execute_process(
- COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_INSTALL_PREFIX:PATH=${LIBS_PREBUILT_DIR} -DCMAKE_INSTALL_LIBDIR:PATH=${ARCH_PREBUILT_DIRS_RELEASE} -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS} -DBUILD_CODEC:BOOL=OFF
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/openjpeg-2.5.3
- OUTPUT_VARIABLE openjpeg_installed
- )
- endif ()
-
- file(
- COPY
- ${CMAKE_BINARY_DIR}/openjpeg-2.5.3/src/lib/openjp2/cio.h
- ${CMAKE_BINARY_DIR}/openjpeg-2.5.3/src/lib/openjp2/event.h
- ${CMAKE_BINARY_DIR}/openjpeg-2.5.3/src/lib/openjp2/opj_config_private.h
- DESTINATION ${LIBS_PREBUILT_DIR}/include/openjpeg-2.5
- )
- file(WRITE ${PREBUILD_TRACKING_DIR}/openjpeg_installed "${openjpeg_installed}")
-endif ()
-
-if (${LINUX_DISTRO} MATCHES ubuntu)
-target_link_libraries(ll::openjpeg INTERFACE openjp2 )
-else ()
- include(FindPkgConfig)
- pkg_check_modules(Openjpeg REQUIRED libopenjp2)
- target_include_directories(ll::openjpeg SYSTEM INTERFACE ${Openjpeg_INCLUDE_DIRS})
- target_link_directories(ll::openjpeg INTERFACE ${Openjpeg_LIBRARY_DIRS})
- target_link_libraries(ll::openjpeg INTERFACE ${Openjpeg_LIBRARIES})
-endif ()
target_include_directories( ll::openjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 39fd21c33f..428f9e3326 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -1,57 +1,18 @@
-# -*- cmake -*-
+# Allow explicit Python path via environment variable
+if(DEFINED ENV{PYTHON})
+ set(Python3_ROOT_DIR "$ENV{PYTHON}")
+endif()
-set(PYTHONINTERP_FOUND)
+# On Windows, prefer registry entries to avoid Cygwin/MSYS Python
+# The registry is searched first by default, which finds native Windows Python
+# installations rather than Cygwin/MSYS Python
+if(WINDOWS)
+ set(Python3_FIND_REGISTRY FIRST CACHE STRING "Python search order")
+endif()
-if (DEFINED ENV{PYTHON})
- # Allow python executable to be explicitly set
- set(python "$ENV{PYTHON}")
- set(PYTHONINTERP_FOUND ON)
-elseif (WINDOWS)
- # On Windows, explicitly avoid Cygwin Python.
+# Find Python 3 interpreter
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
- # if the user has their own version of Python installed, prefer that
- foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE)
- # prefer more recent Python versions to older ones, if multiple versions
- # are installed
- foreach(pyver 3.14 3.13 3.12 3.11 3.10 3.9 3.8 3.7)
- list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]")
- endforeach()
- endforeach()
-
- # TODO: This logic has the disadvantage that if you have multiple versions
- # of Python installed, the selected path won't necessarily be the newest -
- # e.g. this GLOB will prefer Python310 to Python311. But since pymaybe is
- # checked AFTER the registry entries, this will only surface as a problem if
- # no installed Python appears in the registry.
- file(GLOB pymaybe
- "$ENV{PROGRAMFILES}/Python*"
-## "$ENV{PROGRAMFILES(X86)}/Python*"
- # The Windows environment variable is in fact as shown above, but CMake
- # disallows querying an environment variable containing parentheses -
- # thanks, Windows. Fudge by just appending " (x86)" to $PROGRAMFILES and
- # hoping for the best.
- "$ENV{PROGRAMFILES} (x86)/Python*"
- "c:/Python*")
-
- find_program(python
- NAMES python3.exe python.exe
- NO_DEFAULT_PATH # added so that cmake does not find cygwin python
- PATHS
- ${regpaths}
- ${pymaybe}
- )
- find_package(Python3 COMPONENTS Interpreter)
-else()
- find_program(python python3)
-
- if (python)
- set(PYTHONINTERP_FOUND ON)
- endif (python)
-endif (DEFINED ENV{PYTHON})
-
-if (NOT python)
- message(FATAL_ERROR "No Python interpreter found")
-endif (NOT python)
-
-set(PYTHON_EXECUTABLE "${python}" CACHE FILEPATH "Python interpreter for builds")
+# Set legacy variable name for compatibility with existing code
+set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}" CACHE FILEPATH "Python interpreter for builds")
mark_as_advanced(PYTHON_EXECUTABLE)
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index ac45838427..c4b2dfbd37 100644
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -6,16 +6,19 @@ include(GLIB)
add_library( ll::uilibraries INTERFACE IMPORTED )
if (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ use_prebuilt_binary(fltk)
+ endif ()
target_compile_definitions(ll::uilibraries INTERFACE LL_FLTK=1 LL_X11=1 )
if( USE_CONAN )
return()
endif()
- if (${LINUX_DISTRO} MATCHES debian)
+ if (${LINUX_DISTRO} MATCHES arch OR (${LINUX_DISTRO} MATCHES debian) OR (${LINUX_DISTRO} MATCHES freedesktop) OR (${LINUX_DISTRO} MATCHES ubuntu))
include(FindPkgConfig)
- pkg_check_modules(Cairo REQUIRED cairo)
- target_include_directories(ll::uilibraries SYSTEM INTERFACE ${Cairo_INCLUDE_DIRS})
+ pkg_check_modules(CAIRO REQUIRED cairo)
+ target_include_directories(ll::uilibraries SYSTEM INTERFACE ${CAIRO_INCLUDE_DIRS})
endif ()
target_link_libraries( ll::uilibraries INTERFACE
@@ -51,8 +54,29 @@ if( WINDOWS )
)
endif()
-if (FALSE)
+if (${LINUX_DISTRO} MATCHES freedesktop)
target_include_directories( ll::uilibraries SYSTEM INTERFACE
${LIBS_PREBUILT_DIR}/include
)
+ pkg_check_modules(CAIRO-XLIB REQUIRED cairo-xlib)
+ pkg_check_modules(DBUS-1 REQUIRED dbus-1)
+ pkg_check_modules(LIBDECOR-0 REQUIRED libdecor-0)
+ pkg_check_modules(PANGO REQUIRED pango)
+ pkg_check_modules(PANGOCAIRO REQUIRED pangocairo)
+ pkg_check_modules(WAYLAND-CLIENT REQUIRED wayland-client)
+ pkg_check_modules(WAYLAND-CURSOR REQUIRED wayland-cursor)
+ pkg_check_modules(XKBCOMMON REQUIRED xkbcommon)
+ pkg_check_modules(XKBCOMMON-X11 REQUIRED xkbcommon-x11)
+ target_link_libraries(ll::uilibraries INTERFACE
+ ${CAIRO_LIBRARIES}
+ ${CAIRO-XLIB_LIBRARIES}
+ ${DBUS-1_LIBRARIES}
+ ${LIBDECOR-0_LIBRARIES}
+ ${PANGO_LIBRARIES}
+ ${PANGOCAIRO_LIBRARIES}
+ ${WAYLAND-CLIENT_LIBRARIES}
+ ${WAYLAND-CURSOR_LIBRARIES}
+ ${XKBCOMMON_LIBRARIES}
+ ${XKBCOMMON-X11_LIBRARIES}
+ )
endif ()
diff --git a/indra/cmake/UnixInstall.cmake b/indra/cmake/UnixInstall.cmake
index 1fd17a0142..70107fea9a 100644
--- a/indra/cmake/UnixInstall.cmake
+++ b/indra/cmake/UnixInstall.cmake
@@ -6,24 +6,26 @@ set(INSTALL OFF CACHE BOOL
"Generate install target.")
if (INSTALL)
- if (CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+ if (${LINUX_DISTRO} MATCHES freedesktop OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)
set(INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH
"Top-level installation directory.")
- else (CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+ else ()
set(INSTALL_PREFIX /usr CACHE PATH
"Top-level installation directory.")
- endif (CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+ endif ()
- if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
- set(_LIB lib/${ARCH}-linux-gnu)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ set(_LIB lib)
+ elseif (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
+ set(_LIB lib/${ARCH}-linux-gnu/${VIEWER_BINARY_NAME})
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR (${LINUX_DISTRO} MATCHES gentoo))
- set(_LIB lib${ADDRESS_SIZE})
+ set(_LIB lib${ADDRESS_SIZE}/${VIEWER_BINARY_NAME})
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
set(INSTALL_LIBRARY_DIR ${INSTALL_PREFIX}/${_LIB} CACHE PATH
- "Installation directory for read-only shared files.")
+ "Installation directory for dynamic library files and their resources.")
set(INSTALL_SHARE_DIR ${INSTALL_PREFIX}/share CACHE PATH
"Installation directory for read-only shared files.")
@@ -35,13 +37,17 @@ if (INSTALL)
set(APP_SHARE_DIR ${INSTALL_SHARE_DIR}/${VIEWER_BINARY_NAME}
CACHE PATH
"Installation directory for read-only data files.")
- if (${LINUX_DISTRO} MATCHES arch)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ set(APP_LIBEXEC_DIR ${INSTALL_PREFIX}/libexec
+ CACHE PATH
+ "Installation directory for non-manual executables.")
+ elseif (${LINUX_DISTRO} MATCHES arch)
set(APP_LIBEXEC_DIR ${INSTALL_PREFIX}/lib/${VIEWER_BINARY_NAME}
CACHE PATH
"Installation directory for non-manual executables.")
- else (${LINUX_DISTRO} MATCHES arch)
+ else ()
set(APP_LIBEXEC_DIR ${INSTALL_PREFIX}/libexec/${VIEWER_BINARY_NAME}
CACHE PATH
"Installation directory for non-manual executables.")
- endif (${LINUX_DISTRO} MATCHES arch)
+ endif ()
endif (INSTALL)
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index af13746c91..5efca62032 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -3,21 +3,13 @@ include(Prebuilt)
if (NOT (DARWIN OR WINDOWS))
add_library( ll::fontconfig INTERFACE IMPORTED )
-
find_package(Fontconfig REQUIRED)
target_link_libraries( ll::fontconfig INTERFACE Fontconfig::Fontconfig )
endif ()
-if (FALSE)
-if( NOT USE_CONAN )
- use_prebuilt_binary(libhunspell)
-endif()
-
-use_prebuilt_binary(slvoice)
-endif (FALSE)
-
-if (${LINUX_DISTRO} MATCHES debian AND CMAKE_SYSTEM_PROCESSOR MATCHES x86_64 OR DARWIN)
+if (DARWIN OR (${LINUX_DISTRO} MATCHES freedesktop))
use_prebuilt_binary(nanosvg)
endif ()
use_prebuilt_binary(viewer-fonts)
+use_prebuilt_binary(google-fonts)
use_prebuilt_binary(emoji_shortcodes)
diff --git a/indra/cmake/WebRTC.cmake b/indra/cmake/WebRTC.cmake
index 038ce90b88..1575c30d82 100644
--- a/indra/cmake/WebRTC.cmake
+++ b/indra/cmake/WebRTC.cmake
@@ -6,27 +6,18 @@ include(Prebuilt)
add_library( ll::webrtc INTERFACE IMPORTED )
target_include_directories( ll::webrtc SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/webrtc" "${LIBS_PREBUILT_DIR}/include/webrtc/third_party/abseil-cpp")
-if (DARWIN OR WINDOWS)
-use_prebuilt_binary(webrtc)
-elseif (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64) OR (${LINUX_DISTRO} MATCHES gentoo) OR (${LINUX_DISTRO} MATCHES debian AND CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)))
+if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64 AND LINUX)
target_compile_definitions(ll::webrtc INTERFACE CM_WEBRTC=1)
if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/webrtc_installed OR NOT ${webrtc_installed} EQUAL 0)
- if (DARWIN)
- set(WEBRTC_PLATFORM macos-arm64)
- elseif (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
- set(WEBRTC_PLATFORM linux-arm64)
- else ()
- set(WEBRTC_PLATFORM linux-x64)
- endif ()
- if (NOT EXISTS ${CMAKE_BINARY_DIR}/libwebrtc-${WEBRTC_PLATFORM}.tar.xz)
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/libwebrtc-linux-arm64.tar.xz)
file(DOWNLOAD
- https://github.com/crow-misia/libwebrtc-bin/releases/download/137.7151.3.1/libwebrtc-${WEBRTC_PLATFORM}.tar.xz
- ${CMAKE_BINARY_DIR}/libwebrtc-${WEBRTC_PLATFORM}.tar.xz
+ https://github.com/crow-misia/libwebrtc-bin/releases/download/139.7258.3.1/libwebrtc-linux-arm64.tar.xz
+ ${CMAKE_BINARY_DIR}/libwebrtc-linux-arm64.tar.xz
SHOW_PROGRESS
)
endif ()
file(ARCHIVE_EXTRACT
- INPUT ${CMAKE_BINARY_DIR}/libwebrtc-${WEBRTC_PLATFORM}.tar.xz
+ INPUT ${CMAKE_BINARY_DIR}/libwebrtc-linux-arm64.tar.xz
DESTINATION ${LIBS_PREBUILT_DIR}
)
file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/include/webrtc)
@@ -34,7 +25,6 @@ elseif (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES a
foreach(directory
api
audio
- base
build
buildtools
call
@@ -67,16 +57,10 @@ elseif (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES a
${LIBS_PREBUILT_DIR}/lib/libwebrtc.a
${ARCH_PREBUILT_DIRS_RELEASE}/libwebrtc.a
)
- if (CMAKE_OSX_ARCHITECTURES MATCHES arm64)
- file(REMOVE_RECURSE ${ARCH_PREBUILT_DIRS_RELEASE}/WebRTC.framework)
- file(RENAME
- ${LIBS_PREBUILT_DIR}/Frameworks/WebRTC.xcframework/${WEBRTC_PLATFORM}/WebRTC.framework
- ${ARCH_PREBUILT_DIRS_RELEASE}/WebRTC.framework
- )
- file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/Frameworks)
- endif ()
file(WRITE ${PREBUILD_TRACKING_DIR}/webrtc_installed "0")
endif ()
+elseif (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64)))
+use_prebuilt_binary(webrtc)
endif ()
find_library(WEBRTC_LIBRARY
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index bcb00e6afd..2452352097 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1424,6 +1424,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
size_t mem_size = pixels * bytes_per_pixel;
alpha_data = (U8*)ll_aligned_malloc_32(mem_size);
+ if (!alpha_data)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Failed to allocate memory for morph texture: " << (S32)(mem_size) << LL_ENDL;
+ return;
+ }
bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels
@@ -1433,6 +1439,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
{ // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO
// returning only the alpha portion without locking up downstream
U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA
+ if (!temp)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Failed to allocate temporary memory for morph texture readback: " << (S32)(mem_size << 2) << LL_ENDL;
+ return;
+ }
if (bound_target)
{
@@ -1471,6 +1483,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// We just want GL_ALPHA, but that isn't supported in OGL core profile 4.
static const size_t TEMP_BYTES_PER_PIXEL = 4;
U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL);
+ if (!temp_data)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Failed to allocate temporary memory for morph texture: " << (S32)(mem_size * TEMP_BYTES_PER_PIXEL) << LL_ENDL;
+ return;
+ }
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data);
for (size_t pixel = 0; pixel < pixels; pixel++) {
alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3];
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index 5e785e4f3e..59320cc00d 100644
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -27,6 +27,7 @@
#ifndef LL_LLTEXLAYERPARAMS_H
#define LL_LLTEXLAYERPARAMS_H
+#include <atomic>
#include "llpointer.h"
#include "v4color.h"
#include "llviewervisualparam.h"
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 613c408157..6f2f7eae61 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -225,6 +225,7 @@ void LLAudioEngine::updateChannels()
void LLAudioEngine::idle()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;
// "Update" all of our audio sources, clean up dead ones.
// Primarily does position updating, cleanup of unused audio sources.
// Also does regeneration of the current priority of each audio source.
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt
index 7c158c4ff9..6795652136 100644
--- a/indra/llcharacter/CMakeLists.txt
+++ b/indra/llcharacter/CMakeLists.txt
@@ -17,14 +17,12 @@ set(llcharacter_SOURCE_FILES
lljointsolverrp3.cpp
llkeyframefallmotion.cpp
llkeyframemotion.cpp
- llkeyframemotionparam.cpp
llkeyframestandmotion.cpp
llkeyframewalkmotion.cpp
llmotioncontroller.cpp
llmotion.cpp
llmultigesture.cpp
llpose.cpp
- llstatemachine.cpp
lltargetingmotion.cpp
llvisualparam.cpp
)
@@ -45,14 +43,12 @@ set(llcharacter_HEADER_FILES
lljointstate.h
llkeyframefallmotion.h
llkeyframemotion.h
- llkeyframemotionparam.h
llkeyframestandmotion.h
llkeyframewalkmotion.h
llmotion.h
llmotioncontroller.h
llmultigesture.h
llpose.h
- llstatemachine.h
lltargetingmotion.h
llvisualparam.h
)
diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp
deleted file mode 100644
index e4552b96c9..0000000000
--- a/indra/llcharacter/llkeyframemotionparam.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/**
- * @file llkeyframemotionparam.cpp
- * @brief Implementation of LLKeyframeMotion class.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-//-----------------------------------------------------------------------------
-// Header Files
-//-----------------------------------------------------------------------------
-#include "linden_common.h"
-
-#include "llkeyframemotionparam.h"
-#include "llcharacter.h"
-#include "llmath.h"
-#include "m3math.h"
-#include "lldir.h"
-#include "llanimationstates.h"
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam class
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam()
-// Class Constructor
-//-----------------------------------------------------------------------------
-LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
-{
- mDefaultKeyframeMotion = NULL;
- mCharacter = NULL;
-
- mEaseInDuration = 0.f;
- mEaseOutDuration = 0.f;
- mDuration = 0.f;
- mPriority = LLJoint::LOW_PRIORITY;
-}
-
-
-//-----------------------------------------------------------------------------
-// ~LLKeyframeMotionParam()
-// Class Destructor
-//-----------------------------------------------------------------------------
-LLKeyframeMotionParam::~LLKeyframeMotionParam()
-{
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- delete paramMotion.mMotion;
- }
- motionList.clear();
- }
- mParameterizedMotions.clear();
-}
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::onInitialize(LLCharacter *character)
-//-----------------------------------------------------------------------------
-LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
-{
- mCharacter = character;
-
- if (!loadMotions())
- {
- return STATUS_FAILURE;
- }
-
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- LLMotion* motion = paramMotion.mMotion;
- motion->onInitialize(character);
-
- if (motion->getDuration() > mEaseInDuration)
- {
- mEaseInDuration = motion->getEaseInDuration();
- }
-
- if (motion->getEaseOutDuration() > mEaseOutDuration)
- {
- mEaseOutDuration = motion->getEaseOutDuration();
- }
-
- if (motion->getDuration() > mDuration)
- {
- mDuration = motion->getDuration();
- }
-
- if (motion->getPriority() > mPriority)
- {
- mPriority = motion->getPriority();
- }
-
- LLPose *pose = motion->getPose();
-
- mPoseBlender.addMotion(motion);
- for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
- {
- LLPose *blendedPose = mPoseBlender.getBlendedPose();
- blendedPose->addJointState(jsp);
- }
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::onActivate()
-//-----------------------------------------------------------------------------
-bool LLKeyframeMotionParam::onActivate()
-{
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- paramMotion.mMotion->activate(mActivationTimestamp);
- }
- }
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::onUpdate()
-//-----------------------------------------------------------------------------
-bool LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
-{
- LL_PROFILE_ZONE_SCOPED;
- F32 weightFactor = 1.f / (F32)mParameterizedMotions.size();
-
- // zero out all pose weights
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
-// LL_INFOS() << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << LL_ENDL;
- paramMotion.mMotion->getPose()->setWeight(0.f);
- }
- }
-
-
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- const std::string& paramName = motion_pair.first;
- F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName);
- if (NULL == paramValue) // unexpected, but...
- {
- LL_WARNS() << "paramValue == NULL" << LL_ENDL;
- continue;
- }
-
- // DANGER! Do not modify mParameterizedMotions while using these pointers!
- const ParameterizedMotion* firstMotion = NULL;
- const ParameterizedMotion* secondMotion = NULL;
-
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- paramMotion.mMotion->onUpdate(time, joint_mask);
-
- F32 distToParam = paramMotion.mParam - *paramValue;
-
- if ( distToParam <= 0.f)
- {
- // keep track of the motion closest to the parameter value
- firstMotion = &paramMotion;
- }
- else
- {
- // we've passed the parameter value
- // so store the first motion we find as the second one we want to blend...
- if (firstMotion && !secondMotion )
- {
- secondMotion = &paramMotion;
- }
- //...or, if we've seen no other motion so far, make sure we blend to this only
- else if (!firstMotion)
- {
- firstMotion = &paramMotion;
- secondMotion = &paramMotion;
- }
- }
- }
-
- LLPose *firstPose;
- LLPose *secondPose;
-
- if (firstMotion)
- firstPose = firstMotion->mMotion->getPose();
- else
- firstPose = NULL;
-
- if (secondMotion)
- secondPose = secondMotion->mMotion->getPose();
- else
- secondPose = NULL;
-
- // now modify weight of the subanim (only if we are blending between two motions)
- if (firstMotion && secondMotion)
- {
- if (firstMotion == secondMotion)
- {
- firstPose->setWeight(weightFactor);
- }
- else if (firstMotion->mParam == secondMotion->mParam)
- {
- firstPose->setWeight(0.5f * weightFactor);
- secondPose->setWeight(0.5f * weightFactor);
- }
- else
- {
- F32 first_weight = 1.f -
- ((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) /
- (secondMotion->mParam - firstMotion->mParam));
- first_weight = llclamp(first_weight, 0.f, 1.f);
-
- F32 second_weight = 1.f - first_weight;
-
- firstPose->setWeight(first_weight * weightFactor);
- secondPose->setWeight(second_weight * weightFactor);
-
-// LL_INFOS() << "Parameter " << *paramName << ": " << *paramValue << LL_ENDL;
-// LL_INFOS() << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << LL_ENDL;
- }
- }
- else if (firstMotion && !secondMotion)
- {
- firstPose->setWeight(weightFactor);
- }
- }
-
- // blend poses
- mPoseBlender.blendAndApply();
-
- LL_INFOS() << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << LL_ENDL;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::onDeactivate()
-//-----------------------------------------------------------------------------
-void LLKeyframeMotionParam::onDeactivate()
-{
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- paramMotion.mMotion->onDeactivate();
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::addKeyframeMotion()
-//-----------------------------------------------------------------------------
-bool LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
-{
- LLMotion *newMotion = mCharacter->createMotion( id );
-
- if (!newMotion)
- {
- return false;
- }
-
- newMotion->setName(name);
-
- // now add motion to this list
- mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value));
-
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// LLKeyframeMotionParam::setDefaultKeyframeMotion()
-//-----------------------------------------------------------------------------
-void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
-{
- for (motion_map_t::value_type& motion_pair : mParameterizedMotions)
- {
- motion_list_t& motionList = motion_pair.second;
- for (const ParameterizedMotion& paramMotion : motionList)
- {
- if (paramMotion.mMotion->getName() == name)
- {
- mDefaultKeyframeMotion = paramMotion.mMotion;
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// loadMotions()
-//-----------------------------------------------------------------------------
-bool LLKeyframeMotionParam::loadMotions()
-{
- //-------------------------------------------------------------------------
- // Load named file by concatenating the character prefix with the motion name.
- // Load data into a buffer to be parsed.
- //-------------------------------------------------------------------------
- //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
- // + "_" + getName() + ".llp";
- //RN: deprecated unused reference to "motion" directory
- std::string path;
-
-
- //-------------------------------------------------------------------------
- // open the file
- //-------------------------------------------------------------------------
- S32 fileSize = 0;
- LLAPRFile infile ;
- infile.open(path, LL_APR_R, NULL, &fileSize);
- apr_file_t* fp = infile.getFileHandle() ;
- if (!fp || fileSize == 0)
- {
- LL_INFOS() << "ERROR: can't open: " << path << LL_ENDL;
- return false;
- }
-
- // allocate a text buffer
- std::vector<char> text(fileSize+1);
-
- //-------------------------------------------------------------------------
- // load data from file into buffer
- //-------------------------------------------------------------------------
- bool error = false;
- char *p = &text[0];
- while ( 1 )
- {
- if (apr_file_eof(fp) == APR_EOF)
- {
- break;
- }
- if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
- {
- error = true;
- break;
- }
- while ( *(++p) )
- ;
- }
-
- //-------------------------------------------------------------------------
- // close the file
- //-------------------------------------------------------------------------
- infile.close();
-
- //-------------------------------------------------------------------------
- // check for error
- //-------------------------------------------------------------------------
- llassert( p <= (&text[0] + fileSize) );
-
- if ( error )
- {
- LL_INFOS() << "ERROR: error while reading from " << path << LL_ENDL;
- return false;
- }
-
- LL_INFOS() << "Loading parametric keyframe data for: " << getName() << LL_ENDL;
-
- //-------------------------------------------------------------------------
- // parse the text and build keyframe data structures
- //-------------------------------------------------------------------------
- p = &text[0];
- S32 num;
- char strA[80]; /* Flawfinder: ignore */
- char strB[80]; /* Flawfinder: ignore */
- F32 floatA = 0.0f;
-
-
- //-------------------------------------------------------------------------
- // get priority
- //-------------------------------------------------------------------------
- bool isFirstMotion = true;
- num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
-
- while(1)
- {
- if (num == 0 || num == EOF) break;
- if ((num != 3))
- {
- LL_INFOS() << "WARNING: can't read parametric motion" << LL_ENDL;
- return false;
- }
-
- addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA);
- if (isFirstMotion)
- {
- isFirstMotion = false;
- setDefaultKeyframeMotion(strA);
- }
-
- p = strstr(p, "\n");
- if (!p)
- {
- break;
- }
-
- p++;
- num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
- }
-
- return true;
-}
-
-// End
diff --git a/indra/llcharacter/llkeyframemotionparam.h b/indra/llcharacter/llkeyframemotionparam.h
deleted file mode 100644
index 8c57766e9b..0000000000
--- a/indra/llcharacter/llkeyframemotionparam.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * @file llkeyframemotionparam.h
- * @brief Implementation of LLKeframeMotionParam class.
- *
- * $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$
- */
-
-#ifndef LL_LLKEYFRAMEMOTIONPARAM_H
-#define LL_LLKEYFRAMEMOTIONPARAM_H
-
-//-----------------------------------------------------------------------------
-// Header files
-//-----------------------------------------------------------------------------
-
-#include <string>
-
-#include "llmotion.h"
-#include "lljointstate.h"
-#include "v3math.h"
-#include "llquaternion.h"
-#include "llkeyframemotion.h"
-
-//-----------------------------------------------------------------------------
-// class LLKeyframeMotionParam
-//-----------------------------------------------------------------------------
-class LLKeyframeMotionParam :
- public LLMotion
-{
-public:
- // Constructor
- LLKeyframeMotionParam(const LLUUID &id);
-
- // Destructor
- virtual ~LLKeyframeMotionParam();
-
-public:
- //-------------------------------------------------------------------------
- // functions to support MotionController and MotionRegistry
- //-------------------------------------------------------------------------
-
- // static constructor
- // all subclasses must implement such a function and register it
- static LLMotion *create(const LLUUID &id) { return new LLKeyframeMotionParam(id); }
-
-public:
- //-------------------------------------------------------------------------
- // animation callbacks to be implemented by subclasses
- //-------------------------------------------------------------------------
-
- // motions must specify whether or not they loop
- virtual bool getLoop() {
- return true;
- }
-
- // motions must report their total duration
- virtual F32 getDuration() {
- return mDuration;
- }
-
- // motions must report their "ease in" duration
- virtual F32 getEaseInDuration() {
- return mEaseInDuration;
- }
-
- // motions must report their "ease out" duration.
- virtual F32 getEaseOutDuration() {
- return mEaseOutDuration;
- }
-
- // motions must report their priority
- virtual LLJoint::JointPriority getPriority() {
- return mPriority;
- }
-
- virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
-
- // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
- virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_KEYFRAME; }
-
- // run-time (post constructor) initialization,
- // called after parameters have been set
- // must return true to indicate success and be available for activation
- virtual LLMotionInitStatus onInitialize(LLCharacter *character);
-
- // called when a motion is activated
- // must return true to indicate success, or else
- // it will be deactivated
- virtual bool onActivate();
-
- // called per time step
- // must return true while it is active, and
- // must return false when the motion is completed.
- virtual bool onUpdate(F32 time, U8* joint_mask);
-
- // called when a motion is deactivated
- virtual void onDeactivate();
-
- virtual LLPose* getPose() { return mPoseBlender.getBlendedPose();}
-
-protected:
- //-------------------------------------------------------------------------
- // new functions defined by this subclass
- //-------------------------------------------------------------------------
- struct ParameterizedMotion
- {
- ParameterizedMotion(LLMotion* motion, F32 param) : mMotion(motion), mParam(param) {}
- LLMotion* mMotion;
- F32 mParam;
- };
-
- // add a motion and associated parameter triplet
- bool addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value);
-
- // set default motion for LOD and retrieving blend constants
- void setDefaultKeyframeMotion(char *);
-
- bool loadMotions();
-
-protected:
- //-------------------------------------------------------------------------
- // Member Data
- //-------------------------------------------------------------------------
-
- struct compare_motions
- {
- bool operator() (const ParameterizedMotion& a, const ParameterizedMotion& b) const
- {
- if (a.mParam != b.mParam)
- return (a.mParam < b.mParam);
- else
- return a.mMotion < b.mMotion;
- }
- };
-
- typedef std::set < ParameterizedMotion, compare_motions > motion_list_t;
- typedef std::map <std::string, motion_list_t > motion_map_t;
- motion_map_t mParameterizedMotions;
- LLMotion* mDefaultKeyframeMotion;
- LLCharacter* mCharacter;
- LLPoseBlender mPoseBlender;
-
- F32 mEaseInDuration;
- F32 mEaseOutDuration;
- F32 mDuration;
- LLJoint::JointPriority mPriority;
-
- LLUUID mTransactionID;
-};
-
-#endif // LL_LLKEYFRAMEMOTIONPARAM_H
diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h
index 0c262bf24a..c2cb174821 100644
--- a/indra/llcharacter/llmotioncontroller.h
+++ b/indra/llcharacter/llmotioncontroller.h
@@ -37,7 +37,6 @@
#include "llmotion.h"
#include "llpose.h"
#include "llframetimer.h"
-#include "llstatemachine.h"
#include "llstring.h"
//-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp
deleted file mode 100644
index 38e9ef444c..0000000000
--- a/indra/llcharacter/llstatemachine.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/**
- * @file llstatemachine.cpp
- * @brief LLStateMachine implementation file.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llstatemachine.h"
-#include "llapr.h"
-
-#define FSM_PRINT_STATE_TRANSITIONS (0)
-
-U32 LLUniqueID::sNextID = 0;
-
-bool operator==(const LLUniqueID &a, const LLUniqueID &b)
-{
- return (a.mId == b.mId);
-}
-
-bool operator!=(const LLUniqueID &a, const LLUniqueID &b)
-{
- return (a.mId != b.mId);
-}
-
-//-----------------------------------------------------------------------------
-// LLStateDiagram
-//-----------------------------------------------------------------------------
-LLStateDiagram::LLStateDiagram()
-{
- mDefaultState = NULL;
- mUseDefaultState = false;
-}
-
-LLStateDiagram::~LLStateDiagram()
-{
-
-}
-
-// add a state to the state graph
-bool LLStateDiagram::addState(LLFSMState *state)
-{
- mStates[state] = Transitions();
- return true;
-}
-
-// add a directed transition between 2 states
-bool LLStateDiagram::addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition)
-{
- StateMap::iterator state_it;
- state_it = mStates.find(&start_state);
- Transitions* state_transitions = NULL;
- if (state_it == mStates.end() )
- {
- addState(&start_state);
- state_transitions = &mStates[&start_state];
- }
- else
- {
- state_transitions = &state_it->second;
- }
- state_it = mStates.find(&end_state);
- if (state_it == mStates.end() )
- {
- addState(&end_state);
- }
-
- Transitions::iterator transition_it = state_transitions->find(&transition);
- if (transition_it != state_transitions->end())
- {
- LL_ERRS() << "LLStateTable::addDirectedTransition() : transition already exists" << LL_ENDL;
- return false; // transition already exists
- }
-
- (*state_transitions)[&transition] = &end_state;
- return true;
-}
-
-// add an undirected transition between 2 states
-bool LLStateDiagram::addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition)
-{
- bool result;
- result = addTransition(start_state, end_state, transition);
- if (result)
- {
- result = addTransition(end_state, start_state, transition);
- }
- return result;
-}
-
-// add a transition that exists for every state
-void LLStateDiagram::addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition)
-{
- mDefaultTransitions[&transition] = &end_state;
-}
-
-// process a possible transition, and get the resulting state
-LLFSMState* LLStateDiagram::processTransition(LLFSMState& start_state, LLFSMTransition& transition)
-{
- // look up transition
- //LLFSMState** dest_state = (mStates.getValue(&start_state))->getValue(&transition);
- LLFSMState* dest_state = NULL;
- StateMap::iterator state_it = mStates.find(&start_state);
- if (state_it == mStates.end())
- {
- return NULL;
- }
- Transitions::iterator transition_it = state_it->second.find(&transition);
-
- // try default transitions if state-specific transition not found
- if (transition_it == state_it->second.end())
- {
- dest_state = mDefaultTransitions[&transition];
- }
- else
- {
- dest_state = transition_it->second;
- }
-
- // if we have a destination state...
- if (NULL != dest_state)
- {
- // ...return it...
- return dest_state;
- }
- // ... otherwise ...
- else
- {
- // ...look for default state...
- if (mUseDefaultState)
- {
- // ...return it if we have it...
- return mDefaultState;
- }
- else
- {
- // ...or else we're still in the same state.
- return &start_state;
- }
- }
-}
-
-void LLStateDiagram::setDefaultState(LLFSMState& default_state)
-{
- mUseDefaultState = true;
- mDefaultState = &default_state;
-}
-
-S32 LLStateDiagram::numDeadendStates()
-{
- S32 numDeadends = 0;
- for (StateMap::value_type& state_pair : mStates)
- {
- if (state_pair.second.size() == 0)
- {
- numDeadends++;
- }
- }
- return numDeadends;
-}
-
-bool LLStateDiagram::stateIsValid(LLFSMState& state)
-{
- if (mStates.find(&state) != mStates.end())
- {
- return true;
- }
- return false;
-}
-
-LLFSMState* LLStateDiagram::getState(U32 state_id)
-{
- for (StateMap::value_type& state_pair : mStates)
- {
- if (state_pair.first->getID() == state_id)
- {
- return state_pair.first;
- }
- }
- return NULL;
-}
-
-bool LLStateDiagram::saveDotFile(const std::string& filename)
-{
- LLAPRFile outfile ;
- outfile.open(filename, LL_APR_W);
- apr_file_t* dot_file = outfile.getFileHandle() ;
-
- if (!dot_file)
- {
- LL_WARNS() << "LLStateDiagram::saveDotFile() : Couldn't open " << filename << " to save state diagram." << LL_ENDL;
- return false;
- }
- apr_file_printf(dot_file, "digraph StateMachine {\n\tsize=\"100,100\";\n\tfontsize=40;\n\tlabel=\"Finite State Machine\";\n\torientation=landscape\n\tratio=.77\n");
-
- for (StateMap::value_type& state_pair : mStates)
- {
- apr_file_printf(dot_file, "\t\"%s\" [fontsize=28,shape=box]\n", state_pair.first->getName().c_str());
- }
- apr_file_printf(dot_file, "\t\"All States\" [fontsize=30,style=bold,shape=box]\n");
-
- for (Transitions::value_type& transition_pair : mDefaultTransitions)
- {
- apr_file_printf(dot_file, "\t\"All States\" -> \"%s\" [label = \"%s\",fontsize=24];\n", transition_pair.second->getName().c_str(),
- transition_pair.second->getName().c_str());
- }
-
- if (mDefaultState)
- {
- apr_file_printf(dot_file, "\t\"All States\" -> \"%s\";\n", mDefaultState->getName().c_str());
- }
-
-
- for (StateMap::value_type& state_pair : mStates)
- {
- LLFSMState *state = state_pair.first;
-
- for (Transitions::value_type& transition_pair : state_pair.second)
- {
- std::string state_name = state->getName();
- std::string target_name = transition_pair.second->getName();
- std::string transition_name = transition_pair.first->getName();
- apr_file_printf(dot_file, "\t\"%s\" -> \"%s\" [label = \"%s\",fontsize=24];\n", state->getName().c_str(),
- target_name.c_str(),
- transition_name.c_str());
- }
- }
-
- apr_file_printf(dot_file, "}\n");
-
- return true;
-}
-
-std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM)
-{
- if (FSM.mDefaultState)
- {
- s << "Default State: " << FSM.mDefaultState->getName() << "\n";
- }
-
- for (LLStateDiagram::Transitions::value_type& transition_pair : FSM.mDefaultTransitions)
- {
- s << "Any State -- " << transition_pair.first->getName()
- << " --> " << transition_pair.second->getName() << "\n";
- }
-
- for (LLStateDiagram::StateMap::value_type& state_pair : FSM.mStates)
- {
- for (LLStateDiagram::Transitions::value_type& transition_pair : state_pair.second)
- {
- s << state_pair.first->getName() << " -- " << transition_pair.first->getName()
- << " --> " << transition_pair.second->getName() << "\n";
- }
- s << "\n";
- }
-
- return s;
-}
-
-//-----------------------------------------------------------------------------
-// LLStateMachine
-//-----------------------------------------------------------------------------
-
-LLStateMachine::LLStateMachine()
-{
- // we haven't received a starting state yet
- mCurrentState = NULL;
- mLastState = NULL;
- mLastTransition = NULL;
- mStateDiagram = NULL;
-}
-
-LLStateMachine::~LLStateMachine()
-{
-
-}
-
-// returns current state
-LLFSMState* LLStateMachine::getCurrentState() const
-{
- return mCurrentState;
-}
-
-// executes current state
-void LLStateMachine::runCurrentState(void *data)
-{
- mCurrentState->execute(data);
-}
-
-// set current state
-bool LLStateMachine::setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry)
-{
- llassert(mStateDiagram);
-
- if (mStateDiagram->stateIsValid(*initial_state))
- {
- mLastState = mCurrentState = initial_state;
- if (!skip_entry)
- {
- initial_state->onEntry(user_data);
- }
- return true;
- }
-
- return false;
-}
-
-bool LLStateMachine::setCurrentState(U32 state_id, void* user_data, bool skip_entry)
-{
- llassert(mStateDiagram);
-
- LLFSMState* state = mStateDiagram->getState(state_id);
-
- if (state)
- {
- mLastState = mCurrentState = state;
- if (!skip_entry)
- {
- state->onEntry(user_data);
- }
- return true;
- }
-
- return false;
-}
-
-void LLStateMachine::processTransition(LLFSMTransition& transition, void* user_data)
-{
- llassert(mStateDiagram);
-
- if (NULL == mCurrentState)
- {
- LL_WARNS() << "mCurrentState == NULL; aborting processTransition()" << LL_ENDL;
- return;
- }
-
- LLFSMState* new_state = mStateDiagram->processTransition(*mCurrentState, transition);
-
- if (NULL == new_state)
- {
- LL_WARNS() << "new_state == NULL; aborting processTransition()" << LL_ENDL;
- return;
- }
-
- mLastTransition = &transition;
- mLastState = mCurrentState;
-
- if (*mCurrentState != *new_state)
- {
- mCurrentState->onExit(user_data);
- mCurrentState = new_state;
- mCurrentState->onEntry(user_data);
-#if FSM_PRINT_STATE_TRANSITIONS
- LL_INFOS() << "Entering state " << mCurrentState->getName() <<
- " on transition " << transition.getName() << " from state " <<
- mLastState->getName() << LL_ENDL;
-#endif
- }
-}
-
-void LLStateMachine::setStateDiagram(LLStateDiagram* diagram)
-{
- mStateDiagram = diagram;
-}
diff --git a/indra/llcharacter/llstatemachine.h b/indra/llcharacter/llstatemachine.h
deleted file mode 100644
index 9a33798d96..0000000000
--- a/indra/llcharacter/llstatemachine.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * @file llstatemachine.h
- * @brief LLStateMachine class header file.
- *
- * $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_LLSTATEMACHINE_H
-#define LL_LLSTATEMACHINE_H
-
-#include <string>
-
-#include "llerror.h"
-#include <map>
-
-class LLUniqueID
-{
- friend bool operator==(const LLUniqueID &a, const LLUniqueID &b);
- friend bool operator!=(const LLUniqueID &a, const LLUniqueID &b);
-protected:
- static U32 sNextID;
- U32 mId;
-public:
- LLUniqueID(){mId = sNextID++;}
- virtual ~LLUniqueID(){}
- U32 getID() {return mId;}
-};
-
-class LLFSMTransition : public LLUniqueID
-{
-public:
- LLFSMTransition() : LLUniqueID(){};
- virtual std::string getName()const { return "unnamed"; }
-};
-
-class LLFSMState : public LLUniqueID
-{
-public:
- LLFSMState() : LLUniqueID(){};
- virtual void onEntry(void *){};
- virtual void onExit(void *){};
- virtual void execute(void *){};
- virtual std::string getName() const { return "unnamed"; }
-};
-
-class LLStateDiagram
-{
-typedef std::map<LLFSMTransition*, LLFSMState*> Transitions;
-
-friend std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM);
-friend class LLStateMachine;
-
-protected:
- typedef std::map<LLFSMState*, Transitions> StateMap;
- StateMap mStates;
- Transitions mDefaultTransitions;
- LLFSMState* mDefaultState;
- bool mUseDefaultState;
-
-public:
- LLStateDiagram();
- virtual ~LLStateDiagram();
-
-protected:
- // add a state to the state graph, executed implicitly when adding transitions
- bool addState(LLFSMState *state);
-
- // add a directed transition between 2 states
- bool addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition);
-
- // add an undirected transition between 2 states
- bool addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition);
-
- // add a transition that is taken if none other exist
- void addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition);
-
- // process a possible transition, and get the resulting state
- LLFSMState* processTransition(LLFSMState& start_state, LLFSMTransition& transition);
-
- // add a transition that exists for every state
- void setDefaultState(LLFSMState& default_state);
-
- // return total number of states with no outgoing transitions
- S32 numDeadendStates();
-
- // does this state exist in the state diagram?
- bool stateIsValid(LLFSMState& state);
-
- // get a state pointer by ID
- LLFSMState* getState(U32 state_id);
-
-public:
- // save the graph in a DOT file for rendering and visualization
- bool saveDotFile(const std::string& filename);
-};
-
-class LLStateMachine
-{
-protected:
- LLFSMState* mCurrentState;
- LLFSMState* mLastState;
- LLFSMTransition* mLastTransition;
- LLStateDiagram* mStateDiagram;
-
-public:
- LLStateMachine();
- virtual ~LLStateMachine();
-
- // set state diagram
- void setStateDiagram(LLStateDiagram* diagram);
-
- // process this transition
- void processTransition(LLFSMTransition &transition, void* user_data);
-
- // returns current state
- LLFSMState* getCurrentState() const;
-
- // execute current state
- void runCurrentState(void *data);
-
- // set state by state pointer
- bool setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry = true);
-
- // set state by unique ID
- bool setCurrentState(U32 state_id, void* user_data, bool skip_entry = true);
-};
-
-#endif //_LL_LLSTATEMACHINE_H
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2bafef5d1e..1f7b3163c6 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -66,6 +66,7 @@ set(llcommon_SOURCE_FILES
llmetricperformancetester.cpp
llmortician.cpp
llmutex.cpp
+ llpointer.cpp
llptrto.cpp
llpredicate.cpp
llprocess.cpp
@@ -302,7 +303,7 @@ elseif ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
target_include_directories(llcommon PUBLIC ${prefix_result}/../include/sse2neon)
endif ()
-if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed))
+if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64))
target_include_directories(llcommon PUBLIC ${LIBS_PREBUILT_DIR}/include)
endif ()
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index a0394da281..404e0c71ce 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -163,6 +163,28 @@ constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
constexpr U8 SIM_ACCESS_DOWN = 254;
constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
+// map item types
+constexpr U32 MAP_ITEM_TELEHUB = 0x01;
+constexpr U32 MAP_ITEM_PG_EVENT = 0x02;
+constexpr U32 MAP_ITEM_MATURE_EVENT = 0x03;
+// constexpr U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW
+// constexpr U32 MAP_ITEM_AGENT_COUNT = 0x05;
+constexpr U32 MAP_ITEM_AGENT_LOCATIONS = 0x06;
+constexpr U32 MAP_ITEM_LAND_FOR_SALE = 0x07;
+constexpr U32 MAP_ITEM_CLASSIFIED = 0x08;
+constexpr U32 MAP_ITEM_ADULT_EVENT = 0x09;
+constexpr U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
+
+// Region map layer numbers
+constexpr S32 MAP_SIM_OBJECTS = 0;
+constexpr S32 MAP_SIM_TERRAIN = 1;
+constexpr S32 MAP_SIM_LAND_FOR_SALE = 2; // Transparent alpha overlay of land for sale
+constexpr S32 MAP_SIM_IMAGE_TYPES = 3; // Number of map layers
+constexpr S32 MAP_SIM_INFO_MASK = 0x00FFFFFF; // Agent access may be stuffed into upper byte
+constexpr S32 MAP_SIM_LAYER_MASK = 0x0000FFFF; // Layer info is in lower 16 bits
+constexpr S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000;
+constexpr S32 MAP_SIM_PRELUDE = 0x00020000;
+
// attachment constants
constexpr U8 ATTACHMENT_ADD = 0x80;
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index c532620daa..f92bb98ba6 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -93,6 +93,7 @@ bool LLApp::sDisableCrashlogger = false;
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
LLAppErrorHandler LLApp::sErrorHandler = NULL;
+bool gDisconnected = false;
LLApp::LLApp()
{
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 57f5a112d9..3a855bc480 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -50,6 +50,8 @@ void clear_signals();
#endif
+extern bool gDisconnected;
+
class LL_COMMON_API LLApp
{
public:
@@ -283,6 +285,7 @@ public:
#ifdef LL_WINDOWS
virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; }
+ virtual bool reportCustomToBugsplat(const std::string& description) { return false; }
#endif
public:
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 5205699b92..5545bb71af 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -41,6 +41,9 @@
#include "llstring.h"
#include "llfasttimer.h"
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
+
static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
// should be APR_USEC_PER_SEC, but that relies on INT64_C which
// isn't defined in glib under our build set up for some reason
@@ -64,7 +67,7 @@ std::string LLDate::asString() const
{
std::ostringstream stream;
toStream(stream);
- return stream.str();
+ return std::move(stream).str();
}
//@ brief Converts time in seconds since EPOCH
@@ -184,7 +187,7 @@ bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *se
bool LLDate::fromString(const std::string& iso8601_date)
{
- std::istringstream stream(iso8601_date);
+ boost::iostreams::stream<boost::iostreams::array_source> stream(iso8601_date.data(), iso8601_date.size());
return fromStream(stream);
}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index b14464382b..6f5e57c3de 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -480,7 +480,7 @@ namespace
}
- typedef std::map<std::string, LLError::ELevel> LevelMap;
+ typedef std::unordered_map<std::string, LLError::ELevel> LevelMap;
typedef std::vector<LLError::RecorderPtr> Recorders;
typedef std::vector<LLError::CallSite*> CallSiteVector;
@@ -501,7 +501,7 @@ namespace
LevelMap mClassLevelMap;
LevelMap mFileLevelMap;
LevelMap mTagLevelMap;
- std::map<std::string, unsigned int> mUniqueLogMessages;
+ std::unordered_map<std::string, unsigned int> mUniqueLogMessages;
LLError::FatalFunction mCrashFunction;
LLError::TimeFunction mTimeFunction;
@@ -1404,7 +1404,7 @@ namespace LLError
{
std::ostringstream message_stream;
- std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
+ auto messageIter = s->mUniqueLogMessages.find(message);
if (messageIter != s->mUniqueLogMessages.end())
{
messageIter->second++;
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index d254fa5407..3c58d1df22 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -70,7 +70,6 @@ namespace LLError
Setting a level means log messages at that level or above.
*/
- LL_COMMON_API void setPrintLocation(bool);
LL_COMMON_API void setDefaultLevel(LLError::ELevel);
LL_COMMON_API ELevel getDefaultLevel();
LL_COMMON_API void setAlwaysFlush(bool flush);
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index fde168b022..a3f8d02463 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -31,6 +31,9 @@
#include "lltrace.h"
#include "lltreeiterators.h"
#include "llprocessor.h"
+#if _M_ARM64
+#include "llmutex.h"
+#endif
#if LL_X86 || LL_X86_64
#if LL_WINDOWS
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index a539e4fe28..f752e31563 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -187,13 +187,34 @@ static unsigned short get_fileattr(const std::wstring& utf16path, bool dontFollo
CloseHandle(file_handle);
return st_mode;
}
+ // Retrieve last error before calling CloseHandle()
+ DWORD last_error = GetLastError();
+ CloseHandle(file_handle);
+ set_errno_from_oserror(last_error);
+ }
+ else
+ {
+ set_errno_from_oserror(GetLastError());
}
- // Retrieve last error and set errno before calling CloseHandle()
- set_errno_from_oserror(GetLastError());
- if (file_handle != INVALID_HANDLE_VALUE)
+ // If CreateFileW approach failed (e.g., exFAT), try the simpler GetFileAttributesW()
+ // GetFileAttributesW() always follows symlinks, so we skip this fallback when dontFollowSymLink is true.
+ if (!dontFollowSymLink)
{
- CloseHandle(file_handle);
+ DWORD attributes = GetFileAttributesW(utf16path.c_str());
+ if (attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ bool is_directory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ unsigned short st_mode = is_directory ? S_IFDIR : S_IFREG;
+ st_mode |= (attributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE;
+
+ // propagate user bits to group/other fields:
+ st_mode |= (st_mode & 0700) >> 3;
+ st_mode |= (st_mode & 0700) >> 6;
+
+ return st_mode;
+ }
+ set_errno_from_oserror(GetLastError());
}
return 0;
}
diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp
index 823bea7a3c..03dd7856b6 100644
--- a/indra/llcommon/llheteromap.cpp
+++ b/indra/llcommon/llheteromap.cpp
@@ -27,6 +27,6 @@ LLHeteroMap::~LLHeteroMap()
// pair.second is the std::pair; pair.second.first is the void*;
// pair.second.second points to the deleter function
(pair.second.second)(pair.second.first);
- pair.second.first = NULL;
+ pair.second.first = nullptr;
}
}
diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h
index d8e6fefb17..211dfaae83 100644
--- a/indra/llcommon/llheteromap.h
+++ b/indra/llcommon/llheteromap.h
@@ -12,9 +12,10 @@
#if ! defined(LL_LLHETEROMAP_H)
#define LL_LLHETEROMAP_H
+#include <typeindex>
#include <typeinfo>
#include <utility> // std::pair
-#include <map>
+#include <unordered_map>
/**
* LLHeteroMap addresses an odd requirement. Usually when you want to put
@@ -43,7 +44,7 @@ public:
// Look up map entry by typeid(T). We don't simply use mMap[typeid(T)]
// because that requires default-constructing T on every lookup. For
// some kinds of T, that could be expensive.
- TypeMap::iterator found = mMap.find(&typeid(T));
+ TypeMap::iterator found = mMap.find(typeid(T));
if (found == mMap.end())
{
// Didn't find typeid(T). Create an entry. Because we're storing
@@ -52,8 +53,8 @@ public:
void* ptr = new T();
void (*dlfn)(void*) = &deleter<T>;
std::pair<TypeMap::iterator, bool> inserted =
- mMap.insert(TypeMap::value_type(&typeid(T),
- TypeMap::mapped_type(ptr, dlfn)));
+ mMap.emplace(typeid(T),
+ TypeMap::mapped_type(ptr, dlfn));
// Okay, now that we have an entry, claim we found it.
found = inserted.first;
}
@@ -71,23 +72,9 @@ private:
delete static_cast<T*>(p);
}
- // Comparing two std::type_info* values is tricky, because the standard
- // does not guarantee that there will be only one type_info instance for a
- // given type. In other words, &typeid(A) in one part of the program may
- // not always equal &typeid(A) in some other part. Use special comparator.
- struct type_info_ptr_comp
- {
- bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
- {
- return lhs->before(*rhs);
- }
- };
-
- // What we actually store is a map from std::type_info (permitting lookup
+ // What we actually store is a map from std::type_index (permitting lookup
// by object type) to a void* pointer to the object PLUS its deleter.
- typedef std::map<
- const std::type_info*, std::pair<void*, void (*)(void*)>,
- type_info_ptr_comp>
+ typedef std::unordered_map<std::type_index, std::pair<void*, void (*)(void*)>>
TypeMap;
TypeMap mMap;
};
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index b01ea0bfb1..b220afadfc 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -34,7 +34,6 @@
#include <list>
#include <unordered_map>
#include <boost/function.hpp>
-#include <boost/unordered_map.hpp>
#include "llerror.h"
#include "llstl.h"
@@ -267,7 +266,7 @@ namespace LLInitParam
private:
struct Inaccessable{};
public:
- typedef std::map<std::string, T> value_name_map_t;
+ typedef std::unordered_map<std::string, T> value_name_map_t;
typedef Inaccessable name_t;
typedef TypeValues<T> type_value_t;
typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
@@ -294,7 +293,7 @@ namespace LLInitParam
static std::vector<std::string>* getPossibleValues()
{
- return NULL;
+ return nullptr;
}
void assignNamedValue(const Inaccessable& name)
@@ -310,7 +309,7 @@ namespace LLInitParam
return param_value_t::getValue();
}
- static value_name_map_t* getValueNames() {return NULL;}
+ static value_name_map_t* getValueNames() { return nullptr; }
};
// helper class to implement name value lookups
@@ -321,7 +320,7 @@ namespace LLInitParam
{
typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;
public:
- typedef typename std::map<std::string, T> value_name_map_t;
+ typedef typename std::unordered_map<std::string, T> value_name_map_t;
typedef std::string name_t;
typedef self_t type_value_t;
typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
@@ -497,9 +496,9 @@ namespace LLInitParam
typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
typedef std::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
- typedef std::map<const std::type_info*, parser_read_func_t> parser_read_func_map_t;
- typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t;
- typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t;
+ typedef std::unordered_map<std::type_index, parser_read_func_t> parser_read_func_map_t;
+ typedef std::unordered_map<std::type_index, parser_write_func_t> parser_write_func_map_t;
+ typedef std::unordered_map<std::type_index, parser_inspect_func_t> parser_inspect_func_map_t;
public:
@@ -514,7 +513,7 @@ namespace LLInitParam
template <typename T> bool readValue(T& param, typename std::enable_if_t<!std::is_enum_v<T>>* dummy = 0)
{
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(typeid(T));
if (found_it != mParserReadFuncs->end())
{
return found_it->second(*this, (void*)&param);
@@ -525,14 +524,14 @@ namespace LLInitParam
template <typename T> bool readValue(T& param, typename std::enable_if_t<std::is_enum_v<T> >* dummy = 0)
{
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(typeid(T));
if (found_it != mParserReadFuncs->end())
{
return found_it->second(*this, (void*)&param);
}
else
{
- found_it = mParserReadFuncs->find(&typeid(S32));
+ found_it = mParserReadFuncs->find(typeid(S32));
if (found_it != mParserReadFuncs->end())
{
S32 int_value;
@@ -546,7 +545,7 @@ namespace LLInitParam
template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
{
- parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+ parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(typeid(T));
if (found_it != mParserWriteFuncs->end())
{
return found_it->second(*this, (const void*)&param, name_stack);
@@ -557,7 +556,7 @@ namespace LLInitParam
// dispatch inspection to registered inspection functions, for each parameter in a param block
template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
{
- parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+ parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(typeid(T));
if (found_it != mParserInspectFuncs->end())
{
found_it->second(name_stack, min_count, max_count, possible_values);
@@ -574,16 +573,16 @@ namespace LLInitParam
protected:
template <typename T>
- void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
+ void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = nullptr)
{
- mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
- mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
+ mParserReadFuncs->emplace(typeid(T), read_func);
+ mParserWriteFuncs->emplace(typeid(T), write_func);
}
template <typename T>
void registerInspectFunc(parser_inspect_func_t inspect_func)
{
- mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
+ mParserInspectFuncs->emplace(typeid(T), inspect_func);
}
bool mParseSilently;
@@ -614,7 +613,7 @@ namespace LLInitParam
{
struct UserData
{
- virtual ~UserData() {}
+ virtual ~UserData() = default;
};
typedef bool(*merge_func_t)(Param&, const Param&, bool);
@@ -665,7 +664,7 @@ namespace LLInitParam
void aggregateBlockData(BlockDescriptor& src_block_data);
void addParam(ParamDescriptorPtr param, const char* name);
- typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t;
+ typedef std::unordered_map<std::string, ParamDescriptorPtr, ll::string_hash, std::equal_to<>> 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;
@@ -679,38 +678,26 @@ namespace LLInitParam
class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
};
- //TODO: implement in terms of owned_ptr
- template<typename T>
+ // TODO: implement in terms of owned_ptr
+ template<typename T>
class LazyValue
- {
- public:
- LazyValue()
- : mPtr(NULL)
- {}
+ {
+ public:
+ LazyValue() = default;
- ~LazyValue()
- {
- delete mPtr;
- }
+ ~LazyValue() { delete mPtr; }
- LazyValue(const T& value)
- {
- mPtr = new T(value);
- }
+ LazyValue(const T& value) { mPtr = new T(value); }
- LazyValue(const LazyValue& other)
- : mPtr(NULL)
- {
- *this = other;
- }
+ LazyValue(const LazyValue& other) : mPtr(nullptr) { *this = other; }
- LazyValue& operator = (const LazyValue& other)
- {
+ LazyValue& operator=(const LazyValue& other)
+ {
if (!other.mPtr)
{
delete mPtr;
- mPtr = NULL;
- }
+ mPtr = nullptr;
+ }
else
{
if (!mPtr)
@@ -721,23 +708,21 @@ namespace LLInitParam
{
*mPtr = *(other.mPtr);
}
- }
- return *this;
}
+ return *this;
+ }
bool operator==(const LazyValue& other) const
{
- if (empty() || other.empty()) return false;
+ if (empty() || other.empty())
+ return false;
return *mPtr == *other.mPtr;
}
- bool empty() const
- {
- return mPtr == NULL;
- }
+ bool empty() const { return mPtr == nullptr; }
- void set(const T& other)
- {
+ void set(const T& other)
+ {
if (!mPtr)
{
mPtr = new T(other);
@@ -748,36 +733,26 @@ namespace LLInitParam
}
}
- const T& get() const
- {
- return *ensureInstance();
- }
+ const T& get() const { return *ensureInstance(); }
- T& get()
- {
- return *ensureInstance();
- }
+ T& get() { return *ensureInstance(); }
- operator const T&() const
- {
- return get();
- }
+ operator const T&() const { return get(); }
- private:
- // lazily allocate an instance of T
- T* ensureInstance() const
+ private:
+ // lazily allocate an instance of T
+ T* ensureInstance() const
+ {
+ if (mPtr == nullptr)
{
- if (mPtr == NULL)
- {
- mPtr = new T();
- }
- return mPtr;
+ mPtr = new T();
}
+ return mPtr;
+ }
- private:
-
- mutable T* mPtr;
- };
+ private:
+ mutable T* mPtr = nullptr;
+ };
// root class of all parameter blocks
@@ -864,7 +839,7 @@ namespace LLInitParam
mParamProvided(false)
{}
- virtual ~BaseBlock() {}
+ virtual ~BaseBlock() = default;
bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
param_handle_t getHandleFromParam(const Param* param) const;
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index ba48319a16..4e44b9a56a 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2026, 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
@@ -52,6 +52,9 @@
//static
+// On windows commit charge information is vital for OOM diagnosis.
+U32Megabytes LLMemory::sAvailCommitMemInMB(U32_MAX);
+
// most important memory metric for texture streaming
// On Windows, this should agree with resource monitor -> performance -> memory -> available
// On OS X, this should be activity monitor -> memory -> (physical memory - memory used)
@@ -70,6 +73,12 @@ U32Kilobytes LLMemory::sAllocatedMemInKB(0);
U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
+LLFrameTimer LLMemory::sMemoryCheckTimer;
+F32 LLMemory::sSysMemoryFactor = 1.f;
+U32 LLMemory::sFactorLastFrameCount = 0;
+
+static const S32Megabytes MEM_LOW_THRESHOLD = S32Megabytes(256);
+
static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");
@@ -102,23 +111,14 @@ void LLMemory::updateMemoryInfo()
{
LL_PROFILE_ZONE_SCOPED;
+ sMemoryCheckTimer.reset();
sMaxPhysicalMemInKB = gSysMemory.getPhysicalMemoryKB();
- U32Kilobytes avail_mem;
- LLMemoryInfo::getAvailableMemoryKB(avail_mem);
- sAvailPhysicalMemInKB = avail_mem;
+ LLMemoryInfo::updateAvailableMemory();
#if LL_WINDOWS
- PROCESS_MEMORY_COUNTERS counters;
-
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
- {
- LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
- return ;
- }
-
- sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
- sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
+ // On windows updateAvailableMemory fills sAvailPhysicalMemInKB,
+ //sAllocatedMemInKB and sAllocatedPageSizeInKB
sample(sVirtualMem, sAllocatedPageSizeInKB);
#elif defined(LL_DARWIN)
@@ -201,6 +201,97 @@ void LLMemory::logMemoryInfo(bool update)
LL_INFOS() << llformat("Current max usable memory: %.2f MB", sMaxPhysicalMemInKB / 1024.0) << LL_ENDL;
}
+void LLMemory::updateFreeSystemMemory()
+{
+ if (sMemoryCheckTimer.getElapsedTimeF32() >= 1.f) //once per second.
+ {
+ LLMemory::updateMemoryInfo(); // resets the timer
+ }
+}
+
+F32 LLMemory::getSystemMemoryBudgetFactor()
+{
+ // Only update once per frame
+ U32 current_frame = LLFrameTimer::getFrameCount();
+ if (sFactorLastFrameCount == current_frame)
+ {
+ return sSysMemoryFactor;
+ }
+ sFactorLastFrameCount = current_frame;
+
+ updateFreeSystemMemory();
+#if LL_WINDOWS
+ S32Megabytes free_sys_mem = getAvailableCommitMemMB();
+#else
+ S32Megabytes free_sys_mem = getAvailableMemKB();
+#endif
+ bool is_sys_low = free_sys_mem < MEM_LOW_THRESHOLD;
+ static bool was_low = false;
+
+ // sSysMemoryFactor affects draw distance
+ //
+ // We only decrement when more than 406MB is free, but increment
+ // when below 256MB free. This should provide a stable value
+ // in the 256-406MB range to avoid draw range fluctuations.
+ //
+ // Draw range reduction is a last resort, texture bias is supposed
+ // to free at least some memory before we get here.
+ // Note: textures were mostly moved to vram, we might want to
+ // detach texture bias from system memory.
+ if (is_sys_low)
+ {
+ // debt is a negative value since MIN_FREE_MAIN_MEMORY > free memory.
+ S32Megabytes sys_budget_debt = free_sys_mem - MEM_LOW_THRESHOLD;
+
+ // Leave some padding, otherwise we will crash out of memory before hitting factor 2.
+ const S32Megabytes PAD_BUFFER(32);
+ S32Megabytes budget_target = MEM_LOW_THRESHOLD - PAD_BUFFER;
+ if (!was_low)
+ {
+ // Result should range from 1 at 0 debt to 2 at -224 debt, 2.14 at -256MB
+ F32 new_factor = 1.f - (F32)sys_budget_debt.value() / (F32)budget_target.value();
+ sSysMemoryFactor = llmax(sSysMemoryFactor, new_factor);
+ }
+ else
+ {
+ // Slowly ramp up factor to free memory (increasing factor decreases draw range)
+ constexpr F32 MAX_INCREMENT = 0.05f;
+ F32 increment = MAX_INCREMENT * llmax(-(F32)sys_budget_debt.value() / (F32)budget_target.value(), 0.f);
+ sSysMemoryFactor += increment * LLFrameTimer::getFrameDeltaTimeF32();
+ }
+ sSysMemoryFactor = llclamp(sSysMemoryFactor, 1.f, 2.f);
+ }
+ else
+ {
+ // Only start ramping down when we have breathing room.
+ // This should be under the value of isSystemMemoryLow to not throw texture
+ // bias into 1.5+ territory each time we fluctuate around isSystemMemoryLow's
+ // threshold.
+ const S32Megabytes MEM_THRESHOLD = MEM_LOW_THRESHOLD + S32Megabytes(150);
+ if (free_sys_mem > MEM_THRESHOLD && sSysMemoryFactor > 1.f)
+ {
+ // Ramp down factor over time.
+ constexpr F32 DECREMENT = 0.02f;
+ sSysMemoryFactor -= DECREMENT * LLFrameTimer::getFrameDeltaTimeF32();
+ sSysMemoryFactor = llclamp(sSysMemoryFactor, 1.f, 2.f);
+ }
+ }
+ was_low = is_sys_low;
+
+ return sSysMemoryFactor;
+}
+
+#if LL_WINDOWS
+//static
+U32Megabytes LLMemory::getAvailableCommitMemMB()
+{
+ // Commit charge combines page file and ram,
+ // theoretical limit is 128TB on 64bit windows.
+ // Store as MB instead of KB to prevent overflow.
+ return sAvailCommitMemInMB;
+}
+#endif
+
//static
U32Kilobytes LLMemory::getAvailableMemKB()
{
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index c06ae93766..5ac114cac9 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2026, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,7 @@
#define LLMEMORY_H
#include "linden_common.h"
+#include "llframetimer.h"
#include "llunits.h"
#include "stdtypes.h"
#if !LL_WINDOWS
@@ -428,17 +429,31 @@ public:
static void initMaxHeapSizeGB(F32Gigabytes max_heap_size);
static void updateMemoryInfo() ;
static void logMemoryInfo(bool update = false);
+ static F32 getSystemMemoryBudgetFactor();
+#if LL_WINDOWS
+ // Commit charge is a Windows-only concept, combines page file and ram
+ static U32Megabytes getAvailableCommitMemMB();
+#endif
static U32Kilobytes getAvailableMemKB() ;
static U32Kilobytes getMaxMemKB() ;
static U32Kilobytes getAllocatedMemKB() ;
private:
+ static void updateFreeSystemMemory();
+ // LLMemoryInfo directly updates memory stats
+ friend class LLMemoryInfo;
+
+ static U32Megabytes sAvailCommitMemInMB;
static U32Kilobytes sAvailPhysicalMemInKB ;
static U32Kilobytes sMaxPhysicalMemInKB ;
static U32Kilobytes sAllocatedMemInKB;
static U32Kilobytes sAllocatedPageSizeInKB ;
static U32Kilobytes sMaxHeapSizeInKB;
+
+ static LLFrameTimer sMemoryCheckTimer;
+ static F32 sSysMemoryFactor;
+ static U32 sFactorLastFrameCount;
};
// LLRefCount moved to llrefcount.h
diff --git a/indra/llcommon/llpointer.cpp b/indra/llcommon/llpointer.cpp
new file mode 100755
index 0000000000..1bb7055b3a
--- /dev/null
+++ b/indra/llcommon/llpointer.cpp
@@ -0,0 +1,43 @@
+/**
+ * @file llpointer.cpp
+ * @author Nat Goodspeed
+ * @date 2024-09-26
+ * @brief Implementation for llpointer.
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llpointer.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llerror.h"
+
+void LLPointerBase::wild_dtor(std::string_view msg)
+{
+// LL_WARNS() << msg << LL_ENDL;
+ llassert_msg(false, msg);
+}
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 048547e4cc..d2dcf530e5 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -26,8 +26,9 @@
#ifndef LLPOINTER_H
#define LLPOINTER_H
-#include "llerror.h" // *TODO: consider eliminating this
-#include "llmutex.h"
+#include <functional>
+#include <string_view>
+#include <utility> // std::swap()
//----------------------------------------------------------------------------
// RefCount objects should generally only be accessed by way of LLPointer<>'s
@@ -42,8 +43,18 @@
//----------------------------------------------------------------------------
+class LLPointerBase
+{
+protected:
+ // alert the coder that a referenced type's destructor did something very
+ // strange -- this is in a non-template base class so we can hide the
+ // implementation in llpointer.cpp
+ static void wild_dtor(std::string_view msg);
+};
+
// Note: relies on Type having ref() and unref() methods
-template <class Type> class LLPointer
+template <class Type>
+class LLPointer: public LLPointerBase
{
public:
template<typename Subclass>
@@ -60,6 +71,13 @@ public:
ref();
}
+ // Even though the template constructors below accepting
+ // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to
+ // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&)
+ // constructors, the compiler recognizes these as The Copy Constructor and
+ // The Move Constructor, respectively. In other words, even in the
+ // presence of the LLPointer<Subclass> constructors, we still must specify
+ // the LLPointer<Type> constructors.
LLPointer(const LLPointer<Type>& ptr) :
mPointer(ptr.mPointer)
{
@@ -98,39 +116,52 @@ public:
const Type& operator*() const { return *mPointer; }
Type& operator*() { return *mPointer; }
- operator BOOL() const { return (mPointer != nullptr); }
operator bool() const { return (mPointer != nullptr); }
bool operator!() const { return (mPointer == nullptr); }
bool isNull() const { return (mPointer == nullptr); }
bool notNull() const { return (mPointer != nullptr); }
operator Type*() const { return mPointer; }
- bool operator !=(Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+ template <typename Type1>
+ bool operator !=(Type1* ptr) const { return (mPointer != ptr); }
+ template <typename Type1>
+ bool operator ==(Type1* ptr) const { return (mPointer == ptr); }
+ template <typename Type1>
+ bool operator !=(const LLPointer<Type1>& ptr) const { return (mPointer != ptr.mPointer); }
+ template <typename Type1>
+ bool operator ==(const LLPointer<Type1>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
LLPointer<Type>& operator =(Type* ptr)
{
- assign(ptr);
+ // copy-and-swap idiom, see http://gotw.ca/gotw/059.htm
+ LLPointer temp(ptr);
+ using std::swap; // per Swappable convention
+ swap(*this, temp);
return *this;
}
+ // Even though the template assignment operators below accepting
+ // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to
+ // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&)
+ // assignment operators, the compiler recognizes these as Copy Assignment
+ // and Move Assignment, respectively. In other words, even in the presence
+ // of the LLPointer<Subclass> assignment operators, we still must specify
+ // the LLPointer<Type> operators.
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
{
- assign(ptr);
+ LLPointer temp(ptr);
+ using std::swap; // per Swappable convention
+ swap(*this, temp);
return *this;
}
LLPointer<Type>& operator =(LLPointer<Type>&& ptr)
{
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ptr.mPointer = nullptr;
- }
+ LLPointer temp(std::move(ptr));
+ using std::swap; // per Swappable convention
+ swap(*this, temp);
return *this;
}
@@ -138,28 +169,32 @@ public:
template<typename Subclass>
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
{
- assign(ptr.get());
+ LLPointer temp(ptr);
+ using std::swap; // per Swappable convention
+ swap(*this, temp);
return *this;
}
template<typename Subclass>
LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr)
{
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ptr.mPointer = nullptr;
- }
+ LLPointer temp(std::move(ptr));
+ using std::swap; // per Swappable convention
+ swap(*this, temp);
return *this;
}
// Just exchange the pointers, which will not change the reference counts.
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
{
- Type* temp = a.mPointer;
- a.mPointer = b.mPointer;
- b.mPointer = temp;
+ using std::swap; // per Swappable convention
+ swap(a.mPointer, b.mPointer);
+ }
+
+ // Put swap() overload in the global namespace, per Swappable convention
+ friend void swap(LLPointer<Type>& a, LLPointer<Type>& b)
+ {
+ LLPointer<Type>::swap(a, b);
}
protected:
@@ -184,191 +219,19 @@ protected:
temp->unref();
if (mPointer != nullptr)
{
- LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+ wild_dtor("Unreference did assignment to non-NULL because of destructor");
unref();
}
}
}
#endif // LL_LIBRARY_INCLUDE
- void assign(const LLPointer<Type>& ptr)
- {
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
- }
-
protected:
Type* mPointer;
};
-template <class Type> class LLConstPointer
-{
- template<typename Subclass>
- friend class LLConstPointer;
-public:
- LLConstPointer() :
- mPointer(nullptr)
- {
- }
-
- LLConstPointer(const Type* ptr) :
- mPointer(ptr)
- {
- ref();
- }
-
- LLConstPointer(const LLConstPointer<Type>& ptr) :
- mPointer(ptr.mPointer)
- {
- ref();
- }
-
- LLConstPointer(LLConstPointer<Type>&& ptr) noexcept
- {
- mPointer = ptr.mPointer;
- ptr.mPointer = nullptr;
- }
-
- // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLConstPointer(const LLConstPointer<Subclass>& ptr) :
- mPointer(ptr.get())
- {
- ref();
- }
-
- template<typename Subclass>
- LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept :
- mPointer(ptr.get())
- {
- ptr.mPointer = nullptr;
- }
-
- ~LLConstPointer()
- {
- unref();
- }
-
- const Type* get() const { return mPointer; }
- const Type* operator->() const { return mPointer; }
- const Type& operator*() const { return *mPointer; }
-
- operator BOOL() const { return (mPointer != nullptr); }
- operator bool() const { return (mPointer != nullptr); }
- bool operator!() const { return (mPointer == nullptr); }
- bool isNull() const { return (mPointer == nullptr); }
- bool notNull() const { return (mPointer != nullptr); }
-
- operator const Type*() const { return mPointer; }
- bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLConstPointer<Type>& operator =(const Type* ptr)
- {
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
-
- return *this;
- }
-
- LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
- {
- if( mPointer != ptr.mPointer )
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
- return *this;
- }
-
- LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr)
- {
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ptr.mPointer = nullptr;
- }
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
- {
- if( mPointer != ptr.get() )
- {
- unref();
- mPointer = ptr.get();
- ref();
- }
- return *this;
- }
-
- template<typename Subclass>
- LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr)
- {
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ptr.mPointer = nullptr;
- }
- return *this;
- }
-
- // Just exchange the pointers, which will not change the reference counts.
- static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
- {
- const Type* temp = a.mPointer;
- a.mPointer = b.mPointer;
- b.mPointer = temp;
- }
-
-protected:
-#ifdef LL_LIBRARY_INCLUDE
- void ref();
- void unref();
-#else // LL_LIBRARY_INCLUDE
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- const Type *temp = mPointer;
- mPointer = nullptr;
- temp->unref();
- if (mPointer != nullptr)
- {
- LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
- unref();
- }
- }
- }
-#endif // LL_LIBRARY_INCLUDE
-
-protected:
- const Type* mPointer;
-};
+template <typename Type>
+using LLConstPointer = LLPointer<const Type>;
template<typename Type>
class LLCopyOnWritePointer : public LLPointer<Type>
@@ -418,38 +281,26 @@ private:
bool mStayUnique;
};
-template<typename Type>
-bool operator!=(Type* lhs, const LLPointer<Type>& rhs)
+template<typename Type0, typename Type1>
+bool operator!=(Type0* lhs, const LLPointer<Type1>& rhs)
{
return (lhs != rhs.get());
}
-template<typename Type>
-bool operator==(Type* lhs, const LLPointer<Type>& rhs)
+template<typename Type0, typename Type1>
+bool operator==(Type0* lhs, const LLPointer<Type1>& rhs)
{
return (lhs == rhs.get());
}
-// boost hash adapter
-template <class Type>
-struct boost::hash<LLPointer<Type>>
-{
- typedef LLPointer<Type> argument_type;
- typedef std::size_t result_type;
- result_type operator()(argument_type const& s) const
- {
- return (std::size_t) s.get();
- }
-};
-
-// Adapt boost hash to std hash
+// Specialize for std::hash
namespace std
{
template<class Type> struct hash<LLPointer<Type>>
{
std::size_t operator()(LLPointer<Type> const& s) const noexcept
{
- return boost::hash<LLPointer<Type>>()(s);
+ return std::hash<Type*>()(s.get());
}
};
}
diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h
index e86098f20b..20561b0c65 100644
--- a/indra/llcommon/llpounceable.h
+++ b/indra/llcommon/llpounceable.h
@@ -38,9 +38,9 @@
#include "llsingleton.h"
#include <boost/call_traits.hpp>
#include <boost/utility/value_init.hpp>
-#include <boost/unordered_map.hpp>
#include <boost/signals2/signal.hpp>
+#include <unordered_map>
#include <type_traits>
// Forward declare the user template, since we want to be able to point to it
@@ -86,7 +86,7 @@ class LLPounceableQueueSingleton:
// instance will call on the SAME LLPounceableQueueSingleton instance --
// given how class statics work. We must keep a separate queue for each
// LLPounceable instance. Use a hash map for that.
- typedef boost::unordered_map<owner_ptr, signal_t> map_t;
+ typedef std::unordered_map<owner_ptr, signal_t> map_t;
public:
// Disambiguate queues belonging to different LLPounceables.
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 3120fa0100..cbba2ceb87 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -176,13 +176,13 @@ public:
// In general, our streambuf might contain a number of different
// physical buffers; iterate over those.
bool keepwriting = true;
- for (auto bufi = buffer_sequence_begin(bufs), bufend = buffer_sequence_end(bufs);
+ for (auto bufi(boost::asio::buffer_sequence_begin(bufs)), bufend(boost::asio::buffer_sequence_end(bufs));
bufi != bufend && keepwriting; ++bufi)
{
// http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
// Although apr_file_write() accepts const void*, we
// manipulate const char* so we can increment the pointer.
- const char* remainptr = static_cast<const char*>((*bufi).data());
+ const char* remainptr = static_cast<const char*>(bufi->data());
std::size_t remainlen = boost::asio::buffer_size(*bufi);
while (remainlen)
{
@@ -377,14 +377,14 @@ public:
// In general, the mutable_buffer_sequence returned by prepare() might
// contain a number of different physical buffers; iterate over those.
std::size_t tocommit(0);
- for (auto bufi = buffer_sequence_begin(bufs), bufend = buffer_sequence_end(bufs);
+ for (auto bufi(boost::asio::buffer_sequence_begin(bufs)), bufend(boost::asio::buffer_sequence_end(bufs));
bufi != bufend; ++bufi)
{
// http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
std::size_t toread(boost::asio::buffer_size(*bufi));
apr_size_t gotten(toread);
apr_status_t err = apr_file_read(mPipe,
- static_cast<void*>((*bufi).data()),
+ bufi->data(),
&gotten);
// EAGAIN is exactly what we want from a nonblocking pipe.
// Rather than waiting for data, it should return immediately.
@@ -657,10 +657,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// case), e.g. by calling operator(), returns a reference to *the same
// instance* of the wrapped type that's stored in our Block subclass.
// That's important! We know 'params' persists throughout this method
- // call; but without that guarantee, we'd have to assume that converting
- // one of its members to std::string might return a different (temp)
- // instance. Capturing the c_str() from a temporary std::string is Bad Bad
- // Bad. But armed with this knowledge, when you see params.cwd().c_str(),
+ // call; but without that guarantee, when you see params.cwd().c_str(),
// grit your teeth and smile and carry on.
if (params.cwd.isProvided())
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 35335e1213..92f8ae3245 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -32,21 +32,11 @@
#include "llsingleton.h"
#include "llstl.h"
-template <typename T>
-struct LLRegistryDefaultComparator
-{
- bool operator()(const T& lhs, const T& rhs) const
- {
- using std::less;
- return less<T>()(lhs, rhs);
- }
-};
-
-template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+template <typename KEY, typename VALUE>
class LLRegistry
{
public:
- typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef LLRegistry<KEY, VALUE> registry_t;
typedef const KEY& ref_const_key_t;
typedef const VALUE& ref_const_value_t;
typedef const VALUE* ptr_const_value_t;
@@ -54,9 +44,9 @@ public:
class Registrar
{
- friend class LLRegistry<KEY, VALUE, COMPARATOR>;
+ friend class LLRegistry<KEY, VALUE>;
public:
- typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
+ typedef std::map<KEY, VALUE> registry_map_t;
bool add(ref_const_key_t key, ref_const_value_t value)
{
@@ -234,9 +224,9 @@ private:
Registrar mDefaultRegistrar;
};
-template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+template <typename KEY, typename VALUE, typename DERIVED_TYPE>
class LLRegistrySingleton
- : public LLRegistry<KEY, VALUE, COMPARATOR>,
+ : public LLRegistry<KEY, VALUE>,
public LLSingleton<DERIVED_TYPE>
{
// This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton)
@@ -244,7 +234,7 @@ class LLRegistrySingleton
// LLRegistrySingleton. So each concrete subclass needs
// LLSINGLETON(whatever) -- not this intermediate base class.
public:
- typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef LLRegistry<KEY, VALUE> registry_t;
typedef const KEY& ref_const_key_t;
typedef const VALUE& ref_const_value_t;
typedef VALUE* ptr_value_t;
@@ -309,7 +299,7 @@ public:
};
// convenience functions
- typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
+ typedef typename LLRegistry<KEY, VALUE>::Registrar& ref_registrar_t;
static ref_registrar_t currentRegistrar()
{
return singleton_t::instance().registry_t::currentRegistrar();
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 77fe545c3f..ce39bc7af3 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -39,6 +39,9 @@
#include <limits>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
+
// Defend against a caller forcibly passing a negative number into an unsigned
// size_t index param
inline
@@ -103,6 +106,9 @@ protected:
U32 mUseCount;
public:
+ static void destruct(Impl*& var);
+ ///< safely decrement or destroy var
+
static void reset(Impl*& var, Impl* impl);
///< safely set var to refer to the new impl (possibly shared)
@@ -166,7 +172,7 @@ public:
virtual const LLSD& ref(size_t) const { return undef(); }
virtual LLSD::map_const_iterator beginMap() const { return endMap(); }
- virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); }
+ virtual LLSD::map_const_iterator endMap() const { static const LLSD::llsd_map_t empty; return empty.end(); }
virtual LLSD::array_const_iterator beginArray() const { return endArray(); }
virtual LLSD::array_const_iterator endArray() const { static const std::vector<LLSD> empty; return empty.end(); }
@@ -345,18 +351,7 @@ namespace
LLSD::Real ImplString::asReal() const
{
- F64 v = 0.0;
- std::istringstream i_stream(mValue);
- i_stream >> v;
-
- // we would probably like to ignore all trailing whitespace as
- // well, but for now, simply eat the next character, and make
- // sure we reached the end of the string.
- // *NOTE: gcc 2.95 does not generate an eof() event on the
- // stream operation above, so we manually get here to force it
- // across platforms.
- int c = i_stream.get();
- return ((EOF ==c) ? v : 0.0);
+ return llsd::string_to_real(mValue);
}
@@ -431,7 +426,7 @@ namespace
class ImplMap final : public LLSD::Impl
{
private:
- typedef std::map<LLSD::String, LLSD, std::less<>> DataMap;
+ using DataMap = LLSD::llsd_map_t;
DataMap mData;
@@ -457,7 +452,7 @@ namespace
<< it.second.asXMLRPCValue() << "</member>";
}
os << "</struct>";
- return os.str();
+ return std::move(os).str();
}
virtual bool has(std::string_view) const;
@@ -467,8 +462,13 @@ namespace
using LLSD::Impl::ref; // Unhiding ref(size_t)
virtual LLSD get(std::string_view) const;
virtual LLSD getKeys() const;
+ void insert(std::string&& k, const LLSD& v);
+ void insert(std::string&& k, LLSD&& v);
void insert(std::string_view k, const LLSD& v);
+ void insert(std::string_view k, LLSD&& v);
virtual void erase(const LLSD::String&);
+ LLSD& ref(std::string&&);
+ virtual const LLSD& ref(std::string&&) const;
LLSD& ref(std::string_view);
virtual const LLSD& ref(std::string_view) const;
@@ -525,18 +525,58 @@ namespace
return keys;
}
+ void ImplMap::insert(std::string&& k, const LLSD& v)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
+ mData.emplace(std::move(k), v);
+ }
+
+ void ImplMap::insert(std::string&& k, LLSD&& v)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
+ mData.emplace(std::move(k), std::move(v));
+ }
+
void ImplMap::insert(std::string_view k, const LLSD& v)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
mData.emplace(k, v);
}
+ void ImplMap::insert(std::string_view k, LLSD&& v)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
+ mData.emplace(k, std::move(v));
+ }
+
void ImplMap::erase(const LLSD::String& k)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
mData.erase(k);
}
+ LLSD& ImplMap::ref(std::string&& k)
+ {
+ DataMap::iterator i = mData.lower_bound(k);
+ if (i == mData.end() || mData.key_comp()(k, i->first))
+ {
+ return mData.emplace_hint(i, std::make_pair(std::move(k), LLSD()))->second;
+ }
+
+ return i->second;
+ }
+
+ const LLSD& ImplMap::ref(std::string&& k) const
+ {
+ DataMap::const_iterator i = mData.lower_bound(k);
+ if (i == mData.end() || mData.key_comp()(k, i->first))
+ {
+ return undef();
+ }
+
+ return i->second;
+ }
+
LLSD& ImplMap::ref(std::string_view k)
{
DataMap::iterator i = mData.lower_bound(k);
@@ -598,7 +638,7 @@ namespace
ImplArray(const DataVector& data) : mData(data) { }
public:
- ImplArray() { }
+ ImplArray() = default;
virtual ImplArray& makeArray(Impl*&);
@@ -615,7 +655,7 @@ namespace
os << it.asXMLRPCValue();
}
os << "</data></array>";
- return os.str();
+ return std::move(os).str();
}
using LLSD::Impl::get; // Unhiding get(LLSD::String)
@@ -625,10 +665,13 @@ namespace
virtual LLSD get(size_t) const;
void set(size_t, const LLSD&);
void insert(size_t, const LLSD&);
+ void insert(size_t, LLSD&&);
LLSD& append(const LLSD&);
+ LLSD& append(LLSD&&);
virtual void erase(size_t);
LLSD& ref(size_t);
virtual const LLSD& ref(size_t) const;
+ void reserve(size_t size) { mData.reserve(size); }
LLSD::array_iterator beginArray() { return mData.begin(); }
LLSD::array_iterator endArray() { return mData.end(); }
@@ -690,12 +733,31 @@ namespace
mData.insert(mData.begin() + index, v);
}
+ void ImplArray::insert(size_t i, LLSD&& v)
+ {
+ NEGATIVE_EXIT(i);
+ DataVector::size_type index = i;
+
+ if (index >= mData.size()) // tbd - sanity check limit for index ?
+ {
+ mData.resize(index + 1);
+ }
+
+ mData.insert(mData.begin() + index, std::move(v));
+ }
+
LLSD& ImplArray::append(const LLSD& v)
{
mData.push_back(v);
return mData.back();
}
+ LLSD& ImplArray::append(LLSD&& v)
+ {
+ mData.push_back(std::move(v));
+ return mData.back();
+ }
+
void ImplArray::erase(size_t i)
{
NEGATIVE_EXIT(i);
@@ -763,6 +825,14 @@ LLSD::Impl::~Impl()
--sOutstandingCount;
}
+void LLSD::Impl::destruct(Impl*& var)
+{
+ if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0)
+ {
+ delete var;
+ }
+}
+
void LLSD::Impl::reset(Impl*& var, Impl* impl)
{
if (impl && impl->mUseCount != STATIC_USAGE_COUNT)
@@ -961,7 +1031,7 @@ namespace
LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; }
-LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); }
+LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::destruct(impl); }
LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); }
void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
@@ -1037,13 +1107,31 @@ LLSD LLSD::emptyMap()
bool LLSD::has(const std::string_view k) const { return safe(impl).has(k); }
LLSD LLSD::get(const std::string_view k) const { return safe(impl).get(k); }
LLSD LLSD::getKeys() const { return safe(impl).getKeys(); }
+void LLSD::insert(std::string&& k, const LLSD& v) { makeMap(impl).insert(std::move(k), v); }
+void LLSD::insert(std::string&& k, LLSD&& v) { makeMap(impl).insert(std::move(k), std::move(v)); }
void LLSD::insert(std::string_view k, const LLSD& v) { makeMap(impl).insert(k, v); }
+void LLSD::insert(std::string_view k, LLSD&& v) { makeMap(impl).insert(k, std::move(v)); }
+LLSD& LLSD::with(std::string&& k, const LLSD& v)
+ {
+ makeMap(impl).insert(std::move(k), v);
+ return *this;
+ }
+LLSD& LLSD::with(std::string&& k, LLSD&& v)
+ {
+ makeMap(impl).insert(std::move(k), std::move(v));
+ return *this;
+ }
LLSD& LLSD::with(std::string_view k, const LLSD& v)
{
makeMap(impl).insert(k, v);
return *this;
}
+LLSD& LLSD::with(std::string_view k, LLSD&& v)
+ {
+ makeMap(impl).insert(k, std::move(v));
+ return *this;
+ }
void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
LLSD& LLSD::operator[](const std::string_view k)
@@ -1051,6 +1139,13 @@ LLSD& LLSD::operator[](const std::string_view k)
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return makeMap(impl).ref(k);
}
+
+LLSD& LLSD::operator[](std::string&& k)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
+ return makeMap(impl).ref(std::move(k));
+}
+
const LLSD& LLSD::operator[](const std::string_view k) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
@@ -1064,18 +1159,33 @@ LLSD LLSD::emptyArray()
return v;
}
+LLSD LLSD::emptyReservedArray(size_t size)
+{
+ LLSD v;
+ makeArray(v.impl).reserve(size);
+ return v;
+}
+
size_t LLSD::size() const { return safe(impl).size(); }
LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
+void LLSD::set(Integer i, LLSD&& v) { makeArray(impl).set(i, std::move(v)); }
void LLSD::insert(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); }
+void LLSD::insert(Integer i, LLSD&& v) { makeArray(impl).insert(i, std::move(v)); }
LLSD& LLSD::with(Integer i, const LLSD& v)
{
makeArray(impl).insert(i, v);
return *this;
}
+LLSD& LLSD::with(Integer i, LLSD&& v)
+ {
+ makeArray(impl).insert(i, std::move(v));
+ return *this;
+ }
LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
+LLSD& LLSD::append(LLSD&& v) { return makeArray(impl).append(std::move(v)); }
void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
LLSD& LLSD::operator[](size_t i)
@@ -1143,6 +1253,22 @@ LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl)
namespace llsd
{
+LLSD::Real string_to_real(std::string_view in_string)
+{
+ LLSD::Real v = 0.0;
+ boost::iostreams::stream<boost::iostreams::array_source> i_stream(in_string.data(), in_string.size());
+ i_stream >> v;
+
+ // we would probably like to ignore all trailing whitespace as
+ // well, but for now, simply eat the next character, and make
+ // sure we reached the end of the string.
+ // *NOTE: gcc 2.95 does not generate an eof() event on the
+ // stream operation above, so we manually get here to force it
+ // across platforms.
+ int c = i_stream.get();
+ return ((EOF == c) ? v : 0.0);
+}
+
U32 allocationCount() { return LLSD::Impl::sAllocationCount; }
U32 outstandingCount() { return LLSD::Impl::sOutstandingCount; }
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index d2b3548831..afe35a65ba 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -34,6 +34,7 @@
#include "stdtypes.h"
#include "lldate.h"
+#include "llstl.h"
#include "lluri.h"
#include "lluuid.h"
@@ -321,11 +322,34 @@ public:
bool has(const std::string_view) const;
LLSD get(const std::string_view) const;
LLSD getKeys() const; // Return an LLSD array with keys as strings
+ void insert(const char* k, const LLSD& v)
+ {
+ return insert(std::string_view(k), v);
+ }
+ void insert(const char* k , LLSD&& v)
+ {
+ return insert(std::string_view(k), std::move(v));
+ }
+ void insert(std::string&&, const LLSD&);
+ void insert(std::string&&, LLSD&&);
void insert(std::string_view, const LLSD&);
+ void insert(std::string_view, LLSD&&);
void erase(const String&);
+ LLSD& with(const char* k, const LLSD& v)
+ {
+ return with(std::string_view(k), v);
+ }
+ LLSD& with(const char* k, LLSD&& v)
+ {
+ return with(std::string_view(k), std::move(v));
+ }
+ LLSD& with(std::string&&, const LLSD&);
+ LLSD& with(std::string&&, LLSD&&);
LLSD& with(std::string_view, const LLSD&);
+ LLSD& with(std::string_view, LLSD&&);
LLSD& operator[](const std::string_view);
+ LLSD& operator[](std::string&&);
LLSD& operator[](const char* c)
{
return c ? (*this)[std::string_view(c)] : *this;
@@ -339,14 +363,22 @@ public:
/** @name Array Values */
//@{
+ // Allocate an empty array
static LLSD emptyArray();
+ // Allocate an array with internal storage reserved but not initialized like a std::vector
+ static LLSD emptyReservedArray(size_t size);
+
LLSD get(Integer) const;
void set(Integer, const LLSD&);
+ void set(Integer, LLSD&&);
void insert(Integer, const LLSD&);
+ void insert(Integer, LLSD&&);
LLSD& append(const LLSD&);
+ LLSD& append(LLSD&&);
void erase(Integer);
LLSD& with(Integer, const LLSD&);
+ LLSD& with(Integer, LLSD&&);
// accept size_t so we can index relative to size()
const LLSD& operator[](size_t) const;
@@ -366,8 +398,9 @@ public:
//@{
size_t size() const;
- typedef std::map<String, LLSD>::iterator map_iterator;
- typedef std::map<String, LLSD>::const_iterator map_const_iterator;
+ using llsd_map_t = std::map<String, LLSD, std::less<>>;
+ typedef llsd_map_t::iterator map_iterator;
+ typedef llsd_map_t::const_iterator map_const_iterator;
map_iterator beginMap();
map_iterator endMap();
@@ -512,6 +545,8 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
namespace llsd
{
+ // Used by LLSD::ImplString to convert string type to real
+ LLSD::Real string_to_real(std::string_view in_string);
#ifdef LLSD_DEBUG_INFO
/** @name Unit Testing Interface */
diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
index a4b45ed80d..71f35802c5 100644
--- a/indra/llcommon/llsdjson.cpp
+++ b/indra/llcommon/llsdjson.cpp
@@ -70,7 +70,7 @@ LLSD LlsdFromJson(const boost::json::value& val)
const boost::json::array& array = val.as_array();
size_t size = array.size();
// allocate elements 0 .. (size() - 1) to avoid incremental allocation
- if (! array.empty())
+ if (!array.empty())
{
result[size - 1] = LLSD();
}
@@ -84,7 +84,7 @@ LLSD LlsdFromJson(const boost::json::value& val)
result = LLSD::emptyMap();
for (const auto& element : val.as_object())
{
- result[element.key()] = LlsdFromJson(element.value());
+ result[std::string_view(element.key())] = LlsdFromJson(element.value());
}
break;
}
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 68a7bf0adf..f850238dff 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -775,7 +775,8 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) c
// There must be a value for every key, thus
// child_count must be greater than 0.
parse_count += count;
- map.insert(name, child);
+ map.insert(std::move(name), std::move(child)); // Move as name will be filled on next iteration
+ name.clear();
}
else
{
@@ -822,7 +823,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_dept
else
{
parse_count += count;
- array.append(child);
+ array.append(std::move(child));
}
c = get(istr);
}
@@ -841,7 +842,7 @@ bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
auto count = deserialize_string(istr, value, mMaxBytesLeft);
if(PARSE_FAILURE == count) return false;
account(count);
- data = value;
+ data = std::move(value);
return true;
}
@@ -872,10 +873,10 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
if(len)
{
value.resize(len);
- account(fullread(istr, (char *)&value[0], len));
+ account(fullread(istr, (char*)value.data(), len));
}
c = get(istr); // strip off the trailing double-quote
- data = value;
+ data = std::move(value);
}
else if(0 == strncmp("b64", buf, 3))
{
@@ -885,7 +886,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
std::stringstream coded_stream;
get(istr, *(coded_stream.rdbuf()), '\"');
c = get(istr);
- std::string encoded(coded_stream.str());
+ std::string encoded(std::move(coded_stream).str());
S32 len = apr_base64_decode_len(encoded.c_str());
std::vector<U8> value;
if(len)
@@ -894,7 +895,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
len = apr_base64_decode_binary(&value[0], encoded.c_str());
value.resize(len);
}
- data = value;
+ data = std::move(value);
}
else if(0 == strncmp("b16", buf, 3))
{
@@ -925,7 +926,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
// copy the data out of the byte buffer
value.insert(value.end(), byte_buffer, write);
}
- data = value;
+ data = std::move(value);
}
else
{
@@ -1077,7 +1078,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
}
else
{
- data = value;
+ data = std::move(value);
account(cnt);
}
if(istr.fail())
@@ -1094,7 +1095,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
std::string value;
if(parseString(istr, value))
{
- data = value;
+ data = std::move(value);
}
else
{
@@ -1159,7 +1160,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
value.resize(size);
account(fullread(istr, (char*)&value[0], size));
}
- data = value;
+ data = std::move(value);
}
if(istr.fail())
{
@@ -1218,7 +1219,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) con
// There must be a value for every key, thus child_count
// must be greater than 0.
parse_count += child_count;
- map.insert(name, child);
+ map.insert(std::move(name), std::move(child));
}
else
{
@@ -1238,13 +1239,12 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) con
S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
{
- array = LLSD::emptyArray();
U32 value_nbo = 0;
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
S32 size = (S32)ntohl(value_nbo);
- // *FIX: This would be a good place to reserve some space in the
- // array...
+ // Preallocate array to avoid incremental allocation
+ array = LLSD::emptyReservedArray(size);
S32 parse_count = 0;
S32 count = 0;
@@ -1260,7 +1260,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth)
if(child_count)
{
parse_count += child_count;
- array.append(child);
+ array.append(std::move(child));
}
++count;
c = istr.peek();
@@ -1279,18 +1279,15 @@ bool LLSDBinaryParser::parseString(
std::istream& istr,
std::string& value) const
{
- // *FIX: This is memory inefficient.
U32 value_nbo = 0;
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
S32 size = (S32)ntohl(value_nbo);
if(mCheckLimits && (size > mMaxBytesLeft)) return false;
if(size < 0) return false;
- std::vector<char> buf;
if(size)
{
- buf.resize(size);
- account(fullread(istr, &buf[0], size));
- value.assign(buf.begin(), buf.end());
+ value.resize(size);
+ account(fullread(istr, value.data(), size));
}
return true;
}
@@ -1785,7 +1782,7 @@ llssize deserialize_string_delim(
}
}
- value = write_buffer.str();
+ value = std::move(write_buffer).str();
return count;
}
@@ -1806,15 +1803,12 @@ llssize deserialize_string_raw(
{
// We probably have a valid raw string. determine
// the size, and read it.
- // *FIX: This is memory inefficient.
- auto len = strtol(buf + 1, NULL, 0);
+ auto len = strtol(buf + 1, nullptr, 0);
if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
- std::vector<char> buf;
if(len)
{
- buf.resize(len);
- count += fullread(istr, (char *)&buf[0], len);
- value.assign(buf.begin(), buf.end());
+ value.resize(len);
+ count += fullread(istr, value.data(), len);
}
c = istr.get();
++count;
@@ -2170,7 +2164,7 @@ std::string zip_llsd(LLSD& data)
return std::string();
}
- std::string source = llsd_strm.str();
+ std::string source = std::move(llsd_strm).str();
U8 out[CHUNK];
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index ce416baa04..afe4fd63a6 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -31,6 +31,8 @@
#include <deque>
#include "apr_base64.h"
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
#include <boost/regex.hpp>
extern "C"
@@ -645,7 +647,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch
if (mCurrentKey.empty()) { return startSkipping(); }
LLSD& map = *mStack.back();
- LLSD& newElement = map[mCurrentKey];
+ LLSD& newElement = map[std::move(mCurrentKey)];
mStack.push_back(&newElement);
mCurrentKey.clear();
@@ -709,7 +711,8 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
return;
case ELEMENT_KEY:
- mCurrentKey = mCurrentContent;
+ mCurrentKey = std::move(mCurrentContent); // This is safe to move as we are in the end element handler
+ mCurrentContent.clear(); // Ensure mCurrentContent is empty for subsequent use
return;
default:
@@ -742,14 +745,22 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
}
else
{
- value = LLSD(mCurrentContent).asInteger();
+ // This must treat "1.23" not as an error, but as a number, which is
+ // then truncated down to an integer. Hence, this code doesn't call
+ // std::istringstream::operator>>(int&), which would not consume the
+ // ".23" portion.
+
+ // Utilizes implementation used internally by LLSD::ImplString::asInteger
+ value = (int)llsd::string_to_real(mCurrentContent);
}
}
break;
case ELEMENT_REAL:
{
- value = LLSD(mCurrentContent).asReal();
+ // Utilizes implementation used internally by LLSD::ImplString::asReal
+ value = llsd::string_to_real(mCurrentContent);
+
// removed since this breaks when locale has decimal separator that isn't '.'
// investigated changing local to something compatible each time but deemed higher
// risk that just using LLSD.asReal() each time.
@@ -766,19 +777,19 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
break;
case ELEMENT_STRING:
- value = mCurrentContent;
+ value = std::move(mCurrentContent); // This is safe to move as we are in the end element handler and this is cleared below
break;
case ELEMENT_UUID:
- value = LLSD(mCurrentContent).asUUID();
+ value = LLUUID(mCurrentContent);
break;
case ELEMENT_DATE:
- value = LLSD(mCurrentContent).asDate();
+ value = LLDate(mCurrentContent);
break;
case ELEMENT_URI:
- value = LLSD(mCurrentContent).asURI();
+ value = LLURI(mCurrentContent);
break;
case ELEMENT_BINARY:
@@ -787,15 +798,14 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
// created by python and other non-linden systems - DEV-39358
// Fortunately we have very little binary passing now,
// so performance impact shold be negligible. + poppy 2009-09-04
- boost::regex r;
- r.assign("\\s");
+ static const boost::regex r("\\s");
std::string stripped = boost::regex_replace(mCurrentContent, r, "");
S32 len = apr_base64_decode_len(stripped.c_str());
std::vector<U8> data;
data.resize(len);
len = apr_base64_decode_binary(&data[0], stripped.c_str());
data.resize(len);
- value = data;
+ value = std::move(data);
break;
}
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 3fba8602ee..e6989211ae 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -25,10 +25,10 @@
#ifndef LLSINGLETON_H
#define LLSINGLETON_H
-#include <boost/unordered_set.hpp>
#include <initializer_list>
#include <list>
#include <typeinfo>
+#include <unordered_set>
#include <vector>
#include "mutex.h"
#include "lockstatic.h"
@@ -61,7 +61,7 @@ private:
static vec_t dep_sort();
// we directly depend on these other LLSingletons
- typedef boost::unordered_set<LLSingletonBase*> set_t;
+ typedef std::unordered_set<LLSingletonBase*> set_t;
set_t mDepends;
protected:
diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h
index 66ba3487c4..edff955ee7 100644
--- a/indra/llcommon/llstaticstringtable.h
+++ b/indra/llcommon/llstaticstringtable.h
@@ -29,9 +29,10 @@
#define LL_STATIC_STRING_TABLE_H
#include "lldefs.h"
-#include <boost/unordered_map.hpp>
#include "llstl.h"
+#include <unordered_map>
+
class LLStaticHashedString
{
public:
@@ -74,7 +75,7 @@ struct LLStaticStringHasher
template< typename MappedObject >
class LL_COMMON_API LLStaticStringTable
- : public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
+ : public std::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
{
};
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 7d41c42ba7..7a1c7caf82 100644
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -34,6 +34,7 @@
#include <vector>
#include <list>
#include <set>
+#include <typeindex>
#include <typeinfo>
#ifdef LL_LINUX
@@ -229,12 +230,10 @@ void delete_and_clear_array(T*& ptr)
template <typename T>
inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_type const& key)
{
- // Typedef here avoids warnings because of new c++ naming rules.
- typedef typename T::const_iterator map_iter;
- map_iter iter = inmap.find(key);
+ auto iter = inmap.find(key);
if(iter == inmap.end())
{
- return NULL;
+ return nullptr;
}
else
{
@@ -243,8 +242,8 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty
};
// helper function which returns true if key is in inmap.
-template <typename K, typename T>
-inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
+template <typename T>
+inline bool is_in_map(const T& inmap, typename T::key_type const& key)
{
if(inmap.find(key) == inmap.end())
{
@@ -260,12 +259,10 @@ inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
// To replace LLSkipMap getIfThere, use:
// get_if_there(map, key, 0)
// WARNING: Make sure default_value (generally 0) is not a valid map entry!
-template <typename K, typename T>
-inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
+template <typename T>
+inline typename T::mapped_type get_if_there(const T& inmap, typename T::key_type const& key, typename T::mapped_type default_value)
{
- // Typedef here avoids warnings because of new c++ naming rules.
- typedef typename std::map<K,T>::const_iterator map_iter;
- map_iter iter = inmap.find(key);
+ auto iter = inmap.find(key);
if(iter == inmap.end())
{
return default_value;
@@ -709,5 +706,24 @@ struct ll_template_cast_impl<DEST, SOURCE> \
} \
}
+// Transparent string hashing helper for use with std::unordered_*
+// std::unordered_map<std::string, val, ll::string_hash, std::equal_to<>>
+namespace ll
+{
+ struct string_hash
+ {
+ using is_transparent = void;
+ [[nodiscard]] size_t operator()(char const* rhs) const { return std::hash<std::string_view>{}(rhs); }
+ [[nodiscard]] size_t operator()(std::string_view rhs) const { return std::hash<std::string_view>{}(rhs); }
+ [[nodiscard]] size_t operator()(const std::string& rhs) const { return std::hash<std::string>{}(rhs); }
+ };
+} // namespace ll
+
+// Specialize ostream for std::type_index to allow log output
+inline std::ostream& operator<<(std::ostream& s, std::type_index type)
+{
+ s << type.name();
+ return s;
+}
#endif // LL_LLSTL_H
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 542de4ee67..452acf4322 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2026, 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
@@ -43,6 +43,7 @@
#include "llerrorcontrol.h"
#include "llevents.h"
#include "llformat.h"
+#include "llmemory.h"
#include "llregex.h"
#include "lltimer.h"
#include "llsdserialize.h"
@@ -811,15 +812,13 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
}
//static
-void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_mem_kb)
+void LLMemoryInfo::updateAvailableMemory()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
#if LL_WINDOWS
- // Sigh, this shouldn't be a static method, then we wouldn't have to
- // reload this data separately from refresh()
- LLSD statsMap(loadStatsMap());
-
- avail_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
+ // On windows loadStatsMap will fill sAvailPhysicalMemInKB,
+ // sAvailCommitMemInMB, sAllocatedMemInKB and sAllocatedPageSizeInKB
+ loadStatsMap();
#elif LL_DARWIN
// use host_statistics64 to get memory info
@@ -831,11 +830,11 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_mem_kb)
kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count);
if (result == KERN_SUCCESS)
{
- avail_mem_kb = U64Bytes((vmstat.free_count + vmstat.inactive_count) * page_size);
+ LLMemory::sAvailPhysicalMemInKB = U64Bytes((vmstat.free_count + vmstat.inactive_count) * page_size);
}
else
{
- avail_mem_kb = (U32Kilobytes)-1;
+ LLMemory::sAvailPhysicalMemInKB = (U32Kilobytes)-1;
}
#elif LL_LINUX
@@ -889,12 +888,12 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_mem_kb)
// (could also run 'free', but easier to read a file than run a program)
LLSD statsMap(loadStatsMap());
- avail_mem_kb = (U32Kilobytes)statsMap["MemFree"].asInteger();
+ LLMemory::sAvailPhysicalMemInKB = (U32Kilobytes)statsMap["MemFree"].asInteger();
#else
//do not know how to collect available memory info for other systems.
//leave it blank here for now.
- avail_mem_kb = (U32Kilobytes)-1 ;
+ LLMemory::sAvailPhysicalMemInKB = (U32Kilobytes)-1 ;
#endif
}
@@ -965,15 +964,24 @@ LLSD LLMemoryInfo::loadStatsMap()
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
- DWORDLONG div = 1024;
+ static constexpr DWORDLONG div = 1024;
- stats.add("Percent Memory use", state.dwMemoryLoad/div);
+ stats.add("Percent Memory use", state.dwMemoryLoad);
stats.add("Total Physical KB", state.ullTotalPhys/div);
stats.add("Avail Physical KB", state.ullAvailPhys/div);
+
+ // Despite the confusing naming "PageFile" , these values
+ // actually represent the committed memory limit for
+ // the system or the current process, whichever is smaller.
stats.add("Total page KB", state.ullTotalPageFile/div);
stats.add("Avail page KB", state.ullAvailPageFile/div);
- stats.add("Total Virtual KB", state.ullTotalVirtual/div);
- stats.add("Avail Virtual KB", state.ullAvailVirtual/div);
+
+ static constexpr DWORDLONG mb_div = 1024 * 1024;
+ stats.add("Total Virtual MB", state.ullTotalVirtual/mb_div); // ~134 million MB
+ stats.add("Avail Virtual MB", state.ullAvailVirtual/mb_div);
+
+ LLMemory::sAvailPhysicalMemInKB = U32Kilobytes::convert(U64Bytes(state.ullAvailPhys));
+ LLMemory::sAvailCommitMemInMB = U32Megabytes::convert(U64Bytes(state.ullAvailPageFile));
// SL-12122 - Call to GetPerformanceInfo() was removed here. Took
// on order of 10 ms, causing unacceptable frame time spike every
@@ -989,18 +997,38 @@ LLSD LLMemoryInfo::loadStatsMap()
// specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a
// classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the
// pointer.
- GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmem, sizeof(pmem));
+ if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmem, sizeof(pmem)))
+ {
+ LLMemory::sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(pmem.WorkingSetSize));
+ LLMemory::sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(pmem.PagefileUsage));
- stats.add("Page Fault Count", pmem.PageFaultCount);
- stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/div);
- stats.add("WorkingSetSize KB", pmem.WorkingSetSize/div);
- stats.add("QutaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage/div);
- stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage/div);
- stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage/div);
- stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage/div);
- stats.add("PagefileUsage KB", pmem.PagefileUsage/div);
- stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage/div);
- stats.add("PrivateUsage KB", pmem.PrivateUsage/div);
+ stats.add("Page Fault Count", pmem.PageFaultCount);
+ stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize / div);
+ stats.add("WorkingSetSize KB", pmem.WorkingSetSize / div);
+ stats.add("QuotaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage / div);
+ stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage / div);
+ stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage / div);
+ stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage / div);
+ stats.add("PagefileUsage KB", pmem.PagefileUsage / div);
+ stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage / div);
+ stats.add("PrivateUsage KB", pmem.PrivateUsage / div);
+ }
+ else
+ {
+ LLMemory::sAllocatedMemInKB = U32Kilobytes(0);
+ LLMemory::sAllocatedPageSizeInKB = U32Kilobytes(0);
+
+ stats.add("Page Fault Count", 0);
+ stats.add("PeakWorkingSetSize KB", 0);
+ stats.add("WorkingSetSize KB", 0);
+ stats.add("QuotaPeakPagedPoolUsage KB", 0);
+ stats.add("QuotaPagedPoolUsage KB", 0);
+ stats.add("QuotaPeakNonPagedPoolUsage KB", 0);
+ stats.add("QuotaNonPagedPoolUsage KB", 0);
+ stats.add("PagefileUsage KB", 0);
+ stats.add("PeakPagefileUsage KB", 0);
+ stats.add("PrivateUsage KB", 0);
+ }
#elif LL_DARWIN
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index c8ff4dd98a..91fa2754ab 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2026, 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
@@ -134,11 +134,12 @@ public:
static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib.
#endif
- //get the available memory in KiloBytes.
- static void getAvailableMemoryKB(U32Kilobytes& avail_mem_kb);
+ // Updates LLMemory's values.
+ static void updateAvailableMemory();
// Retrieve a map of memory statistics. The keys of the map are platform-
- // dependent. The values are in kilobytes to try to avoid integer overflow.
+ // dependent.
+ // On Windows updates LLMemory values.
LLSD getStatsMap() const;
// Re-fetch memory data (as reported by stream() and getStatsMap()) from the
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index ca1cf03c4d..f91aadccc0 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -26,6 +26,7 @@
#ifndef LL_LLUUID_H
#define LL_LLUUID_H
+#include <functional>
#include <iostream>
#include <set>
#include <vector>
@@ -176,15 +177,27 @@ namespace std
{
inline size_t operator()(const LLUUID& id) const noexcept
{
- return (size_t)id.getDigest64();
+ size_t h = 0;
+ // Golden ratio hash with avalanche mixing
+ // Process 8 bytes at a time by manually constructing 64-bit values
+ // Shift by 31: mixes upper half into lower half for better bit distribution
+ // Shift by 47: ensures highest bits influence final hash output
+ for (int i = 0; i < UUID_BYTES; i += 8) {
+ size_t chunk = (size_t)id.mData[i] | ((size_t)id.mData[i+1] << 8) |
+ ((size_t)id.mData[i+2] << 16) | ((size_t)id.mData[i+3] << 24) |
+ ((size_t)id.mData[i+4] << 32) | ((size_t)id.mData[i+5] << 40) |
+ ((size_t)id.mData[i+6] << 48) | ((size_t)id.mData[i+7] << 56);
+ h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47);
+ }
+ return h;
}
};
}
-// For use with boost containers.
+// For use with boost::container_hash
inline size_t hash_value(const LLUUID& id) noexcept
{
- return (size_t)id.getDigest64();
+ return std::hash<LLUUID>{}(id);
}
#endif // LL_LLUUID_H
diff --git a/indra/llcommon/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp
index fa240a9ed7..886f19366c 100644
--- a/indra/llcommon/llwatchdog.cpp
+++ b/indra/llcommon/llwatchdog.cpp
@@ -28,6 +28,7 @@
#include "linden_common.h"
#include "llwatchdog.h"
+#include "llmutex.h"
#include "llthread.h"
constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U;
@@ -86,7 +87,7 @@ void LLWatchdogEntry::start()
void LLWatchdogEntry::stop()
{
// this can happen very late in the shutdown sequence
- if (!LLWatchdog::wasDeleted())
+ if (LLWatchdog::instanceExists())
{
LLWatchdog::getInstance()->remove(this);
}
@@ -115,6 +116,11 @@ bool LLWatchdogTimeout::isAlive() const
return (mTimer.getStarted() && !mTimer.hasExpired());
}
+bool LLWatchdogTimeout::started() const
+{
+ return mTimer.getStarted();
+}
+
void LLWatchdogTimeout::reset()
{
mTimer.setTimerExpirySec(mTimeout);
@@ -172,6 +178,17 @@ void LLWatchdog::add(LLWatchdogEntry* e)
{
lockThread();
mSuspects.insert(e);
+
+ if (!mFrozeList.empty())
+ {
+ mFrozeList.erase(e);
+ if (mFrozeList.empty())
+ {
+ // Clear error marker file if there is no frozen threads,
+ // viewer is responsive again.
+ mClearMarkerFnc();
+ }
+ }
unlockThread();
}
@@ -179,10 +196,16 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
{
lockThread();
mSuspects.erase(e);
+ mFrozeList.erase(e);
unlockThread();
}
-void LLWatchdog::init(func_t set_error_state_callback)
+void LLWatchdog::init(
+ create_marker_func_t error_state_callback,
+ clear_marker_func_t clear_marker_callback,
+ report_func_t report_callback,
+ notify_func_t notify_callback,
+ bool crash_on_freeze)
{
if (!mSuspectsAccessMutex && !mTimer)
{
@@ -195,7 +218,11 @@ void LLWatchdog::init(func_t set_error_state_callback)
// start needs to use the mSuspectsAccessMutex
mTimer->start();
}
- mCreateMarkerFnc = set_error_state_callback;
+ mCreateMarkerFnc = error_state_callback;
+ mClearMarkerFnc = clear_marker_callback;
+ mCrashReportFnc = report_callback;
+ mNotifyFnc = notify_callback;
+ mCrashOnFreeze = crash_on_freeze;
}
void LLWatchdog::cleanup()
@@ -250,21 +277,47 @@ void LLWatchdog::run()
mTimer->stop();
}
- // Sets error marker file
- mCreateMarkerFnc();
- // Todo1: Warn user?
- // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'.
std::string last_state = (*result)->getLastState();
- if (last_state.empty())
+ std::string description = "Watchdog timer for thread " + (*result)->getThreadName() + " expired";
+ if (!last_state.empty())
+ {
+ description += " with state: " + last_state;
+ }
+ description += "; assuming viewer is hung and crashing";
+
+ if (!mCrashOnFreeze)
{
- LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
- << " expired; assuming viewer is hung and crashing" << LL_ENDL;
+ // Sets watchdog marker file
+ mCreateMarkerFnc(false);
+ // If it's mainloop and it somehow recovers, it will re-add itself
+ LLWatchdogEntry* froze_entry = *result;
+ mSuspects.erase(result);
+ mFrozeList.insert(froze_entry);
+ LL_WARNS() << description << LL_ENDL;
}
else
{
- LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
- << " expired with state: " << last_state
- << "; assuming viewer is hung and crashing" << LL_ENDL;
+
+ if (!mCrashReportFnc(description))
+ {
+ // Sets error marker file
+ mCreateMarkerFnc(true);
+ // If false is returned, then we failed to report the issue to bugsplat,
+ // instead, Notify user, then crash viewer.
+ // Todo: ask user if viewer should quit or wait?
+ mNotifyFnc();
+ LL_ERRS() << description << LL_ENDL;
+ }
+ else
+ {
+ // Sets watchdog marker file
+ mCreateMarkerFnc(false);
+ // Already reported, don't report again.
+ // If it's mainloop and it somehow recovers, it will re-add itself
+ LLWatchdogEntry* froze_entry = *result;
+ mSuspects.erase(result);
+ mFrozeList.insert(froze_entry);
+ }
}
}
}
diff --git a/indra/llcommon/llwatchdog.h b/indra/llcommon/llwatchdog.h
index fded881bb8..d55bf434f3 100644
--- a/indra/llcommon/llwatchdog.h
+++ b/indra/llcommon/llwatchdog.h
@@ -47,6 +47,7 @@ public:
// This may mean that resources used by
// isAlive and other method may need synchronization.
virtual bool isAlive() const = 0;
+ virtual bool started() const = 0;
virtual void reset() = 0;
virtual void start();
virtual void stop();
@@ -66,6 +67,7 @@ public:
virtual ~LLWatchdogTimeout();
bool isAlive() const override;
+ bool started() const override;
void reset() override;
void start() override { start(""); }
void stop() override;
@@ -83,18 +85,26 @@ private:
};
class LLWatchdogTimerThread; // Defined in the cpp
-class LLWatchdog : public LLSingleton<LLWatchdog>
+class LLWatchdog : public LLSimpleton<LLWatchdog>
{
- LLSINGLETON(LLWatchdog);
+public:
+ LLWatchdog();
~LLWatchdog();
-public:
// Add an entry to the watchdog.
void add(LLWatchdogEntry* e);
void remove(LLWatchdogEntry* e);
- typedef std::function<void()> func_t;
- void init(func_t set_error_state_callback);
+ typedef std::function<void(bool)> create_marker_func_t;
+ typedef std::function<void()> clear_marker_func_t;
+ typedef std::function<bool(std::string&)> report_func_t;
+ typedef std::function<void()> notify_func_t;
+ void init(
+ create_marker_func_t error_state_callback,
+ clear_marker_func_t clear_marker_callback,
+ report_func_t report_callback,
+ notify_func_t notify_callback,
+ bool crash_on_freeze);
void run();
void cleanup();
@@ -105,14 +115,19 @@ private:
typedef std::set<LLWatchdogEntry*> SuspectsRegistry;
SuspectsRegistry mSuspects;
+ SuspectsRegistry mFrozeList;
LLMutex* mSuspectsAccessMutex;
LLWatchdogTimerThread* mTimer;
U64 mLastClockCount;
+ bool mCrashOnFreeze;
// At the moment watchdog expects app to set markers in mCreateMarkerFnc,
// but technically can be used to set any error states or do some cleanup
// or show warnings.
- func_t mCreateMarkerFnc;
+ create_marker_func_t mCreateMarkerFnc;
+ clear_marker_func_t mClearMarkerFnc;
+ report_func_t mCrashReportFnc;
+ notify_func_t mNotifyFnc;
};
#endif // LL_LLTHREADWATCHDOG_H
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 111ad4322e..fbd92d089e 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -293,12 +293,30 @@ bool LL::WorkQueue::done()
bool LL::WorkQueue::post(const Work& callable)
{
- return mQueue.pushIfOpen(callable);
+ try
+ {
+ return mQueue.pushIfOpen(callable);
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::post" << LL_ENDL;
+ return false;
+ }
}
bool LL::WorkQueue::tryPost(const Work& callable)
{
- return mQueue.tryPush(callable);
+ try
+ {
+ return mQueue.tryPush(callable);
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::tryPost" << LL_ENDL;
+ return false;
+ }
}
LL::WorkQueue::Work LL::WorkQueue::pop_()
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index c6d8db8d48..a57ac021d9 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -44,6 +44,7 @@
#include "stringize.h"
#include "llstring.h"
#include <boost/filesystem.hpp>
+#include "llprocess.h"
#include <boost/bind.hpp>
#include <algorithm>
@@ -1104,6 +1105,64 @@ LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) c
return SepOff(false, 0);
}
+void LLDir::openDir(const std::string& filepath)
+{
+ if (filepath.empty())
+ {
+ LL_WARNS() << "Cannot open file browser: filepath is empty" << LL_ENDL;
+ return;
+ }
+
+ // Extract directory path from full filepath
+ std::string dir_path = getDirName(filepath);
+
+ LLProcess::Params params;
+
+#if LL_WINDOWS
+ // Windows: Use explorer.exe with /select flag to highlight the file
+ std::string system_root = LLStringUtil::getenv("SystemRoot");
+ if (system_root.empty())
+ {
+ system_root = LLStringUtil::getenv("WINDIR");
+ }
+ if (system_root.empty())
+ {
+ LL_WARNS() << "Neither SystemRoot nor WINDIR environment variable is set" << LL_ENDL;
+ system_root = "C:\\Windows"; // Last resort fallback
+ }
+ params.executable = system_root + "\\explorer.exe";
+ params.args.add("/select,");
+ params.args.add(filepath);
+#elif LL_DARWIN
+ // macOS: Use 'open' command with -R flag to reveal in Finder
+ params.executable = "/usr/bin/open";
+ params.args.add("-R");
+ params.args.add(filepath);
+#elif LL_LINUX
+ // Linux: Use xdg-open to open the directory
+ // Note: Most file managers don't support file selection, so we open the directory
+ params.executable = "/usr/bin/xdg-open";
+ params.args.add(dir_path);
+#elif __FreeBSD__
+ params.executable = "/usr/local/bin/xdg-open";
+ params.args.add(dir_path);
+#else
+ LL_WARNS() << "Platform not supported for file browser opening" << LL_ENDL;
+ return;
+#endif
+
+ params.autokill = false; // Don't kill the file browser when viewer exits
+
+ if (!LLProcess::create(params))
+ {
+ LL_WARNS() << "Failed to open file browser for: " << filepath << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Opened file browser for: " << filepath << LL_ENDL;
+ }
+}
+
void dir_exists_or_crash(const std::string &dir_name)
{
#if LL_WINDOWS
diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h
index b0d2b6aada..3c8e2e2da6 100644
--- a/indra/llfilesystem/lldir.h
+++ b/indra/llfilesystem/lldir.h
@@ -194,6 +194,9 @@ class LLDir
virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG);
+ // Open the system file browser to reveal a file or directory
+ void openDir(const std::string& filepath);
+
// Utility routine
std::string buildSLOSCacheDir() const;
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index 82e9e18918..fafe959ac6 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -91,6 +91,8 @@ LLDiskCache::LLDiskCache(const std::string& cache_dir,
// asset will have to be re-requested.
void LLDiskCache::purge()
{
+ LL_PROFILE_ZONE_SCOPED;
+
if (mEnableCacheDebugInfo)
{
LL_INFOS() << "Total dir size before purge is " << dirFileSize(sCacheDir) << LL_ENDL;
@@ -112,6 +114,10 @@ void LLDiskCache::purge()
boost::filesystem::directory_iterator iter(cache_path, ec);
while (iter != boost::filesystem::directory_iterator() && !ec.failed())
{
+ if(!LLApp::isRunning())
+ {
+ return;
+ }
if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())
{
#if LL_WINDOWS
@@ -158,6 +164,10 @@ void LLDiskCache::purge()
uintmax_t file_size_total = 0;
for (file_info_t& entry : file_info)
{
+ if (!LLApp::isRunning())
+ {
+ return;
+ }
file_size_total += entry.second.first;
bool should_remove = file_size_total > mMaxSizeBytes;
@@ -190,6 +200,10 @@ void LLDiskCache::purge()
// Logging thousands of file results can take hundreds of milliseconds
for (size_t i = 0; i < file_info.size(); ++i)
{
+ if (!LLApp::isRunning())
+ {
+ return;
+ }
const file_info_t& entry = file_info[i];
const bool removed = file_removed[i];
const std::string action = removed ? "DELETE:" : "KEEP:";
diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 541266af4f..cd0ce45049 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -75,13 +75,16 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_
bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
{
LL_PROFILE_ZONE_SCOPED;
+#if LL_WINDOWS
+ const auto filename = ll_convert<std::wstring>(LLDiskCache::metaDataToFilepath(file_id, file_type));
+#else
const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
+#endif
- llifstream file(filename, std::ios::binary);
- if (file.is_open())
+ boost::system::error_code ec;
+ if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec))
{
- file.seekg(0, std::ios::end);
- return file.tellg() > 0;
+ return boost::filesystem::file_size(filename, ec) > 0;
}
return false;
}
@@ -118,17 +121,18 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
// static
S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type)
{
+#if LL_WINDOWS
+ const auto filename = ll_convert<std::wstring>(LLDiskCache::metaDataToFilepath(file_id, file_type));
+#else
const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
+#endif
- S32 file_size = 0;
- llifstream file(filename, std::ios::binary);
- if (file.is_open())
+ boost::system::error_code ec;
+ if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec))
{
- file.seekg(0, std::ios::end);
- file_size = (S32)file.tellg();
+ return static_cast<S32>(boost::filesystem::file_size(filename, ec));
}
-
- return file_size;
+ return 0;
}
bool LLFileSystem::read(U8* buffer, S32 bytes)
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 6b14b68c78..1fb61673bd 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -27,10 +27,11 @@
#ifndef LL_LLIMAGE_H
#define LL_LLIMAGE_H
-#include "lluuid.h"
-#include "llstring.h"
+#include "llmutex.h"
#include "llpointer.h"
+#include "llstring.h"
#include "lltrace.h"
+#include "lluuid.h"
constexpr S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
constexpr S32 MAX_IMAGE_MIP = 12; // 4096x4096
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 9350901324..7cfadb889d 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -28,7 +28,7 @@
#include "llimagej2coj.h"
// this is defined so that we get static linking.
-#include <openjpeg-2.5/openjpeg.h>
+#include "openjpeg.h"
// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 3defad8f3b..f126accfb8 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -1017,10 +1017,9 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
if (i->first == INV_THUMBNAIL_LABEL)
{
const LLSD &thumbnail_map = i->second;
- const std::string w = INV_ASSET_ID_LABEL;
- if (thumbnail_map.has(w))
+ if (thumbnail_map.has(INV_ASSET_ID_LABEL))
{
- mThumbnailUUID = thumbnail_map[w];
+ mThumbnailUUID = thumbnail_map[INV_ASSET_ID_LABEL];
}
/* Example:
<key> asset_id </key>
@@ -1033,7 +1032,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
<integer> 1 </key>
*/
continue;
- }
+ }
if (i->first == INV_THUMBNAIL_ID_LABEL)
{
@@ -1044,10 +1043,9 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
if (i->first == INV_FAVORITE_LABEL)
{
const LLSD& favorite_map = i->second;
- const std::string w = INV_TOGGLED_LABEL;
- if (favorite_map.has(w))
+ if (favorite_map.has(INV_TOGGLED_LABEL))
{
- mFavorite = favorite_map[w].asBoolean();
+ mFavorite = favorite_map[INV_TOGGLED_LABEL].asBoolean();
}
continue;
}
@@ -1111,7 +1109,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
LLSD const &label = i->second;
if (label.isString())
{
- mType = LLAssetType::lookup(label.asString().c_str());
+ mType = LLAssetType::lookup(label.asStringRef().c_str());
}
else if (label.isInteger())
{
@@ -1126,7 +1124,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
LLSD const &label = i->second;
if (label.isString())
{
- mInventoryType = LLInventoryType::lookup(label.asString().c_str());
+ mInventoryType = LLInventoryType::lookup(label.asStringRef().c_str());
}
else if (label.isInteger())
{
@@ -1290,7 +1288,7 @@ void LLInventoryCategory::packMessage(LLMessageSystem* msg) const
bool LLInventoryCategory::fromLLSD(const LLSD& sd)
{
- std::string w;
+ std::string_view w;
w = INV_FOLDER_ID_LABEL_WS;
if (sd.has(w))
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 7eba9494a6..cf45f93168 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -158,6 +158,9 @@ public:
kdu_codestream* codestreamp);
~LLKDUDecodeState();
bool processTileDecode(F32 decode_time, bool limit_time = true);
+#ifdef LL_WINDOWS
+ bool processTileDecodeSEH(F32 decode_time, bool limit_time = true);
+#endif
private:
S32 mNumComponents;
@@ -282,10 +285,16 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
try
{
-
S32 data_size = base.getDataSize();
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
+ // Data sanity checks
+ // 0 data size appears to be valid.
+ if (data_size < 0 || data_size > 128 * 1024 * 1024) // 128MB
+ {
+ LLTHROW(KDUError(STRINGIZE("Invalid data size: " << data_size)));
+ }
+
//
// Initialization
//
@@ -385,7 +394,8 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
catch (std::bad_alloc&)
{
// we are in a thread, can't show an 'out of memory' here,
- // main thread will keep going
+ // as main thread will keep going
+ // Todo: should cause main thread to stop and show an error.
throw;
}
catch (...)
@@ -602,7 +612,11 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// Do the actual processing
F32 remaining_time = limit_time ? decode_time - decode_timer.getElapsedTimeF32().value() : 0.0f;
// This is where we do the actual decode. If we run out of time, return false.
+#ifdef LL_WINDOWS
+ if (mDecodeState->processTileDecodeSEH(remaining_time, limit_time))
+#else
if (mDecodeState->processTileDecode(remaining_time, limit_time))
+#endif
{
mDecodeState.reset();
}
@@ -615,6 +629,11 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
return false;
}
}
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Bad memory allocation in J2C KDU" << LL_ENDL;
+ }
catch (const KDUError& msg)
{
base.setLastError(msg.what());
@@ -1297,6 +1316,11 @@ all necessary level shifting, type conversion, rounding and truncation. */
LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
kdu_codestream* codestreamp)
{
+ if (!buf)
+ {
+ LLTHROW(KDUError("Null buffer passed to LLKDUDecodeState"));
+ }
+
S32 c;
mTile = tile;
@@ -1306,6 +1330,11 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
mNumComponents = tile.get_num_components();
llassert(mNumComponents <= 4);
+ if (mNumComponents <= 0 || mNumComponents > 4)
+ {
+ LL_WARNS() << "Invalid component count: " << mNumComponents << ", clamping to valid range" << LL_ENDL;
+ mNumComponents = llclamp(mNumComponents, 1, 4);
+ }
mUseYCC = tile.get_ycc();
for (c = 0; c < 4; ++c)
@@ -1358,6 +1387,20 @@ LLKDUDecodeState::~LLKDUDecodeState()
mTile.close();
}
+#ifdef LL_WINDOWS
+bool LLKDUDecodeState::processTileDecodeSEH(F32 decode_time, bool limit_time)
+{
+ __try
+ {
+ return processTileDecode(decode_time, limit_time);
+ }
+ __except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ return false;
+ }
+}
+#endif
+
bool LLKDUDecodeState::processTileDecode(F32 decode_time, bool limit_time)
/* Decompresses a tile, writing the data into the supplied byte buffer.
The buffer contains interleaved image components, if there are any.
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 0cf5ecd3d0..4660026d40 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -912,7 +912,7 @@ bool LLProfile::generate(const LLProfileParams& params, bool path_open,F32 detai
case LL_PCODE_HOLE_CIRCLE:
case LL_PCODE_HOLE_SAME:
default:
- addHole(params, true, circle_detail, 0, hollow, 1.f);
+ addHole(params, false, circle_detail, 0, hollow, 1.f);
break;
}
}
@@ -4943,9 +4943,17 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
mOctree(NULL),
mOctreeTriangles(NULL)
{
- mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
- mCenter = mExtents+2;
- *this = src;
+ try
+ {
+ mExtents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * 3);
+ mCenter = mExtents + 2;
+ *this = src;
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLVolume") << "Bad memory allocation in LLVolumeFace" << LL_ENDL;
+ }
}
LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
@@ -5163,7 +5171,7 @@ void LLVolumeFace::remap()
// Documentation for meshopt_generateVertexRemapMulti claims that remap should use vertice count
// but all examples use indice count. There are out of bounds crashes when using vertice count.
// To be on the safe side use bigger of the two.
- std::vector<unsigned int> remap(llmax(mNumIndices, mNumVertices));
+ std::vector<unsigned int> remap(llmax(mNumIndices, mNumVertices), 0);
S32 remap_vertices_count = static_cast<S32>(LLMeshOptimizer::generateRemapMultiU16(&remap[0],
mIndices,
mNumIndices,
@@ -5681,7 +5689,12 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
catch (std::bad_alloc&)
{
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL;
+ LL_ERRS("LLVolume") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL;
+ }
+ catch (...)
+ {
+ LL_WARNS_ONCE("LLVolume") << "Mikktspace::genTangSpace() failed" << LL_ENDL;
+ return false;
}
@@ -5703,7 +5716,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
catch (std::bad_alloc&)
{
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL;
+ LL_ERRS("LLVOLUME") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL;
}
U32 stream_count = data.w.empty() ? 4 : 5;
@@ -5720,7 +5733,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
catch (std::bad_alloc&)
{
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL;
+ LL_ERRS("LLVolume") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL;
}
}
@@ -5732,7 +5745,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
if (mNumVertices == 0)
{
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("LLCoros") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL;
+ LL_ERRS("LLVolume") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL;
}
if (!data.w.empty())
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
index bb0c94d513..d8f649140f 100644
--- a/indra/llmath/llvolumemgr.cpp
+++ b/indra/llmath/llvolumemgr.cpp
@@ -25,6 +25,7 @@
#include "linden_common.h"
+#include "llmutex.h"
#include "llvolumemgr.h"
#include "llvolume.h"
diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp
index 7339454367..76d51fdad0 100644
--- a/indra/llmeshoptimizer/llmeshoptimizer.cpp
+++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp
@@ -171,7 +171,6 @@ size_t LLMeshOptimizer::generateRemapMultiU32(
// but providing indices helps with removing unused vertices
U64 indeces_cmp = indices ? index_count : vertex_count;
- // meshopt_generateVertexRemapMulti will throw an assert if (indices[i] >= vertex_count)
return meshopt_generateVertexRemapMulti(&remap[0], indices, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0]));
}
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 4c3acb27f4..b6a98575f9 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -453,6 +453,7 @@ bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetTyp
bool exists = LLFileSystem::getExists(uuid, type);
if (exists)
{
+ LL_PROFILE_ZONE_SCOPED;
LLFileSystem file(uuid, type);
U32 size = file.getSize();
if (size > 0)
@@ -562,7 +563,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
if (callback == tmp->mDownCallback && user_data == tmp->mUserData)
{
// this is a duplicate from the same subsystem - throw it away
- LL_WARNS("AssetStorage") << "Discarding duplicate request for asset " << uuid
+ LL_DEBUGS("AssetStorage") << "Discarding duplicate request for asset " << uuid
<< "." << LLAssetType::lookup(type) << LL_ENDL;
return;
}
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index ebafc53a4d..86b36315dc 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -276,7 +276,7 @@ void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &h
// Provide some fallback for agents that return errors
void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
{
- std::map<LLUUID,LLAvatarName>::iterator existing = mCache.find(agent_id);
+ cache_t::iterator existing = mCache.find(agent_id);
if (existing == mCache.end())
{
// there is no existing cache entry, so make a temporary name from legacy
@@ -311,7 +311,7 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName&
bool updated_account = true; // assume obsolete value for new arrivals by default
- std::map<LLUUID, LLAvatarName>::iterator it = mCache.find(agent_id);
+ cache_t::iterator it = mCache.find(agent_id);
if (it != mCache.end()
&& (*it).second.getAccountName() == av_name.getAccountName())
{
@@ -418,7 +418,7 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
// Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy
// protocol, we do not get an expiration date for each name and there's no reason to ask the
// data again and again so we set the expiration time to the largest value admissible.
- std::map<LLUUID,LLAvatarName>::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id);
+ cache_t::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id);
LLAvatarName& av_name = av_record->second;
av_name.setExpires(MAX_UNREFRESHED_TIME);
}
@@ -631,7 +631,7 @@ bool LLAvatarNameCache::getName(const LLUUID& agent_id, LLAvatarName *av_name)
if (mRunning)
{
// ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ cache_t::iterator it = mCache.find(agent_id);
if (it != mCache.end())
{
*av_name = it->second;
@@ -682,7 +682,7 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::getNameCallback(cons
if (mRunning)
{
// ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ cache_t::iterator it = mCache.find(agent_id);
if (it != mCache.end())
{
const LLAvatarName& av_name = it->second;
@@ -753,13 +753,11 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
LLUUID LLAvatarNameCache::findIdByName(const std::string& name)
{
- std::map<LLUUID, LLAvatarName>::iterator it;
- std::map<LLUUID, LLAvatarName>::iterator end = mCache.end();
- for (it = mCache.begin(); it != end; ++it)
+ for (const auto& [id, avatar_name] : mCache)
{
- if (it->second.getUserName() == name)
+ if (avatar_name.getUserName() == name)
{
- return it->first;
+ return id;
}
}
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 0ddaee2aa1..6743943495 100644
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -30,8 +30,10 @@
#include "llavatarname.h" // for convenience
#include "llsingleton.h"
+#include "lluuid.h"
#include <boost/signals2.hpp>
#include <set>
+#include <unordered_map>
class LLSD;
class LLUUID;
@@ -161,23 +163,23 @@ private:
std::string mNameLookupURL;
// Accumulated agent IDs for next query against service
- typedef std::set<LLUUID> ask_queue_t;
+ using ask_queue_t = std::set<LLUUID>;
ask_queue_t mAskQueue;
// Agent IDs that have been requested, but with no reply.
// Maps agent ID to frame time request was made.
- typedef std::map<LLUUID, F64> pending_queue_t;
+ using pending_queue_t = std::unordered_map<LLUUID, F64>;
pending_queue_t mPendingQueue;
// Callbacks to fire when we received a name.
// May have multiple callbacks for a single ID, which are
// represented as multiple slots bound to the signal.
// Avoid copying signals via pointers.
- typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
+ using signal_map_t = std::unordered_map<LLUUID, callback_signal_t*>;
signal_map_t mSignalMap;
// The cache at last, i.e. avatar names we know about.
- typedef std::map<LLUUID, LLAvatarName> cache_t;
+ using cache_t = std::unordered_map<LLUUID, LLAvatarName>;
cache_t mCache;
// Time when unrefreshed cached names were checked last.
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 56dfaef873..95b7bb8c3d 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -179,12 +179,11 @@ void ReplySender::flush()
}
}
-
-typedef std::set<LLUUID> AskQueue;
-typedef std::list<PendingReply*> ReplyQueue;
-typedef std::map<LLUUID,U32> PendingQueue;
-typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
-typedef std::map<std::string, LLUUID> ReverseCache;
+using AskQueue = std::set<LLUUID>;
+using ReplyQueue = std::list<PendingReply*>;
+using PendingQueue = std::unordered_map<LLUUID, U32>;
+using Cache = std::unordered_map<LLUUID, LLCacheNameEntry*>;
+using ReverseCache = std::unordered_map<std::string, LLUUID>;
class LLCacheName::Impl
{
@@ -214,7 +213,7 @@ public:
Impl(LLMessageSystem* msg);
~Impl();
- bool getName(const LLUUID& id, std::string& first, std::string& last, std::map<std::string, std::string>& default_names);
+ bool getName(const LLUUID& id, std::string& first, std::string& last, cache_map_t& default_names);
boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
void addPending(const LLUUID& id, const LLHost& host);
@@ -401,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
}
-bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last, std::map<std::string, std::string>& default_names)
+bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last, cache_map_t &default_names)
{
if(id.isNull())
{
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 609387b6de..a333eac0f5 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -136,7 +136,8 @@ public:
void localizeCacheName(std::string key, std::string value);
private:
- std::map<std::string, std::string> mCacheName;
+ using cache_map_t = std::unordered_map<std::string, std::string>;
+ cache_map_t mCacheName;
class Impl;
Impl& impl;
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index b24e5e4fcc..647064f607 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -37,6 +37,7 @@
#include "llsdserialize.h"
#include "boost/json.hpp" // Boost.Json
#include "llfilesystem.h"
+#include "workqueue.h"
#include "message.h" // for getting the port
@@ -295,41 +296,73 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
}
else
{
- try
+ constexpr size_t MAX_BODY_SIZE_THRESHOLD = 65536;
+ bool posted = false;
+ // Some messsages (ex: AISAPI) can return large bodies.
+ // If the body is larger than our threshold, post the
+ // parsing to the general queue to avoid stalling the
+ // main thread.
+ if (response->getBodySize() > MAX_BODY_SIZE_THRESHOLD)
{
- result = this->handleSuccess(response, status);
- }
- catch (std::bad_alloc&)
- {
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL;
- }
- }
+ response->addRef();
- buildStatusEntry(response, status, result);
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General");
+ posted = main_queue->postTo(
+ general_queue,
+ [handler = shared_from_this(), response, status]() // Work done on general queue
+ {
+ std::pair<LLSD, LLCore::HttpStatus> result;
+ result.second = status;
+ try
+ {
+ result.first = handler->handleSuccess(response, result.second);
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling (threaded)." << LL_ENDL;
+ }
+ // LLSD is not thread safe! Be carefull with moving the result around.
+ return result;
+ },
+ [handler = shared_from_this(), response](std::pair<LLSD, LLCore::HttpStatus> result) mutable // Callback to main thread
+ {
+ handler->replyPost(response, result.second, result.first);
+ response->release();
+ });
- if (!status)
- {
- LLSD &httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS];
+ if (posted)
+ {
+ // Thread will do the cleanup and notify the pump. Done.
+ return;
+ }
+ else
+ {
+ // For whatever reason, failed to post, clean up and
+ // do the work on the main thread.
+ response->release();
+ }
+ }
- LLCore::BufferArray *body = response->getBody();
- LLCore::BufferArrayStream bas(body);
- LLSD::String bodyData;
- bodyData.reserve(response->getBodySize());
- bas >> std::noskipws;
- bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
- httpStatus["error_body"] = LLSD(bodyData);
- if (getBoolSetting(HTTP_LOGBODY_KEY))
+ if (!posted)
{
- // commenting out, but keeping since this can be useful for debugging
- LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
+ try
+ {
+ result = this->handleSuccess(response, status);
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL;
+ }
}
}
- mReplyPump.post(result);
+ replyPost(response, status, result);
}
-void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result)
+void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) const
{
LLSD httpresults = LLSD::emptyMap();
@@ -357,6 +390,31 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H
result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults;
}
+void HttpCoroHandler::replyPost(LLCore::HttpResponse* response, LLCore::HttpStatus &status, LLSD& result)
+{
+ buildStatusEntry(response, status, result);
+
+ if (!status)
+ {
+ LLSD& httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS];
+
+ LLCore::BufferArray* body = response->getBody();
+ LLCore::BufferArrayStream bas(body);
+ LLSD::String bodyData;
+ bodyData.reserve(response->getBodySize());
+ bas >> std::noskipws;
+ bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+ httpStatus["error_body"] = LLSD(bodyData);
+ if (getBoolSetting(HTTP_LOGBODY_KEY))
+ {
+ // commenting out, but keeping since this can be useful for debugging
+ LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
+ }
+ }
+
+ mReplyPump.post(result);
+}
+
void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result)
{
result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast<LLSD::Boolean>(status);
@@ -389,8 +447,8 @@ public:
HttpCoroLLSDHandler(LLEventStream &reply);
protected:
- virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
- virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success);
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const;
+ virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const;
};
//-------------------------------------------------------------------------
@@ -400,7 +458,7 @@ HttpCoroLLSDHandler::HttpCoroLLSDHandler(LLEventStream &reply):
}
-LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const
{
LLSD result;
@@ -465,7 +523,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
return result;
}
-LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success)
+LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success) const
{
success = true;
if (response->getBodySize() == 0)
@@ -496,8 +554,8 @@ class HttpCoroRawHandler : public HttpCoroHandler
public:
HttpCoroRawHandler(LLEventStream &reply);
- virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
- virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success);
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const;
+ virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const;
};
//-------------------------------------------------------------------------
@@ -506,7 +564,7 @@ HttpCoroRawHandler::HttpCoroRawHandler(LLEventStream &reply):
{
}
-LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const
{
LLSD result = LLSD::emptyMap();
@@ -552,7 +610,7 @@ LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::
return result;
}
-LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success)
+LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success) const
{
success = true;
return LLSD();
@@ -571,8 +629,8 @@ class HttpCoroJSONHandler : public HttpCoroHandler
public:
HttpCoroJSONHandler(LLEventStream &reply);
- virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
- virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success);
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const;
+ virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const;
};
//-------------------------------------------------------------------------
@@ -581,7 +639,7 @@ HttpCoroJSONHandler::HttpCoroJSONHandler(LLEventStream &reply) :
{
}
-LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const
{
LLSD result = LLSD::emptyMap();
@@ -607,7 +665,7 @@ LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
return result;
}
-LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success)
+LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success) const
{
success = true;
BufferArray * body(response->getBody());
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index 3dbfd6f00d..3072f78911 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -259,7 +259,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ
/// +- ["url"] - The URL used to make the call.
/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
///
-class HttpCoroHandler : public LLCore::HttpHandler
+class HttpCoroHandler : public LLCore::HttpHandler, public std::enable_shared_from_this<HttpCoroHandler>
{
public:
@@ -279,11 +279,12 @@ public:
protected:
/// this method may modify the status value
- virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) = 0;
- virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) = 0;
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const = 0;
+ virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const = 0;
private:
- void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result);
+ void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) const;
+ void replyPost(LLCore::HttpResponse* response, LLCore::HttpStatus& status, LLSD& result);
LLEventStream &mReplyPump;
};
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index e911150787..ecd0b4ee8d 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -289,32 +289,46 @@ bool LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const c
}
-bool LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
+bool LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name)
{
if (!verifyLength(4, name))
{
LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
+ out_size = 0;
return false;
}
- htolememcpy(&size, mCurBufferp, MVT_S32, 4);
+ if (value_size < 0)
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData passed negative buffer size, aborting!" << LL_ENDL;
+ out_size = 0;
+ return false;
+ }
+
+ htolememcpy(&out_size, mCurBufferp, MVT_S32, 4);
- if (size < 0)
+ if (out_size < 0)
{
LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData unpacked invalid size, aborting!" << LL_ENDL;
+ out_size = 0;
return false;
}
mCurBufferp += 4;
- if (!verifyLength(size, name))
+ if (!verifyLength(out_size, name))
{
LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
return false;
}
+ S32 copy_size = llmin(out_size, value_size);
+ htolememcpy(value, mCurBufferp, MVT_VARIABLE, copy_size);
+ mCurBufferp += out_size;
- htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
- mCurBufferp += size;
+ if (value_size < out_size)
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData buffer too small for data, truncating!" << LL_ENDL;
+ }
return true;
}
@@ -836,21 +850,34 @@ bool LLDataPackerAsciiBuffer::packBinaryData(const U8 *value, S32 size, const ch
}
-bool LLDataPackerAsciiBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
+bool LLDataPackerAsciiBuffer::unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name)
{
bool success = true;
char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
if (!getValueStr(name, valuestr, DP_BUFSIZE))
{
+ out_size = 0;
+ return false;
+ }
+
+ if (value_size < 0)
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData passed negative buffer size, aborting!" << LL_ENDL;
+ out_size = 0;
return false;
}
char *cur_pos = &valuestr[0];
- sscanf(valuestr,"%010d", &size);
+ sscanf(valuestr,"%010d", &out_size);
cur_pos += 11;
+ S32 max_bytes = llmin(out_size, value_size);
+ if (max_bytes != out_size)
+ {
+ LL_WARNS() << "LLDataPackerAsciiBuffer::unpackBinaryData: buffer too small for data, truncating!" << LL_ENDL;
+ }
S32 i;
- for (i = 0; i < size; i++)
+ for (i = 0; i < max_bytes; i++)
{
S32 val;
sscanf(cur_pos,"%02x", &val);
@@ -1634,28 +1661,40 @@ bool LLDataPackerAsciiFile::packBinaryData(const U8 *value, S32 size, const char
}
-bool LLDataPackerAsciiFile::unpackBinaryData(U8 *value, S32 &size, const char *name)
+bool LLDataPackerAsciiFile::unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name)
{
- bool success = true;
char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
if (!getValueStr(name, valuestr, DP_BUFSIZE))
{
+ out_size = 0;
+ return false;
+ }
+
+ if (value_size < 0)
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData passed negative buffer size, aborting!" << LL_ENDL;
+ out_size = 0;
return false;
}
char *cur_pos = &valuestr[0];
- sscanf(valuestr,"%010d", &size);
+ sscanf(valuestr,"%010d", &out_size);
cur_pos += 11;
+ S32 max_bytes = llmin(out_size, value_size);
+ if (max_bytes != out_size)
+ {
+ LL_WARNS() << "LLDataPackerAsciiBuffer::unpackBinaryData: buffer too small for data, truncating!" << LL_ENDL;
+ }
S32 i;
- for (i = 0; i < size; i++)
+ for (i = 0; i < max_bytes; i++)
{
S32 val;
sscanf(cur_pos,"%02x", &val);
value[i] = val;
cur_pos += 3;
}
- return success;
+ return true;
}
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h
index 167c102b43..5ac45356cf 100644
--- a/indra/llmessage/lldatapacker.h
+++ b/indra/llmessage/lldatapacker.h
@@ -49,7 +49,7 @@ public:
virtual bool unpackString(std::string& value, const char *name) = 0;
virtual bool packBinaryData(const U8 *value, S32 size, const char *name) = 0;
- virtual bool unpackBinaryData(U8 *value, S32 &size, const char *name) = 0;
+ virtual bool unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name) = 0;
// Constant size binary data packing
virtual bool packBinaryDataFixed(const U8 *value, S32 size, const char *name) = 0;
@@ -135,7 +135,7 @@ public:
/*virtual*/ bool unpackString(std::string& value, const char *name);
/*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name);
// Constant size binary data packing
/*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
@@ -246,7 +246,7 @@ public:
/*virtual*/ bool unpackString(std::string& value, const char *name);
/*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name);
// Constant size binary data packing
/*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
@@ -378,7 +378,7 @@ public:
/*virtual*/ bool unpackString(std::string& value, const char *name);
/*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 value_size, S32 &out_size, const char *name);
/*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
/*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp
index 78876f9f36..b7c4b5e591 100644
--- a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp
+++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp
@@ -75,10 +75,7 @@ LLCDResult LLConvexDecompositionVHACD::quitSystem()
LLConvexDecompositionVHACD::LLConvexDecompositionVHACD()
{
- //Create our vhacd instance and setup default parameters
- mVHACD = VHACD::CreateVHACD();
-
- mVHACDParameters.m_callback = &mVHACDCallback;
+ // Setup default parameters
mVHACDParameters.m_logger = &mVHACDLogger;
mDecompStages[0].mName = "Analyze";
@@ -206,27 +203,33 @@ LLConvexDecompositionVHACD::LLConvexDecompositionVHACD()
LLConvexDecompositionVHACD::~LLConvexDecompositionVHACD()
{
- mBoundDecomp = nullptr;
- mDecompData.clear();
-
- mVHACD->Release();
+ {
+ LLMutexLock lock(&mDecompDataMutex);
+ mBoundDecompID = INVALID_DECOMP_ID;
+ mDecompData.clear();
+ }
}
void LLConvexDecompositionVHACD::genDecomposition(int& decomp)
{
- int new_decomp_id = static_cast<int>(mDecompData.size()) + 1;
- mDecompData[new_decomp_id] = LLDecompData();
- decomp = new_decomp_id;
+ LLMutexLock lock(&mDecompDataMutex);
+
+ mDecompData[mNextDecompID] = std::make_shared<LLDecompData>();
+ decomp = mNextDecompID;
+
+ ++mNextDecompID; // Increment decomposition ID. Never reuse to protect downstream consumers from misuse
}
void LLConvexDecompositionVHACD::deleteDecomposition(int decomp)
{
+ LLMutexLock lock(&mDecompDataMutex);
+
auto iter = mDecompData.find(decomp);
if (iter != mDecompData.end())
{
- if (mBoundDecomp == &iter->second)
+ if (mBoundDecompID == decomp)
{
- mBoundDecomp = nullptr;
+ mBoundDecompID = INVALID_DECOMP_ID;
}
mDecompData.erase(iter);
}
@@ -234,29 +237,48 @@ void LLConvexDecompositionVHACD::deleteDecomposition(int decomp)
void LLConvexDecompositionVHACD::bindDecomposition(int decomp)
{
- auto iter = mDecompData.find(decomp);
- if (iter != mDecompData.end())
+ LLMutexLock lock(&mDecompDataMutex);
+
+ if (mDecompData.contains(decomp))
{
- mBoundDecomp = &iter->second;
+ mBoundDecompID = decomp;
}
else
{
LL_WARNS() << "Failed to bind unknown decomposition: " << decomp << LL_ENDL;
- mBoundDecomp = nullptr;
+ mBoundDecompID = INVALID_DECOMP_ID;
}
}
+LLConvexDecompositionVHACD::data_ptr_t LLConvexDecompositionVHACD::getBoundDecomp()
+{
+ data_ptr_t bound_decomp;
+ {
+ LLMutexLock lock(&mDecompDataMutex);
+ auto it = mDecompData.find(mBoundDecompID);
+ if (it != mDecompData.end())
+ {
+ bound_decomp = it->second; // Take a copy of the shared_ptr to avoid potential deletion
+ }
+ }
+ return bound_decomp;
+}
+
LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, float val)
{
- if (name == std::string("Num Hulls"))
+ LLMutexLock lock(&mParamsMutex);
+
+ using namespace std::literals;
+
+ if (name == "Num Hulls"sv)
{
mVHACDParameters.m_maxConvexHulls = llclamp(ll_round(val), 1, MAX_HULLS);
}
- else if (name == std::string("Num Vertices"))
+ else if (name == "Num Vertices"sv)
{
mVHACDParameters.m_maxNumVerticesPerCH = llclamp(ll_round(val), 3, MAX_VERTICES_PER_HULL);
}
- else if (name == std::string("Error Tolerance"))
+ else if (name == "Error Tolerance"sv)
{
mVHACDParameters.m_minimumVolumePercentErrorAllowed = val;
}
@@ -270,11 +292,15 @@ LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, bool val)
LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val)
{
- if (name == std::string("Fill Mode"))
+ LLMutexLock lock(&mParamsMutex);
+
+ using namespace std::literals;
+
+ if (name == "Fill Mode"sv)
{
mVHACDParameters.m_fillMode = (VHACD::FillMode)val;
}
- else if (name == std::string("Voxel Resolution"))
+ else if (name == "Voxel Resolution"sv)
{
mVHACDParameters.m_resolution = val;
}
@@ -283,19 +309,21 @@ LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val)
LLCDResult LLConvexDecompositionVHACD::setMeshData( const LLCDMeshData* data, bool vertex_based )
{
- if (!mBoundDecomp)
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp)
{
return LLCD_NULL_PTR;
}
- return mBoundDecomp->mSourceMesh.from(data, vertex_based);
+ return bound_decomp->mSourceMesh.from(data, vertex_based);
}
LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackFunc callback )
{
if (stage == 0)
{
- mVHACDCallback.setCallbackFunc(callback);
+ LLMutexLock lock(&mParamsMutex);
+ mCurrentCallbackFunc = callback;
return LLCD_OK;
}
else
@@ -306,44 +334,68 @@ LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackF
LLCDResult LLConvexDecompositionVHACD::executeStage(int stage)
{
- if (!mBoundDecomp)
+ if (stage != 0)
+ {
+ return LLCD_INVALID_STAGE;
+ }
+
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp)
{
return LLCD_NULL_PTR;
}
- if (stage != 0)
+ bound_decomp->mDecomposedHulls.clear();
+
+ const auto& decomp_mesh = bound_decomp->mSourceMesh;
+
+ VHACDCallback callbacks;
+ VHACD::IVHACD::Parameters current_params;
{
- return LLCD_INVALID_STAGE;
+ LLMutexLock lock(&mParamsMutex);
+
+ current_params = mVHACDParameters;
+ callbacks.setCallbackFunc(mCurrentCallbackFunc);
+ }
+ current_params.m_callback = &callbacks;
+
+ auto vhacd_impl = VHACD::CreateVHACD();
+ if (!vhacd_impl)
+ {
+ LL_WARNS() << "Failed to create VHACD instance" << LL_ENDL;
+ return LLCD_NULL_PTR;
}
- mBoundDecomp->mDecomposedHulls.clear();
- const auto& decomp_mesh = mBoundDecomp->mSourceMesh;
- if (!mVHACD->Compute((const double* const)decomp_mesh.mVertices.data(), static_cast<uint32_t>(decomp_mesh.mVertices.size()), (const uint32_t* const)decomp_mesh.mIndices.data(), static_cast<uint32_t>(decomp_mesh.mIndices.size()), mVHACDParameters))
+ if (!vhacd_impl->Compute((const double*)decomp_mesh.mVertices.data(), static_cast<uint32_t>(decomp_mesh.mVertices.size()),
+ (const uint32_t*)decomp_mesh.mIndices.data(), static_cast<uint32_t>(decomp_mesh.mIndices.size()),
+ current_params))
{
+ vhacd_impl->Release();
return LLCD_INVALID_HULL_DATA;
}
- uint32_t num_nulls = mVHACD->GetNConvexHulls();
- if (num_nulls == 0)
+ uint32_t num_convex_hulls = vhacd_impl->GetNConvexHulls();
+ if (num_convex_hulls == 0)
{
+ vhacd_impl->Release();
return LLCD_INVALID_HULL_DATA;
}
- for (uint32_t i = 0; num_nulls > i; ++i)
+ for (uint32_t i = 0; num_convex_hulls > i; ++i)
{
VHACD::IVHACD::ConvexHull ch;
- if (!mVHACD->GetConvexHull(i, ch))
+ if (!vhacd_impl->GetConvexHull(i, ch))
continue;
LLConvexMesh out_mesh;
out_mesh.setVertices(ch.m_points);
out_mesh.setIndices(ch.m_triangles);
- mBoundDecomp->mDecomposedHulls.push_back(std::move(out_mesh));
+ bound_decomp->mDecomposedHulls.push_back(std::move(out_mesh));
}
- mVHACD->Clean();
+ vhacd_impl->Release();
return LLCD_OK;
}
@@ -351,19 +403,21 @@ LLCDResult LLConvexDecompositionVHACD::executeStage(int stage)
LLCDResult LLConvexDecompositionVHACD::buildSingleHull()
{
LL_INFOS() << "Building single hull mesh" << LL_ENDL;
- if (!mBoundDecomp || mBoundDecomp->mSourceMesh.mVertices.empty())
+
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp || bound_decomp->mSourceMesh.mVertices.empty())
{
return LLCD_NULL_PTR;
}
- mBoundDecomp->mSingleHullMesh.clear();
+ bound_decomp->mSingleHullMesh.clear();
VHACD::QuickHull quickhull;
- uint32_t num_tris = quickhull.ComputeConvexHull(mBoundDecomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL);
+ uint32_t num_tris = quickhull.ComputeConvexHull(bound_decomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL);
if (num_tris > 0)
{
- mBoundDecomp->mSingleHullMesh.setVertices(quickhull.GetVertices());
- mBoundDecomp->mSingleHullMesh.setIndices(quickhull.GetIndices());
+ bound_decomp->mSingleHullMesh.setVertices(quickhull.GetVertices());
+ bound_decomp->mSingleHullMesh.setIndices(quickhull.GetIndices());
return LLCD_OK;
}
@@ -373,29 +427,31 @@ LLCDResult LLConvexDecompositionVHACD::buildSingleHull()
int LLConvexDecompositionVHACD::getNumHullsFromStage(int stage)
{
- if (!mBoundDecomp || stage != 0)
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp || stage != 0)
{
return 0;
}
- return narrow(mBoundDecomp->mDecomposedHulls.size());
+ return narrow(bound_decomp->mDecomposedHulls.size());
}
LLCDResult LLConvexDecompositionVHACD::getSingleHull( LLCDHull* hullOut )
{
memset( hullOut, 0, sizeof(LLCDHull) );
- if (!mBoundDecomp)
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp)
{
return LLCD_NULL_PTR;
}
- if (mBoundDecomp->mSingleHullMesh.vertices.empty())
+ if (bound_decomp->mSingleHullMesh.vertices.empty())
{
return LLCD_INVALID_HULL_DATA;
}
- mBoundDecomp->mSingleHullMesh.to(hullOut);
+ bound_decomp->mSingleHullMesh.to(hullOut);
return LLCD_OK;
}
@@ -403,7 +459,8 @@ LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LL
{
memset( hullOut, 0, sizeof(LLCDHull) );
- if (!mBoundDecomp)
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp)
{
return LLCD_NULL_PTR;
}
@@ -413,19 +470,21 @@ LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LL
return LLCD_INVALID_STAGE;
}
- if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull)
+ if (bound_decomp->mDecomposedHulls.empty() || S32(bound_decomp->mDecomposedHulls.size()) <= hull)
{
return LLCD_REQUEST_OUT_OF_RANGE;
}
- mBoundDecomp->mDecomposedHulls[hull].to(hullOut);
+ bound_decomp->mDecomposedHulls[hull].to(hullOut);
return LLCD_OK;
}
LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut )
{
memset( meshDataOut, 0, sizeof(LLCDMeshData));
- if (!mBoundDecomp)
+
+ data_ptr_t bound_decomp = getBoundDecomp();
+ if (!bound_decomp)
{
return LLCD_NULL_PTR;
}
@@ -435,12 +494,12 @@ LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LL
return LLCD_INVALID_STAGE;
}
- if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull)
+ if (bound_decomp->mDecomposedHulls.empty() || S32(bound_decomp->mDecomposedHulls.size()) <= hull)
{
return LLCD_REQUEST_OUT_OF_RANGE;
}
- mBoundDecomp->mDecomposedHulls[hull].to(meshDataOut);
+ bound_decomp->mDecomposedHulls[hull].to(meshDataOut);
return LLCD_OK;
}
diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h
index 675356629c..27c867704e 100644
--- a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h
+++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h
@@ -31,6 +31,7 @@
#include "llconvexdecomposition.h"
#include "llsingleton.h"
#include "llmath.h"
+#include "llmutex.h"
#include <vector>
@@ -323,14 +324,25 @@ private:
std::vector<LLConvexMesh> mDecomposedHulls;
};
- std::unordered_map<int, LLDecompData> mDecompData;
+ using data_ptr_t = std::shared_ptr<LLDecompData>;
- LLDecompData* mBoundDecomp = nullptr;
+ data_ptr_t getBoundDecomp();
+
+ // MUST lock before accessing mDecompData mBoundDecompID or mNextDecompID
+ LLMutex mDecompDataMutex;
+
+ static constexpr int INVALID_DECOMP_ID = -1;
+
+ int mBoundDecompID = INVALID_DECOMP_ID;
+ int mNextDecompID = 0; // Only for use inside genDecomposition.
+
+ std::unordered_map<int, data_ptr_t> mDecompData;
- VHACD::IVHACD* mVHACD = nullptr;
- VHACDCallback mVHACDCallback;
VHACDLogger mVHACDLogger;
+
+ LLMutex mParamsMutex;
VHACD::IVHACD::Parameters mVHACDParameters;
+ llcdCallbackFunc mCurrentCallbackFunc;
LLConvexMesh mMeshFromHullData;
LLConvexMesh mSingleHullMeshFromMeshData;
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 53a338b3d6..6ab378f30f 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -168,6 +168,7 @@ void LLPluginClassMedia::reset()
void LLPluginClassMedia::idle(void)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;
if(mPlugin)
{
mPlugin->idle();
@@ -1015,7 +1016,7 @@ void LLPluginClassMedia::enableMediaPluginDebugging( bool enable )
sendMessage( message );
}
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
void LLPluginClassMedia::enablePipeWireVolumeCatcher( bool enable )
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_pipewire_volume_catcher");
@@ -1658,3 +1659,15 @@ void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
}
+
+void LLPluginClassMedia::forceRenderRefresh()
+{
+ // Force layout recalculation by briefly hiding/showing the web content
+ // Used to clear black screen issues after resize, see #5607
+ const std::string refresh_script =
+ "document.documentElement.style.visibility='hidden';"
+ "document.documentElement.offsetHeight;"
+ "document.documentElement.style.visibility='';";
+
+ executeJavaScript(refresh_script);
+}
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 6c512003cc..944108aa10 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -134,7 +134,7 @@ public:
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
void enablePipeWireVolumeCatcher( bool enable );
#endif
@@ -356,6 +356,8 @@ public:
std::shared_ptr<LLPluginClassMedia> getSharedPtr() { return std::dynamic_pointer_cast<LLPluginClassMedia>(shared_from_this()); } // due to enable_shared_from_this
+ void forceRenderRefresh();
+
protected:
LLPluginClassMediaOwner *mOwner;
diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt
index 38f4c92b09..80356b6b51 100644
--- a/indra/llplugin/slplugin/CMakeLists.txt
+++ b/indra/llplugin/slplugin/CMakeLists.txt
@@ -61,6 +61,13 @@ elseif (DARWIN)
)
endif ()
+if (CMAKE_BUILD_TYPE MATCHES Release AND (CMAKE_CXX_COMPILER_ID STREQUAL Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU))
+ add_custom_command(
+ TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_STRIP} ${PROJECT_NAME}
+ )
+endif ()
+
if (BUILD_SHARED_LIBS)
set_target_properties(SLPlugin PROPERTIES LINK_FLAGS_RELEASE
"${LINK_FLAGS_RELEASE} -Wl,--allow-shlib-undefined")
@@ -69,6 +76,8 @@ endif ()
if (INSTALL)
if (DARWIN OR WINDOWS)
install(TARGETS ${PROJECT_NAME} DESTINATION .)
+ elseif (${LINUX_DISTRO} MATCHES freedesktop)
+ install(TARGETS ${PROJECT_NAME} DESTINATION libexec)
elseif (${LINUX_DISTRO} MATCHES arch)
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${VIEWER_BINARY_NAME})
else ()
diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp
index 930222e3db..764ab222ad 100644
--- a/indra/llprimitive/llgltfmaterial.cpp
+++ b/indra/llprimitive/llgltfmaterial.cpp
@@ -214,7 +214,7 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const
// to WriteGltfSceneToStream in the viewer.
gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false);
- return str.str();
+ return std::move(str).str();
}
void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
@@ -924,6 +924,34 @@ void LLGLTFMaterial::updateTextureTracking()
// for material overrides editor will set it
}
+// Test cases:
+// Case 1.
+// Input: scale 1.0,1.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0.349066;
+// Expected output: scale 1.0,1.0; Offset horizontal 0.201, Offset vertical -0.141 Rotation -0.349066;
+// Case 2.
+// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.1 Rotation 0;
+// Expected output: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical -0.1 Rotation -0;
+// Case 3.
+// Input: scale 1.0,1.0; Offset horizontal 0.1, Offset vertical 0.2 Rotation 0.349066;
+// Expected output: scale 1.0,1.0; Offset horizontal 0.295, Offset vertical -0.345 Rotation -0.349066;
+// Case 4.
+// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.0 Rotation 0.349066;
+// Expected output: scale 1.0,1.0; Offset horizontal 0.701, Offset vertical -0.141 Rotation -0.349066;
+// Case 5.
+// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation -1.57079637
+// Expected output: scale 15.0,10.0; Offset horizontal 7.5, Offset vertical -4.0 Rotation 1.57079637;
+// Case 6.
+// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0
+// Expected output: scale 10.0,15.0; Offset horizontal 0.5, Offset vertical .0 Rotation 0;
+// Case 7.
+// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation -0.785398163
+// Expected output: scale 12.74,12.74; Offset horizontal 0.5, Offset vertical .0 Rotation 0.785398163;
+//
+// Legacy offsets are right to left and top to bottom.
+// PBR offsets are right to left and bottom to top.
+//
+// Legacy rotation is relative to face's center counter clockwise,
+// PBR rotation is relative to top-left corner, clockwise
void LLGLTFMaterial::convertTextureTransformToPBR(
F32 tex_scale_s,
F32 tex_scale_t,
@@ -934,23 +962,108 @@ void LLGLTFMaterial::convertTextureTransformToPBR(
LLVector2& pbr_offset,
F32& pbr_rotation)
{
- pbr_scale.set(tex_scale_s, tex_scale_t);
- pbr_rotation = -(tex_rotation) / 2.f;
- const F32 adjusted_offset_s = tex_offset_s;
- const F32 adjusted_offset_t = -tex_offset_t;
- F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s);
- F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t);
+ // Legacy is counter-clockwise, PBR is clockwise
+ pbr_rotation = -tex_rotation;
- if (pbr_rotation != 0.0f)
+ // Center of the tile
+ const F32 center_s = 0.5f;
+ const F32 center_t = 0.5f;
+
+ // Calculate the rotated scale
+ F32 cos_rot = cosf(tex_rotation);
+ F32 sin_rot = sinf(tex_rotation);
+ F32 cos_sq = cos_rot * cos_rot;
+ F32 sin_sq = sin_rot * sin_rot;
+
+ // GLTF scale doesn't match legacy scaling when rotation is applied.
+ // Legacy applies scale then rotation, which allows for planar aligment
+ // withoutn deformations, but gltf rotates first, so when scale gets
+ // aplied image gets deformed by rotation.
+ // It appears to be imposible to properly match legacy scale, so this
+ // is an approximation that at least matches at 0, 90, 180, 270 degree
+ // rotations, and is close enough at angles like 45.
+ pbr_scale.mV[VX] = tex_scale_s * cos_sq + tex_scale_t * sin_sq;
+ pbr_scale.mV[VY] = tex_scale_s * sin_sq + tex_scale_t * cos_sq;
+
+ // Center adjustment for scale
+ F32 center_adjust_s = 0.5f * (1.0f - pbr_scale.mV[VX]);
+ F32 center_adjust_t = 0.5f * (1.0f - pbr_scale.mV[VY]);
+
+ // 2. Offset from center
+ F32 pos_s = center_adjust_s - center_s;
+ F32 pos_t = center_adjust_t - center_t;
+
+ // 3. Rotate around center (clockwise, as per GLTF spec)
+ F32 c = cosf(pbr_rotation);
+ F32 s = sinf(pbr_rotation);
+ F32 rot_s = pos_s * c + pos_t * s;
+ F32 rot_t = -pos_s * s + pos_t * c;
+
+ // 4. Move back to top-left and apply offset
+ pbr_offset.set(rot_s + center_s + tex_offset_s, rot_t + center_t - tex_offset_t);
+}
+
+// Convert PBR transform values back to legacy TE transform values.
+// This is the reverse of convertTextureTransformToPBR.
+void LLGLTFMaterial::convertPBRTransformToTexture(
+ const LLVector2& pbr_scale,
+ const LLVector2& pbr_offset,
+ F32 pbr_rotation,
+ F32& tex_scale_s,
+ F32& tex_scale_t,
+ F32& tex_offset_s,
+ F32& tex_offset_t,
+ F32& tex_rotation)
+{
+ tex_rotation = -pbr_rotation;
+
+ // Reverse the scale transformation
+ // From: pbr_s = tex_s * cos² + tex_t * sin²
+ // pbr_t = tex_s * sin² + tex_t * cos²
+ // Solve for tex_s and tex_t
+ F32 cos_rot = cosf(tex_rotation);
+ F32 sin_rot = sinf(tex_rotation);
+ F32 cos_sq = cos_rot * cos_rot;
+ F32 sin_sq = sin_rot * sin_rot;
+
+ F32 denom = cos_sq * cos_sq - sin_sq * sin_sq;
+
+ if (fabsf(denom) < 0.0001f) // Near 45 degrees (cos²≈sin²≈0.5)
+ {
+ // At 45°: both scales contribute equally
+ // pbr_s = pbr_t = (tex_s + tex_t) / 2
+ // So: tex_s + tex_t = 2 * pbr_avg
+ // Use the average and assume symmetric scaling
+ tex_scale_s = tex_scale_t = (pbr_scale.mV[VX] + pbr_scale.mV[VY]) / 2.f;
+ }
+ else
{
- const F32 c = cosf(pbr_rotation);
- const F32 s = sinf(pbr_rotation);
- const F32 tmp_s = center_adjust_s * c - center_adjust_t * s;
- const F32 tmp_t = center_adjust_s * s + center_adjust_t * c;
- center_adjust_s = tmp_s;
- center_adjust_t = tmp_t;
+ // Solve the 2x2 system:
+ // pbr_s * cos² - pbr_t * sin² = tex_s * (cos⁴ - sin⁴)
+ // pbr_t * cos² - pbr_s * sin² = tex_t * (cos⁴ - sin⁴)
+ tex_scale_s = (pbr_scale.mV[VX] * cos_sq - pbr_scale.mV[VY] * sin_sq) / denom;
+ tex_scale_t = (pbr_scale.mV[VY] * cos_sq - pbr_scale.mV[VX] * sin_sq) / denom;
}
- pbr_offset.set(adjusted_offset_s + center_adjust_s,
- adjusted_offset_t + center_adjust_t);
+ // Center of the tile
+ const F32 center_s = 0.5f;
+ const F32 center_t = 0.5f;
+
+ // Center adjustment for scale
+ F32 center_adjust_s = 0.5f * (1.0f - pbr_scale.mV[VX]);
+ F32 center_adjust_t = 0.5f * (1.0f - pbr_scale.mV[VY]);
+
+ // 2. Offset from center
+ F32 pos_s = center_adjust_s - center_s;
+ F32 pos_t = center_adjust_t - center_t;
+
+ // 3. Rotate around center (clockwise, as per GLTF spec)
+ F32 c = cosf(pbr_rotation);
+ F32 s = sinf(pbr_rotation);
+ F32 rot_s = pos_s * c + pos_t * s;
+ F32 rot_t = -pos_s * s + pos_t * c;
+
+ // 3. Recover legacy offset
+ tex_offset_s = pbr_offset.mV[0] - rot_s - center_s;
+ tex_offset_t = -(pbr_offset.mV[1] - rot_t - center_t);
}
diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
index 6bb021254b..64b585aacf 100644
--- a/indra/llprimitive/llgltfmaterial.h
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -223,6 +223,14 @@ public:
LLVector2& pbr_scale,
LLVector2& pbr_offset,
F32& pbr_rotation);
+
+ // Convert PBR transform values to legacy TE transform values.
+ static void convertPBRTransformToTexture(const LLVector2& pbr_scale,
+ const LLVector2& pbr_offset,
+ F32 pbr_rotation,
+ F32& tex_scale_s, F32& tex_scale_t,
+ F32& tex_offset_s, F32& tex_offset_t,
+ F32& tex_rotation);
protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
index bd6256d961..41dd5a8710 100644
--- a/indra/llprimitive/llmaterialid.h
+++ b/indra/llprimitive/llmaterialid.h
@@ -67,15 +67,11 @@ public:
static const LLMaterialID null;
- // Returns a 64 bits digest of the material Id, by XORing its two 64 bits
- // long words. HB
- inline U64 getDigest64() const
- {
- U64* tmp = (U64*)mID;
- return tmp[0] ^ tmp[1];
- }
-
private:
+ // definitions follow class
+ friend std::hash<LLMaterialID>;
+ friend size_t hash_value(const LLMaterialID&) noexcept;
+
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const;
@@ -90,15 +86,27 @@ namespace std
{
inline size_t operator()(const LLMaterialID& id) const noexcept
{
- return (size_t)id.getDigest64();
+ size_t h = 0;
+ // Golden ratio hash with avalanche mixing
+ // Process 8 bytes at a time by manually constructing 64-bit values
+ // Shift by 31: mixes upper half into lower half for better bit distribution
+ // Shift by 47: ensures highest bits influence final hash output
+ for (int i = 0; i < MATERIAL_ID_SIZE; i += 8) {
+ size_t chunk = (size_t)id.mID[i] | ((size_t)id.mID[i + 1] << 8) |
+ ((size_t)id.mID[i+2] << 16) | ((size_t)id.mID[i+3] << 24) |
+ ((size_t)id.mID[i+4] << 32) | ((size_t)id.mID[i+5] << 40) |
+ ((size_t)id.mID[i + 6] << 48) | ((size_t)id.mID[i + 7] << 56);
+ h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47);
+ }
+ return h;
}
};
}
-// For use with boost containers.
+// For use with boost::container_hash
inline size_t hash_value(const LLMaterialID& id) noexcept
{
- return (size_t)id.getDigest64();
+ return std::hash<LLMaterialID>{}(id);
}
#endif // LL_LLMATERIALID_H
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index c116f69a6d..e74adc16b8 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -1515,7 +1515,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
S32 size;
U32 face_count = 0;
- if (!dp.unpackBinaryData(packed_buffer, size, "TextureEntry"))
+ if (!dp.unpackBinaryData(packed_buffer, MAX_TE_BUFFER, size, "TextureEntry"))
{
retval = TEM_INVALID;
LL_WARNS() << "Bad texture entry block! Abort!" << LL_ENDL;
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 31bc76344c..c3e3e19ee9 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -109,11 +109,12 @@ public:
PARAMS_EXTENDED_MESH = 0x70,
PARAMS_RENDER_MATERIAL = 0x80,
PARAMS_REFLECTION_PROBE = 0x90,
+ PARAMS_MAX = PARAMS_REFLECTION_PROBE,
};
public:
U16 mType;
- virtual ~LLNetworkData() {};
+ virtual ~LLNetworkData() = default;
virtual bool pack(LLDataPacker &dp) const = 0;
virtual bool unpack(LLDataPacker &dp) = 0;
virtual bool operator==(const LLNetworkData& data) const = 0;
@@ -319,7 +320,7 @@ public:
bool fromLLSD(LLSD& sd);
void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type);
- LLUUID getSculptTexture() const { return mSculptTexture; }
+ const LLUUID& getSculptTexture() const { return mSculptTexture; }
U8 getSculptType() const { return mSculptType; }
};
@@ -340,10 +341,10 @@ public:
bool fromLLSD(LLSD& sd);
void setLightTexture(const LLUUID& id) { mLightTexture = id; }
- LLUUID getLightTexture() const { return mLightTexture; }
+ const LLUUID& getLightTexture() const { return mLightTexture; }
bool isLightSpotlight() const { return mLightTexture.notNull(); }
void setParams(const LLVector3& params) { mParams = params; }
- LLVector3 getParams() const { return mParams; }
+ const LLVector3& getParams() const { return mParams; }
};
diff --git a/indra/llprimitive/lltextureanim.cpp b/indra/llprimitive/lltextureanim.cpp
index 579538075a..963b7456b8 100644
--- a/indra/llprimitive/lltextureanim.cpp
+++ b/indra/llprimitive/lltextureanim.cpp
@@ -155,7 +155,7 @@ void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
{
S32 size;
U8 data[TA_BLOCK_SIZE];
- dp.unpackBinaryData(data, size, "TextureAnimation");
+ dp.unpackBinaryData(data, TA_BLOCK_SIZE, size, "TextureAnimation");
if (size != TA_BLOCK_SIZE)
{
if (size)
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 6de5685517..71423de95d 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -103,7 +103,12 @@ target_link_libraries(llrender
llwindow
ll::freetype
OpenGL::GL
- OpenGL::GLU
)
+if (${LINUX_DISTRO} MATCHES freedesktop)
+ target_link_libraries(${PROJECT_NAME} ll::glu)
+else ()
+ target_link_libraries(${PROJECT_NAME} OpenGL::GLU)
+endif ()
+
include(LibraryInstall)
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 9d6773ac5b..357dfc8ea8 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -39,6 +39,7 @@
// For some reason, this won't work if it's not wrapped in the ifdef
#ifdef FT_FREETYPE_H
#include FT_FREETYPE_H
+#include FT_MULTIPLE_MASTERS_H
#endif
#include "lldir.h"
@@ -118,6 +119,8 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type)
mYBitmapOffset(0), // Offset to the origin in the bitmap
mXBearing(0), // Distance from baseline to left in pixels
mYBearing(0), // Distance from baseline to top in pixels
+ mLsbDelta(0),
+ mRsbDelta(0),
mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
{
}
@@ -133,6 +136,8 @@ LLFontGlyphInfo::LLFontGlyphInfo(const LLFontGlyphInfo& fgi)
, mYBitmapOffset(fgi.mYBitmapOffset)
, mXBearing(fgi.mXBearing)
, mYBearing(fgi.mYBearing)
+ , mLsbDelta(fgi.mLsbDelta)
+ , mRsbDelta(fgi.mRsbDelta)
{
mBitmapEntry = fgi.mBitmapEntry;
}
@@ -143,6 +148,7 @@ LLFontFreetype::LLFontFreetype()
mDescender(0.f),
mLineHeight(0.f),
mIsFallback(false),
+ mHinting(EFontHinting::FORCE_AUTOHINT),
mFTFace(nullptr),
mRenderGlyphCount(0),
mStyle(0),
@@ -166,7 +172,7 @@ LLFontFreetype::~LLFontFreetype()
// mFallbackFonts cleaned up by LLPointer destructor
}
-bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)
+bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
{
// Don't leak face objects. This is also needed to deal with
// changed font file names.
@@ -190,6 +196,20 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
return false;
mIsFallback = is_fallback;
+ mHinting = hinting;
+ mFontFlags = flags;
+ mWeight = weight;
+
+ bool variable_font = false;
+ if (weight >= 0)
+ {
+ variable_font = setVariationAxis("wght", static_cast<F32>(weight));
+
+ // For Inter, also set optical size based on point size
+ // This makes text look better at different sizes
+ setVariationAxis("opsz", point_size);
+ }
+
F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
error = FT_Set_Char_Size(mFTFace, /* handle to face object */
@@ -245,6 +265,18 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
{
mStyle |= LLFontGL::BOLD;
}
+ else if (flags & LLFontGL::BOLD)
+ {
+ // FontGL applies programmatic bolding to fonts that are a part of 'bold' descriptor but don't have the bold style set.
+ // Ex: Inter SemiBold doesn't have FT_STYLE_FLAG_BOLD and without this style it would be bolded programmatically.
+ mStyle |= LLFontGL::BOLD;
+ }
+ else if (weight >= 600 && variable_font)
+ {
+ // If the font is heavy enough, consider it bold and avoid programmatic bolding
+ // even if it doesn't have the bold style set.
+ mStyle |= LLFontGL::BOLD;
+ }
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
{
@@ -343,16 +375,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
//llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
- U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
// Kern this puppy.
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
- U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
-
- FT_Vector delta;
-
- llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
- return delta.x*(1.f/64.f);
+ return getXKerning(left_glyph_info, right_glyph_info);
}
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
@@ -365,9 +391,28 @@ F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LL
FT_Vector delta;
- llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+ llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, FT_KERNING_UNFITTED, &delta));
- return delta.x*(1.f/64.f);
+ // Apply the FreeType auto-hinter's subpixel side-bearing correction between
+ // adjacent glyphs. When the hinter has shifted the right side of the left
+ // glyph or the left side of the right glyph, (rsb_delta - lsb_delta) is the
+ // sub-pixel nudge that keeps spacing visually even.
+ F32 delta_correction = 0.0f;
+ if (left_glyph_info && right_glyph_info)
+ {
+ // According to FreeType docs, these delta values should only trigger
+ // discrete ±1 pixel adjustments when they cross certain thresholds.
+ // Substructing delta_diff from delta.x doesn't work as well as treating
+ // it as a thresholds
+ S32 delta_diff = left_glyph_info->mRsbDelta - right_glyph_info->mLsbDelta;
+ if (delta_diff > 32)
+ delta_correction = -1.0f;
+ else if (delta_diff < -31)
+ delta_correction = 1.0f;
+ }
+
+ // ft_kerning_unfitted mode always returns 26.6 fixed-point values
+ return (F32)(delta.x * (1.f / 64.f)) + delta_correction;
}
bool LLFontFreetype::hasGlyph(llwchar wch) const
@@ -512,6 +557,11 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
gi->mHeight = height;
gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
+ // FreeType fills these when the glyph has been auto-hinted; they describe how
+ // much the hinter nudged the left/right side bearings (in 26.6 pixels). Keep
+ // them so inter-glyph spacing can be corrected in getXKerning().
+ gi->mLsbDelta = (S32)fontp->mFTFace->glyph->lsb_delta;
+ gi->mRsbDelta = (S32)fontp->mFTFace->glyph->rsb_delta;
// Convert these from 26.6 units to float pixels.
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
@@ -637,7 +687,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
if (mFTFace == nullptr)
return;
- FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
+ FT_Int32 load_flags = (FT_Int32)mHinting;
if (EFontGlyphType::Color == bitmap_type)
{
// We may not actually get a color render so our caller should always examine mFTFace->glyph->bitmap.pixel_mode
@@ -680,7 +730,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
resetBitmapCache();
- loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);
+ loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mWeight, mIsFallback, 0, mHinting, mFontFlags);
if (!mIsFallback)
{
// This is the head of the list - need to rebuild ourself and all fallbacks.
@@ -848,6 +898,73 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32
}
}
+bool LLFontFreetype::setVariationAxis(const std::string& axis_tag, F32 value)
+{
+ if (!mFTFace)
+ return false;
+
+ // Check if this is a variable font
+ FT_MM_Var* master = nullptr;
+ if (FT_Get_MM_Var(mFTFace, &master) != 0)
+ {
+ // Not a variable font - this is not an error, just silently skip
+ return false;
+ }
+
+ // Find the axis by tag (e.g., "wght" for weight)
+ FT_UInt axis_index = 0;
+ bool found = false;
+ for (FT_UInt i = 0; i < master->num_axis; i++)
+ {
+ // Compare the 4-byte tag
+ if (master->axis[i].tag == FT_MAKE_TAG(axis_tag[0], axis_tag[1], axis_tag[2], axis_tag[3]))
+ {
+ axis_index = i;
+ found = true;
+
+ // Clamp value to valid range for this axis
+ F32 min_val = master->axis[i].minimum / 65536.0f;
+ F32 max_val = master->axis[i].maximum / 65536.0f;
+ value = llclamp(value, min_val, max_val);
+
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ FT_Done_MM_Var(gFTLibrary, master);
+ LL_WARNS_ONCE("Font") << "Axis '" << axis_tag << "' not found in font: " << mName << LL_ENDL;
+ return false;
+ }
+
+ FT_UInt num_coords = master->num_axis;
+ FT_Fixed* coords = new FT_Fixed[num_coords];
+
+ // Get current coordinates
+ FT_Get_Var_Design_Coordinates(mFTFace, num_coords, coords);
+
+ // Update the specific axis
+ coords[axis_index] = (FT_Fixed)(value * 65536.0f);
+
+ // Set all coordinates
+ int error = FT_Set_Var_Design_Coordinates(mFTFace, num_coords, coords);
+
+ delete[] coords;
+ FT_Done_MM_Var(gFTLibrary, master);
+
+ if (error != 0)
+ {
+ LL_WARNS() << "Failed to set variation coordinates for " << axis_tag
+ << " = " << value << " in font: " << mName << LL_ENDL;
+ return false;
+ }
+
+ LL_DEBUGS("Font") << "Set " << axis_tag << " = " << value
+ << " for font: " << mName << LL_ENDL;
+ return true;
+}
+
namespace ll
{
@@ -873,30 +990,39 @@ namespace ll
U8 const* LLFontManager::loadFont( std::string const &aFilename, long &a_Size)
{
- a_Size = 0;
- std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> >::iterator itr = m_LoadedFonts.find( aFilename );
- if( itr != m_LoadedFonts.end() )
+ try
{
- ++itr->second->mRefs;
- // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits<long>::max() a few lines below.
- a_Size = static_cast<long>(itr->second->mSize);
- return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
- }
+ a_Size = 0;
+ std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> >::iterator itr = m_LoadedFonts.find(aFilename);
+ if (itr != m_LoadedFonts.end())
+ {
+ ++itr->second->mRefs;
+ // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits<long>::max() a few lines below.
+ a_Size = static_cast<long>(itr->second->mSize);
+ return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
+ }
- auto strContent = LLFile::getContents(aFilename);
+ auto strContent = LLFile::getContents(aFilename);
- if( strContent.empty() )
- return nullptr;
+ if (strContent.empty())
+ return nullptr;
- // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?)
- llassert_always( strContent.size() < std::numeric_limits<long>::max() );
+ // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?)
+ llassert_always(strContent.size() < std::numeric_limits<long>::max());
- a_Size = static_cast<long>(strContent.size());
+ a_Size = static_cast<long>(strContent.size());
- auto pCache = std::make_shared<ll::fonts::LoadedFont>( aFilename, strContent, a_Size );
- itr = m_LoadedFonts.insert( std::make_pair( aFilename, pCache ) ).first;
+ auto pCache = std::make_shared<ll::fonts::LoadedFont>(aFilename, strContent, a_Size);
+ itr = m_LoadedFonts.insert(std::make_pair(aFilename, pCache)).first;
- return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
+ return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
+ }
+ catch (const std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Failed to load font. Out of memory." << LL_ENDL;
+ }
+ return nullptr;
}
void LLFontManager::unloadAllFonts()
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index a9b3a944ee..d2164e8fa2 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -27,13 +27,14 @@
#ifndef LL_LLFONTFREETYPE_H
#define LL_LLFONTFREETYPE_H
-#include <boost/unordered_map.hpp>
#include "llpointer.h"
#include "llstl.h"
#include "llimagegl.h"
#include "llfontbitmapcache.h"
+#include <unordered_map>
+
// Hack. FT_Face is just a typedef for a pointer to a struct,
// but there's no simple forward declarations file for FreeType,
// and the main include file is 200K.
@@ -42,6 +43,7 @@ struct FT_FaceRec_;
typedef struct FT_FaceRec_* LLFT_Face;
struct FT_StreamRec_;
typedef struct FT_StreamRec_ LLFT_Stream;
+enum class EFontHinting : S32;
namespace ll
{
@@ -86,6 +88,8 @@ struct LLFontGlyphInfo
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
S32 mYBearing; // Distance from baseline to top in pixels
+ S32 mLsbDelta; // FreeType subpixel left side bearing delta (26.6 units)
+ S32 mRsbDelta; // FreeType subpixel right side bearing delta (26.6 units)
std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
};
@@ -99,7 +103,7 @@ public:
// is_fallback should be true for fallback fonts that aren't used
// to render directly (Unicode backup, primarily)
- bool loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);
+ bool loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
S32 getNumFaces(const std::string& filename);
@@ -161,9 +165,14 @@ private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
+ bool setVariationAxis(const std::string& axis_tag, F32 value);
bool hasGlyph(llwchar wch) const; // Has a glyph for this character
LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
- LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
+ LLFontGlyphInfo* addGlyphFromFont(
+ const LLFontFreetype *fontp,
+ llwchar wch,
+ U32 glyph_index,
+ EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
@@ -179,12 +188,15 @@ private:
LLFT_Face mFTFace;
bool mIsFallback;
+ EFontHinting mHinting;
+ S32 mFontFlags;
+ S32 mWeight = -1;
typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
typedef std::vector<fallback_font_t> fallback_font_vector_t;
fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
// *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
- typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
+ typedef std::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLFontBitmapCache* mFontBitmapCachep;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 16eec1fdd2..5d99c35047 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -90,14 +90,14 @@ void LLFontGL::destroyGL()
mFontFreetype->destroyGL();
}
-bool LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n)
+bool LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
{
if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
{
mFontFreetype = new LLFontFreetype;
}
- return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n);
+ return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, weight, is_fallback, face_n, hinting, flags);
}
S32 LLFontGL::getNumFaces(const std::string& filename)
@@ -1115,7 +1115,14 @@ LLFontGL* LLFontGL::getFontSansSerifSmallItalic()
//static
LLFontGL* LLFontGL::getFontSansSerif()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
+ return fontp;
+}
+
+// static
+LLFontGL* LLFontGL::getFontSansSerifMedium()
+{
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif", "Medium", 0));
return fontp;
}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 1c8e036f58..3b82d8e43d 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -87,7 +87,7 @@ public:
void destroyGL();
- bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
+ bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
S32 getNumFaces(const std::string& filename);
S32 getCacheGeneration() const;
@@ -204,6 +204,7 @@ public:
static LLFontGL* getFontSansSerifSmallBold();
static LLFontGL* getFontSansSerifSmallItalic();
static LLFontGL* getFontSansSerif();
+ static LLFontGL* getFontSansSerifMedium();
static LLFontGL* getFontSansSerifBig();
static LLFontGL* getFontSansSerifHuge();
static LLFontGL* getFontSansSerifBold();
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index c48a389f6a..890308ab54 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -170,7 +170,7 @@ LLFontDescriptor LLFontDescriptor::normalize() const
if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace"))
new_size = "Monospace";
if (new_size.empty())
- new_size = "Medium";
+ new_size = "Small";
if (removeSubString(new_name,"Bold"))
new_style |= LLFontGL::BOLD;
@@ -181,16 +181,16 @@ LLFontDescriptor LLFontDescriptor::normalize() const
return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
}
-void LLFontDescriptor::addFontFile(const std::string& file_name, const std::string& char_functor)
+void LLFontDescriptor::addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor)
{
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
- mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
+ mFontFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, weight, (mCharFunctors.end() != it) ? it->second : nullptr));
}
-void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, const std::string& char_functor)
+void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor)
{
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
- mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
+ mFontCollectionFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, weight, (mCharFunctors.end() != it) ? it->second : nullptr));
}
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
@@ -289,23 +289,69 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
{
std::string font_file_name = child->getTextContents();
std::string char_functor;
+ EFontHinting hinting = EFontHinting::FORCE_AUTOHINT;
+ S32 flags = 0;
+ S32 weight = -1;
if (child->hasAttribute("functor"))
{
child->getAttributeString("functor", char_functor);
}
+ if (child->hasAttribute("font_hinting"))
+ {
+ std::string attr_hinting;
+ child->getAttributeString("font_hinting", attr_hinting);
+ LLStringUtil::toLower(attr_hinting);
+
+ if (attr_hinting == "default")
+ {
+ hinting = EFontHinting::DEFAULT;
+ }
+ else if (attr_hinting == "force_auto")
+ {
+ hinting = EFontHinting::FORCE_AUTOHINT;
+ }
+ else if (attr_hinting == "no_hinting")
+ {
+ hinting = EFontHinting::NO_HINTING;
+ }
+ }
+
+ if (child->hasAttribute("flags"))
+ {
+ std::string attr_flags;
+ child->getAttributeString("flags", attr_flags);
+ LLStringUtil::toLower(attr_flags);
+
+ if (attr_flags == "bold")
+ {
+ flags |= LLFontGL::BOLD;
+ }
+ }
+
+ F32 size_delta = 0.f;
+ if (child->hasAttribute("size_delta"))
+ {
+ child->getAttributeF32("size_delta", size_delta);
+ }
+
+ if (child->hasAttribute("font_weight"))
+ {
+ child->getAttributeS32("font_weight", weight);
+ }
+
if (child->hasAttribute("load_collection"))
{
bool col = false;
child->getAttributeBOOL("load_collection", col);
if (col)
{
- desc.addFontCollectionFile(font_file_name, char_functor);
+ desc.addFontCollectionFile(font_file_name, hinting, flags, size_delta, weight, char_functor);
}
}
- desc.addFontFile(font_file_name, char_functor);
+ desc.addFontFile(font_file_name, hinting, flags, size_delta, weight, char_functor);
}
else if (child->hasName("os"))
{
@@ -462,7 +508,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
// Add ultimate fallback list - generated dynamically on linux,
// null elsewhere.
std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
- [](const std::string& file_name) { return LLFontFileInfo(file_name); });
+ [](const std::string& file_name) { return LLFontFileInfo(file_name, EFontHinting::FORCE_AUTOHINT, 0, 0.f, -1); });
// Load fonts based on names.
if (font_files.empty())
@@ -517,8 +563,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
{
fontp = new LLFontGL;
}
- if (fontp->loadFace(font_path, point_size_scale,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))
+ if (fontp->loadFace(font_path, point_size_scale + font_file_it->mSizeDelta,
+ LLFontGL::sVertDPI, LLFontGL::sHorizDPI, font_file_it->mWeight, is_fallback, i, font_file_it->mHinting, font_file_it->mFlags))
{
is_font_loaded = true;
if (is_first_found)
diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h
index 8bbf5aa30c..fcbb2667e4 100644
--- a/indra/llrender/llfontregistry.h
+++ b/indra/llrender/llfontregistry.h
@@ -34,22 +34,45 @@ class LLFontGL;
typedef std::vector<std::string> string_vec_t;
+enum class EFontHinting : S32
+{
+ DEFAULT = 0,
+ NO_HINTING = 0x8000U,
+ FORCE_AUTOHINT = 0x20,
+};
+
struct LLFontFileInfo
{
- LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr)
+ LLFontFileInfo(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::function<bool(llwchar)>& char_functor = nullptr)
: FileName(file_name)
, CharFunctor(char_functor)
+ , mHinting(hinting)
+ , mFlags(flags)
+ , mSizeDelta(size_delta)
+ , mWeight(weight)
{
}
- LLFontFileInfo(const LLFontFileInfo& ffi)
+ LLFontFileInfo(const LLFontFileInfo& ffi, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight)
: FileName(ffi.FileName)
, CharFunctor(ffi.CharFunctor)
+ , mHinting(hinting)
+ , mFlags(flags)
+ , mSizeDelta(size_delta)
+ , mWeight(weight)
{
}
std::string FileName;
std::function<bool(llwchar)> CharFunctor;
+ EFontHinting mHinting;
+ S32 mFlags;
+ S32 mWeight; // -1 - default, whatever is in the file.
+
+ // Not all fonts are the same size, Ex: dejavu is bigger than inter,
+ // so in some cases we want to adjust relative sizes to make characters
+ // from different files match.
+ F32 mSizeDelta;
};
typedef std::vector<LLFontFileInfo> font_file_info_vec_t;
@@ -71,10 +94,10 @@ public:
const std::string& getSize() const { return mSize; }
void setSize(const std::string& size) { mSize = size; }
- void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ void addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor = LLStringUtil::null);
const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
- void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ void addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor = LLStringUtil::null);
const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp
index a223509d30..2a0115265f 100644
--- a/indra/llrender/llfontvertexbuffer.cpp
+++ b/indra/llrender/llfontvertexbuffer.cpp
@@ -237,3 +237,80 @@ void LLFontVertexBuffer::renderBuffers()
gGL.popUIMatrix();
}
+// LLFontWidthBuffer
+bool LLFontWidthBuffer::sEnableBufferCollection = true;
+
+LLFontWidthBuffer::LLFontWidthBuffer()
+{
+}
+
+LLFontWidthBuffer::~LLFontWidthBuffer()
+{
+}
+
+void LLFontWidthBuffer::reset()
+{
+ mLastFont = nullptr;
+ mLastOffset = 0;
+ mLastMaxChars = 0;
+ mLastNoPadding = false;
+ mWidth = -1.f;
+ mLastScaleX = 1.f;
+ mLastScaleY = 1.f;
+ mLastVertDPI = 0.f;
+ mLastHorizDPI = 0.f;
+ mLastResGeneration = 0;
+ mLastFontCacheGen = 0;
+}
+
+F32 LLFontWidthBuffer::getWidth(
+ const LLFontGL* fontp,
+ const llwchar* wchars,
+ S32 begin_offset,
+ S32 max_chars,
+ bool no_padding)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
+ if (!fontp || !wchars)
+ {
+ return 0.f;
+ }
+
+ if (!sEnableBufferCollection)
+ {
+ return fontp->getWidthF32(wchars, begin_offset, max_chars, no_padding);
+ }
+
+ // Check if we can use cached width
+ bool needs_recalc = (mWidth < 0.f)
+ || (mLastFont != fontp)
+ || (mLastOffset != begin_offset)
+ || (mLastMaxChars != max_chars)
+ || (mLastNoPadding != no_padding)
+ || (mLastScaleX != LLFontGL::sScaleX)
+ || (mLastScaleY != LLFontGL::sScaleY)
+ || (mLastVertDPI != LLFontGL::sVertDPI)
+ || (mLastHorizDPI != LLFontGL::sHorizDPI)
+ || (mLastResGeneration != LLFontGL::sResolutionGeneration)
+ || (mLastFontCacheGen != fontp->getCacheGeneration());
+
+ if (needs_recalc)
+ {
+ // Calculate width using the font
+ mWidth = fontp->getWidthF32(wchars, begin_offset, max_chars, no_padding);
+
+ // Cache the parameters
+ mLastFont = fontp;
+ mLastOffset = begin_offset;
+ mLastMaxChars = max_chars;
+ mLastNoPadding = no_padding;
+ mLastScaleX = LLFontGL::sScaleX;
+ mLastScaleY = LLFontGL::sScaleY;
+ mLastVertDPI = LLFontGL::sVertDPI;
+ mLastHorizDPI = LLFontGL::sHorizDPI;
+ mLastResGeneration = LLFontGL::sResolutionGeneration;
+ mLastFontCacheGen = fontp->getCacheGeneration();
+ }
+
+ return mWidth;
+}
diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h
index a9e1e2337c..94b833d227 100644
--- a/indra/llrender/llfontvertexbuffer.h
+++ b/indra/llrender/llfontvertexbuffer.h
@@ -32,6 +32,11 @@
class LLVertexBufferData;
+// Rendering fonts is expensive, this class is intended to store
+// vertex buffers for rendered text, so that they can be reused.
+// LLFontVertexBuffer tracks font and rendering parameters, but
+// expects caller to track text changes and call reset() when
+// text changes.
class LLFontVertexBuffer
{
public:
@@ -127,4 +132,45 @@ private:
static bool sEnableBufferCollection;
};
+// Extracting width from a font is expensive, and due to
+// mechanics of font rendering, we need width separately
+// and usually before rendering.
+// LLFontWidthBuffer tracks font and rendering parameters,
+// but expects caller to track text changes and call reset()
+// when text changes.
+class LLFontWidthBuffer
+{
+public:
+ LLFontWidthBuffer();
+ ~LLFontWidthBuffer();
+
+ void reset();
+
+ F32 getWidth(const LLFontGL* fontp,
+ const llwchar* wchars,
+ S32 begin_offset,
+ S32 max_chars,
+ bool no_padding);
+
+ static void enableBufferCollection(bool enable) { sEnableBufferCollection = enable; }
+private:
+ const LLFontGL* mLastFont = nullptr;
+ S32 mLastOffset = 0;
+ S32 mLastMaxChars = 0;
+ bool mLastNoPadding = false;
+ F32 mWidth = -1.f;
+
+ // LLFontGL's values that affect width calculation
+ F32 mLastScaleX = 1.f;
+ F32 mLastScaleY = 1.f;
+ F32 mLastVertDPI = 0.f;
+ F32 mLastHorizDPI = 0.f;
+ S32 mLastResGeneration = 0;
+
+ // Cache generation tracking
+ S32 mLastFontCacheGen = 0;
+
+ static bool sEnableBufferCollection;
+};
+
#endif
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index b002d183ef..3a36e49029 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -2386,7 +2386,7 @@ void clear_glerror()
//
// Static members
-boost::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
+std::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default
GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default
@@ -2433,7 +2433,7 @@ void LLGLState::resetTextureStates()
void LLGLState::dumpStates()
{
LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
- for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"true":"false") << LL_ENDL;
@@ -2465,7 +2465,7 @@ void LLGLState::checkStates(GLboolean writeAlpha)
//llassert_always(colorMask[2]);
// llassert_always(colorMask[3] == writeAlpha);
- for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LLGLenum state = iter->first;
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 414c28481f..a7dced3753 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -31,7 +31,7 @@
#include <functional>
#include <string>
-#include <boost/unordered_map.hpp>
+#include <unordered_map>
#include <list>
#include "llerror.h"
@@ -248,7 +248,7 @@ public:
static void checkStates(GLboolean writeAlpha = GL_TRUE);
protected:
- static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
+ static std::unordered_map<LLGLenum, LLGLboolean> sStateMap;
public:
enum { CURRENT_STATE = -2, DISABLED_STATE = 0, ENABLED_STATE = 1 };
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index bc80bd9556..1942ddb648 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1955,7 +1955,7 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
LLGLint is_compressed = 0;
if (compressed_ok)
{
- glGetTexLevelParameteriv(mTarget, is_compressed, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed);
+ glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed);
}
//-----------------------------------------------------------------------------------------------
@@ -2300,7 +2300,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
{
- if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask)
+ if(!data_in || sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask)
{
return ;
}
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 658947d531..bb98696108 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1788,7 +1788,16 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count)
LLVertexBuffer * vb = new LLVertexBuffer(attribute_mask);
vb->allocateBuffer(count, 0);
- vb->setBuffer();
+ // Non-Apple path uses glBufferSubData inside setXxxData, so the VBO
+ // must already be bound. On Apple, the VBO is lazily created in
+ // _unmapBuffer (LLAppleVBOPool); calling setBuffer() here would bind
+ // mGLBuffer == 0 and then setupVertexBuffer would issue
+ // glVertexAttribIPointer with a non-null offset against no bound
+ // GL_ARRAY_BUFFER -> GL_INVALID_OPERATION in core profile.
+ if (!gGLManager.mIsApple)
+ {
+ vb->setBuffer();
+ }
vb->setPositionData(mVerticesp.get());
@@ -1804,6 +1813,9 @@ LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count)
if(gGLManager.mIsApple && LLVertexBuffer::getVertexBufferMode() == 0)
{
+ // unmapBuffer creates the GL buffer, uploads, and leaves it bound,
+ // drawBuffer's later setBuffer() then runs setupVertexBuffer against
+ // a valid VBO.
vb->unmapBuffer();
}
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index f50ce26793..fae2bd5034 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1026,8 +1026,23 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version,
llifstream instream(meta_out_path, std::ifstream::in | std::ifstream::binary);
LLSD in_data;
- // todo: this is likely very expensive to parse, should use binary
- LLSDSerialize::fromBinary(in_data, instream, LLSDSerialize::SIZE_UNLIMITED);
+ try
+ {
+ LLSDSerialize::fromBinary(in_data, instream, LLSDSerialize::SIZE_UNLIMITED);
+ }
+ catch( std::bad_alloc& )
+ {
+ // Try to get a bit more memory back before we try to clear the cache.
+ in_data.clear();
+ // Just in case it was somehow the cause, clear cache.
+ clearShaderCache();
+ // If user run out of memory this early in init,
+ // we don't want to keep going just to crash again.
+ // Notify user and close.
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("ShaderMgr") << "Failed to parse shader cache metadata, potentially due to size. Purged cache." << LL_ENDL;
+ return;
+ }
instream.close();
if (old_cache_version == current_cache_version
diff --git a/indra/llrender/lltexturemanagerbridge.cpp b/indra/llrender/lltexturemanagerbridge.cpp
index c243f0697a..67838418bf 100644
--- a/indra/llrender/lltexturemanagerbridge.cpp
+++ b/indra/llrender/lltexturemanagerbridge.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "lltexturemanagerbridge.h"
// Define a null texture manager bridge. Applications must provide their own bridge implementaton.
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 828bfb289b..fa9de1eb09 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -39,7 +39,7 @@ static const std::string DD_BUTTON_NAME = "dd_button";
static const std::string DD_TEXTBOX_NAME = "dd_textbox";
static const std::string DD_HEADER_NAME = "dd_header";
-static const S32 HEADER_HEIGHT = 23;
+static const S32 HEADER_HEIGHT = 25;
static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
static const F32 AUTO_OPEN_TIME = 1.f;
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 0048c44189..7f209c60a7 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -85,6 +85,7 @@ LLButton::Params::Params()
image_top_pad("image_top_pad"),
image_bottom_pad("image_bottom_pad"),
imgoverlay_label_space("imgoverlay_label_space", 1),
+ image_overlay_right_delta("image_overlay_right_delta", 0),
label_color("label_color"),
label_color_selected("label_color_selected"), // requires is_toggle true
label_color_disabled("label_color_disabled"),
@@ -109,6 +110,8 @@ LLButton::Params::Params()
commit_on_capture_lost("commit_on_capture_lost", false),
display_pressed_state("display_pressed_state", true),
use_draw_context_alpha("use_draw_context_alpha", true),
+ draw_focus_border("draw_focus_border", true),
+ hover_hand_cursor("hover_hand_cursor", false),
badge("badge"),
handle_right_mouse("handle_right_mouse"),
held_down_delay("held_down_delay"),
@@ -158,6 +161,7 @@ LLButton::LLButton(const LLButton::Params& p)
mImageOverlayTopPad(p.image_top_pad),
mImageOverlayBottomPad(p.image_bottom_pad),
mImgOverlayLabelSpace(p.imgoverlay_label_space),
+ mImageOverlayRightDelta(p.image_overlay_right_delta),
mIsToggle(p.is_toggle),
mScaleImage(p.scale_image),
mDropShadowedText(p.label_shadow),
@@ -179,6 +183,8 @@ LLButton::LLButton(const LLButton::Params& p)
mMouseUpSignal(NULL),
mHeldDownSignal(NULL),
mUseDrawContextAlpha(p.use_draw_context_alpha),
+ mDrawFocusBorder(p.draw_focus_border),
+ mHoverHandCursor(p.hover_hand_cursor),
mHandleRightMouse(p.handle_right_mouse),
mFlashingTimer(NULL)
{
@@ -653,7 +659,7 @@ bool LLButton::handleHover(S32 x, S32 y, MASK mask)
}
// We only handle the click if the click both started and ended within us
- getWindow()->setCursor(UI_CURSOR_ARROW);
+ getWindow()->setCursor(mHoverHandCursor ? UI_CURSOR_HAND : UI_CURSOR_ARROW);
LL_DEBUGS("UserInput") << "hover handled by " << getName() << LL_ENDL;
}
return true;
@@ -840,10 +846,9 @@ void LLButton::draw()
label_color = ll::ui::SearchableControl::getHighlightFontColor();
// overlay with keyboard focus border
- if (hasFocus())
+ if (hasFocus() && mDrawFocusBorder)
{
- F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
- drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, ll_round(lerp(1.f, 3.f, lerp_amt)));
+ drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
}
if (use_glow_effect)
@@ -930,6 +935,17 @@ void LLButton::draw()
}
overlay_color.mV[VALPHA] *= alpha;
+ if (mImageOverlayRightDelta > 0)
+ {
+ mImageOverlay->draw(getRect().getWidth() - overlay_width - mImageOverlayRightDelta,
+ center_y - (overlay_height / 2),
+ overlay_width,
+ overlay_height,
+ overlay_color);
+ }
+ else
+ {
+
switch(mImageOverlayAlignment)
{
case LLFontGL::LEFT:
@@ -964,6 +980,7 @@ void LLButton::draw()
// draw nothing
break;
}
+ }
}
// Draw label
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index f530eceb4b..0d1a28ee31 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -110,6 +110,7 @@ public:
//image overlay paddings
Optional<S32> image_top_pad;
Optional<S32> image_bottom_pad;
+ Optional<S32> image_overlay_right_delta;
/**
* Space between image_overlay and label
@@ -132,7 +133,9 @@ public:
Optional<F32> hover_glow_amount;
Optional<TimeIntervalParam> held_down_delay;
- Optional<bool> use_draw_context_alpha;
+ Optional<bool> use_draw_context_alpha,
+ draw_focus_border,
+ hover_hand_cursor;
Optional<LLBadge::Params> badge;
@@ -366,12 +369,16 @@ protected:
S32 mImageOverlayBottomPad;
bool mUseDrawContextAlpha;
+ bool mDrawFocusBorder;
+ bool mHoverHandCursor;
/*
* Space between image_overlay and label
*/
S32 mImgOverlayLabelSpace;
+ S32 mImageOverlayRightDelta;
+
F32 mHoverGlowStrength;
F32 mCurGlowStrength;
diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h
index 3115606d91..69b80db1e8 100644
--- a/indra/llui/llcallbackmap.h
+++ b/indra/llui/llcallbackmap.h
@@ -27,9 +27,11 @@
#ifndef LLCALLBACKMAP_H
#define LLCALLBACKMAP_H
-#include <map>
+#include "llstl.h"
+
#include <string>
#include <functional>
+#include <unordered_map>
class LLCallbackMap
{
@@ -37,7 +39,7 @@ public:
// callback definition.
typedef std::function<void* (void* data)> callback_t;
- typedef std::map<std::string, LLCallbackMap> map_t;
+ typedef std::unordered_map<std::string, LLCallbackMap> map_t;
typedef map_t::iterator map_iter_t;
typedef map_t::const_iterator map_const_iter_t;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index ae676251ff..01463b4962 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -1323,6 +1323,39 @@ bool LLComboBox::selectItemRange( S32 first, S32 last )
return mList->selectItemRange(first, last);
}
+void LLComboBox::addInfo(LLSD& info)
+{
+ LLUICtrl::addInfo(info);
+
+ if (mList && mList->getItemCount() > 0)
+ {
+ LLSD items_array;
+ std::vector<LLScrollListItem*> item_list = mList->getAllData();
+ for (std::vector<LLScrollListItem*>::iterator iter = item_list.begin(); iter != item_list.end(); ++iter)
+ {
+ if (LLScrollListItem* item = *iter)
+ {
+ LLSD item_info;
+ item_info["value"] = item->getValue();
+ if (item->getNumColumns() > 0)
+ {
+ if (LLScrollListCell* cell = item->getColumn(0))
+ {
+ item_info["label"] = cell->getValue();
+ }
+ }
+ items_array.append(item_info);
+ }
+ }
+ info["items"] = items_array;
+ info["item_count"] = mList->getItemCount();
+ info["current_selection"] = getSelectedItemLabel();
+ }
+ else
+ {
+ info["item_count"] = 0;
+ }
+}
static LLDefaultChildRegistry::Register<LLIconsComboBox> register_icons_combo_box("icons_combo_box");
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index d6ea1202d3..dad60ffb65 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -219,6 +219,10 @@ public:
void setButtonVisible(bool visible);
+ // Populates the provided LLSD with combo box-specific information(list of items, item count, current selection label)
+ // also includes base LLUICtrl information via parent class
+ void addInfo(LLSD & info);
+
void onButtonMouseDown();
void onListMouseUp();
void onItemSelected(const LLSD& data);
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 91e6f281da..ca512a9883 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -67,6 +67,10 @@ LLConsole::LLConsole(const LLConsole::Params& p)
{
setFontSize(p.font_size_index);
}
+ if (mFont == nullptr)
+ {
+ setFontSize(0); // sans-serif
+ }
mFadeTime = mLinePersistTime - FADE_DURATION;
setMaxLines(LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines"));
}
@@ -79,6 +83,13 @@ void LLConsole::setLinePersistTime(F32 seconds)
void LLConsole::reshape(S32 width, S32 height, bool called_from_parent)
{
+ if (mFont == nullptr)
+ {
+ // not initialized yet
+ LL_WARNS() << "LLConsole::reshape called before font is set" << LL_ENDL;
+ return;
+ }
+
S32 new_width = llmax(50, llmin(getRect().getWidth(), width));
S32 new_height = llmax(mFont->getLineHeight() + 15, llmin(getRect().getHeight(), height));
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 15536178ab..b3b47084c5 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -59,7 +59,9 @@ LLDragHandle::LLDragHandle(const LLDragHandle::Params& p)
mMaxTitleWidth( 0 ),
mForeground( true ),
mDragHighlightColor(p.drag_highlight_color()),
- mDragShadowColor(p.drag_shadow_color())
+ mDragShadowColor(p.drag_shadow_color()),
+ mFont(p.font),
+ mLabelVPad(p.label_vpad())
{
static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
@@ -98,14 +100,13 @@ void LLDragHandleTop::setTitle(const std::string& title)
}
else
{
- const LLFontGL* font = LLFontGL::getFontSansSerif();
LLTextBox::Params params;
params.name("Drag Handle Title");
params.rect(getRect());
params.initial_value(trimmed_title);
- params.font(font);
+ params.font(mFont);
params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
- params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
+ params.font_shadow(LLFontGL::NO_SHADOW);
params.use_ellipses = true;
params.parse_urls = false; //cancel URL replacement in floater title
mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
@@ -236,7 +237,6 @@ void LLDragHandleLeft::draw()
void LLDragHandleTop::reshapeTitleBox()
{
- static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0);
if( ! mTitleBox)
{
return;
@@ -248,7 +248,7 @@ void LLDragHandleTop::reshapeTitleBox()
LLRect title_rect;
title_rect.setLeftTopAndSize(
LEFT_PAD,
- getRect().getHeight() - title_vpad,
+ getRect().getHeight() - mLabelVPad,
title_width,
title_height);
diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h
index 73211d5292..f768839749 100644
--- a/indra/llui/lldraghandle.h
+++ b/indra/llui/lldraghandle.h
@@ -43,13 +43,17 @@ public:
: public LLInitParam::Block<Params, LLView::Params>
{
Optional<std::string> label;
+ Optional<S32> label_vpad;
Optional<LLUIColor> drag_highlight_color;
Optional<LLUIColor> drag_shadow_color;
+ Optional<const LLFontGL*> font;
Params()
: label("label"),
+ label_vpad("label_vpad", 7),
drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")),
- drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark"))
+ drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")),
+ font("font", LLFontGL::getFontSansSerif())
{
changeDefault(mouse_opaque, true);
changeDefault(follows.flags, FOLLOWS_ALL);
@@ -82,6 +86,8 @@ protected:
protected:
LLTextBox* mTitleBox;
+ const LLFontGL* mFont;
+ S32 mLabelVPad;
private:
LLRect mButtonsRect;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 52a5e3dbd6..6de2c18620 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -183,8 +183,10 @@ LLFloater::Params::Params()
show_title("show_title", true),
auto_close("auto_close", false),
positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE),
+ header_font("header_font", LLFontGL::getFontSansSerif()),
header_height("header_height", 0),
legacy_header_height("legacy_header_height", 0),
+ header_vpad("header_vpad", 7),
close_image("close_image"),
restore_image("restore_image"),
minimize_image("minimize_image"),
@@ -239,7 +241,7 @@ void LLFloater::initClass()
}
// defaults for floater param block pulled from widgets/floater.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(typeid(LLFloater::Params), "floater");
LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
: LLPanel(), // intentionally do not pass params here, see initFromParams
@@ -293,7 +295,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
memset(mButtonsEnabled, 0, BUTTON_COUNT * sizeof(bool));
memset(mButtons, 0, BUTTON_COUNT * sizeof(LLButton*));
- addDragHandle();
+ addDragHandle(p);
addResizeCtrls();
initFromParams(p);
@@ -336,7 +338,7 @@ void LLFloater::initFloater(const Params& p)
}
}
-void LLFloater::addDragHandle()
+void LLFloater::addDragHandle(const LLFloater::Params& floater_params)
{
if (!mDragHandle)
{
@@ -346,6 +348,8 @@ void LLFloater::addDragHandle()
p.name("drag");
p.follows.flags(FOLLOWS_ALL);
p.label(mTitle);
+ p.font(floater_params.header_font);
+ p.label_vpad(floater_params.header_vpad);
mDragHandle = LLUICtrlFactory::create<LLDragHandleLeft>(p);
}
else // drag on top
@@ -354,6 +358,8 @@ void LLFloater::addDragHandle()
p.name("Drag Handle");
p.follows.flags(FOLLOWS_ALL);
p.label(mTitle);
+ p.font(floater_params.header_font);
+ p.label_vpad(floater_params.header_vpad);
mDragHandle = LLUICtrlFactory::create<LLDragHandleTop>(p);
}
addChild(mDragHandle);
@@ -563,6 +569,8 @@ void LLFloater::storeRectControl()
void LLFloater::storeVisibilityControl()
{
+ // Todo: this is a bit pricey, gets called each frame
+ // on LLAppViewer::idle(), optimize!
if( !sQuitting && mVisibilityControl.size() > 1 )
{
getControlGroup()->setBOOL( mVisibilityControl, getVisible() );
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 9e1594bdd2..bda2531b43 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -172,8 +172,10 @@ public:
Optional<LLFloaterEnums::EOpenPositioning> positioning;
+ Optional<const LLFontGL*> header_font;
Optional<S32> header_height,
- legacy_header_height; // HACK see initFromXML()
+ legacy_header_height, // HACK see initFromXML()
+ header_vpad;
Optional<F32> rel_x,
rel_y;
@@ -442,7 +444,7 @@ private:
bool offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index);
void addResizeCtrls();
void layoutResizeCtrls();
- void addDragHandle();
+ void addDragHandle(const LLFloater::Params& p);
void layoutDragHandle(); // repair layout
static void updateActiveFloaterTransparency();
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index a818e72f59..c18495ce71 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -40,9 +40,9 @@
LLFloaterReg::instance_list_t LLFloaterReg::sNullInstanceList;
LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
-std::map<std::string, std::string, std::less<>> LLFloaterReg::sGroupMap;
+LLFloaterReg::group_map_t LLFloaterReg::sGroupMap;
bool LLFloaterReg::sBlockShowFloaters = false;
-std::set<std::string, std::less<>> LLFloaterReg::sAlwaysShowableList;
+LLFloaterReg::always_showable_t LLFloaterReg::sAlwaysShowableList;
static LLFloaterRegListener sFloaterRegListener;
@@ -96,11 +96,8 @@ LLFloater* LLFloaterReg::getLastFloaterCascading()
candidate_rect.mTop = 100000;
LLFloater* candidate_floater = NULL;
- std::map<std::string,std::string>::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end();
- for( ; it != it_end; ++it)
+ for (const auto& [floater_name, group_name] : sGroupMap)
{
- const std::string& group_name = it->second;
-
instance_list_t& instances = sInstanceMap[group_name];
for (LLFloater* inst : instances)
@@ -604,17 +601,11 @@ U32 LLFloaterReg::getVisibleFloaterInstanceCount()
{
U32 count = 0;
- std::map<std::string,std::string>::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end();
- for( ; it != it_end; ++it)
+ for (const auto& [floater_name, group_name] : sGroupMap)
{
- const std::string& group_name = it->second;
-
instance_list_t& instances = sInstanceMap[group_name];
-
- for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter)
+ for (LLFloater* inst : instances)
{
- LLFloater* inst = *iter;
-
if (inst->getVisible() && !inst->isMinimized())
{
count++;
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 24d1476dda..71a11b6f42 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -29,9 +29,11 @@
/// llcommon
#include "llrect.h"
#include "llsd.h"
+#include "llstl.h"
#include <functional>
#include <list>
+#include <unordered_set>
//*******************************************************
//
@@ -51,26 +53,29 @@ public:
// 2) We can change the key of a floater without altering the list.
typedef std::list<LLFloater*> instance_list_t;
typedef const instance_list_t const_instance_list_t;
- typedef std::map<std::string, instance_list_t, std::less<>> instance_map_t;
+ typedef std::unordered_map<std::string, instance_list_t, ll::string_hash, std::equal_to<>> instance_map_t;
struct BuildData
{
LLFloaterBuildFunc mFunc;
std::string mFile;
};
- typedef std::map<std::string, BuildData, std::less<>> build_map_t;
+ typedef std::unordered_map<std::string, BuildData, ll::string_hash, std::equal_to<>> build_map_t;
private:
friend class LLFloaterRegListener;
static instance_list_t sNullInstanceList;
static instance_map_t sInstanceMap;
static build_map_t sBuildMap;
- static std::map<std::string, std::string, std::less<>> sGroupMap;
+
+ using group_map_t = std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>>;
+ static group_map_t sGroupMap;
static bool sBlockShowFloaters;
/**
* Defines list of floater names that can be shown despite state of sBlockShowFloaters.
*/
- static std::set<std::string, std::less<>> sAlwaysShowableList;
+ using always_showable_t = std::unordered_set<std::string, ll::string_hash, std::equal_to<>>;
+ static always_showable_t sAlwaysShowableList;
public:
// Registration
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
index 17641b8375..7cf09369ec 100644
--- a/indra/llui/llfloaterreglistener.cpp
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -60,6 +60,10 @@ LLFloaterRegListener::LLFloaterRegListener():
"Ask to toggle the state of the floater specified in [\"name\"]",
&LLFloaterRegListener::toggleInstance,
requiredName);
+ add("toggleInstanceOrBringToFront",
+ "Ask to toggle the state of the floater specified in [\"name\"] or bring it to front if already opened",
+ &LLFloaterRegListener::toggleInstance,
+ requiredName);
add("instanceVisible",
"Return on [\"reply\"] an event whose [\"visible\"] indicates the visibility "
"of the floater specified in [\"name\"]",
@@ -107,6 +111,11 @@ void LLFloaterRegListener::toggleInstance(const LLSD& event) const
LLFloaterReg::toggleInstance(event["name"].asString(), event["key"]);
}
+void LLFloaterRegListener::toggleInstanceOrBringToFront(const LLSD& event) const
+{
+ LLFloaterReg::toggleInstanceOrBringToFront(event["name"].asString(), event["key"]);
+}
+
void LLFloaterRegListener::instanceVisible(const LLSD& event) const
{
sendReply(LLSDMap("visible", LLFloaterReg::instanceVisible(event["name"].asString(), event["key"])),
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
index 28f6e7c66b..610a2831dc 100644
--- a/indra/llui/llfloaterreglistener.h
+++ b/indra/llui/llfloaterreglistener.h
@@ -46,6 +46,7 @@ private:
void showInstance(const LLSD& event) const;
void hideInstance(const LLSD& event) const;
void toggleInstance(const LLSD& event) const;
+ void toggleInstanceOrBringToFront(const LLSD& event) const;
void instanceVisible(const LLSD& event) const;
void clickButton(const LLSD& event) const;
};
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 7544a44478..ce0e8036e7 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -464,6 +464,11 @@ F32 LLFocusMgr::getFocusFlashAmt() const
return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f);
}
+S32 LLFocusMgr::getFocusFlashWidth() const
+{
+ return ll_round(lerp(1.f, 2.f, getFocusFlashAmt()));
+}
+
LLColor4 LLFocusMgr::getFocusColor() const
{
static LLUIColor focus_color_cached = LLUIColorTable::instance().getColor("FocusColor");
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 89fee5c9f1..2e2293196b 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -101,7 +101,7 @@ public:
void setKeystrokesOnly(bool keystrokes_only) { mKeystrokesOnly = keystrokes_only; }
F32 getFocusFlashAmt() const;
- S32 getFocusFlashWidth() const { return ll_round(lerp(1.f, 3.f, getFocusFlashAmt())); }
+ S32 getFocusFlashWidth() const;
LLColor4 getFocusColor() const;
void triggerFocusFlash();
bool getAppHasFocus() const { return mAppHasFocus; }
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 878f1cb856..fcc1964bd6 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -28,6 +28,7 @@
#include "llflashtimer.h"
#include "linden_common.h"
+#include "llapp.h"
#include "llfolderviewitem.h"
#include "llfolderview.h"
#include "llfolderviewmodel.h"
@@ -158,9 +159,11 @@ LLFolderViewItem::Params::Params()
icon_width("icon_width", 0),
text_pad("text_pad", 0),
text_pad_right("text_pad_right", 0),
+ text_pad_top("text_pad_top", 1),
single_folder_mode("single_folder_mode", false),
double_click_override("double_click_override", false),
arrow_size("arrow_size", 0),
+ arrow_pad_top("arrow_pad_top", 1),
max_folder_item_overlap("max_folder_item_overlap", 0)
{ }
@@ -200,7 +203,9 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mIconWidth(p.icon_width),
mTextPad(p.text_pad),
mTextPadRight(p.text_pad_right),
+ mTextPadTop(p.text_pad_top),
mArrowSize(p.arrow_size),
+ mArrowPadTop(p.arrow_pad_top),
mSingleFolderMode(p.single_folder_mode),
mMaxFolderItemOverlap(p.max_folder_item_overlap),
mDoubleClickOverride(p.double_click_override)
@@ -810,7 +815,7 @@ void LLFolderViewItem::drawOpenFolderArrow()
if (hasVisibleChildren() || !isFolderComplete())
{
gl_draw_scaled_rotated_image(
- mIndentation, getRect().getHeight() - mArrowSize - mTextPad - sTopPad,
+ mIndentation, getRect().getHeight() - mArrowSize - mArrowPadTop - sTopPad,
mArrowSize, mArrowSize, mControlLabelRotation, sFolderArrowImg->getImage(), sFgColor);
}
}
@@ -1044,7 +1049,7 @@ void LLFolderViewItem::draw()
S32 filter_string_length = mViewModelItem->hasFilterStringMatch() ? (S32)mViewModelItem->getFilterStringSize() : 0;
F32 right_x = 0;
- F32 y = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
+ F32 y = (F32)rect_height - line_height - (F32)mTextPadTop - (F32)sTopPad;
F32 text_left = (F32)getLabelXPos();
LLWString combined_string = mLabel + mLabelSuffix;
@@ -1123,7 +1128,7 @@ void LLFolderViewItem::draw()
if(mLabelSuffix.empty() || (font == sSuffixFont))
{
F32 match_string_left = text_left + font->getWidthF32(combined_string.c_str(), 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string.c_str(), filter_offset, filter_string_length);
- F32 yy = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
+ F32 yy = (F32)rect_height - line_height - (F32)mTextPadTop - (F32)sTopPad;
font->render(combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
filter_string_length, S32_MAX, &right_x);
@@ -1134,7 +1139,7 @@ void LLFolderViewItem::draw()
if(label_filter_length > 0)
{
F32 match_string_left = text_left + font->getWidthF32(mLabel.c_str(), 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel.c_str(), filter_offset, label_filter_length);
- F32 yy = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
+ F32 yy = (F32)rect_height - line_height - (F32)mTextPadTop - (F32)sTopPad;
font->render(mLabel, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
label_filter_length, S32_MAX, &right_x);
@@ -1145,7 +1150,7 @@ void LLFolderViewItem::draw()
{
S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size());
F32 match_string_left = text_left + font->getWidthF32(mLabel.c_str(), 0, static_cast<S32>(mLabel.size())) + sSuffixFont->getWidthF32(mLabelSuffix.c_str(), 0, suffix_offset + suffix_filter_length) - sSuffixFont->getWidthF32(mLabelSuffix.c_str(), suffix_offset, suffix_filter_length);
- F32 yy = (F32)rect_height - sSuffixFont->getLineHeight() - (F32)mTextPad - (F32)sTopPad;
+ F32 yy = (F32)rect_height - sSuffixFont->getLineHeight() - (F32)mTextPadTop - (F32)sTopPad;
sSuffixFont->render(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
suffix_filter_length, S32_MAX, &right_x);
@@ -1884,6 +1889,11 @@ void LLFolderViewFolder::updateHasFavorites(bool new_childs_value)
void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
{
LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data);
+ if (gDisconnected || !self)
+ {
+ return;
+ }
+
if (self->mFavoritesDirtyFlags == FAVORITE_CLEANUP)
{
// parent or child already processed the update, clean the callback
@@ -2359,9 +2369,10 @@ bool LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
{
// navigating is going to destroy views and change children
// delay it untill handleDoubleClick processing is complete
- doOnIdleOneTime([this]()
- {
- getViewModelItem()->navigateToFolder(false);
+ LLPointer<LLFolderViewModelItem> view_model_item = getViewModelItem();
+ doOnIdleOneTime([view_model_item]() mutable
+ {;
+ view_model_item->navigateToFolder(false);
});
}
return true;
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 23d794bf26..258a806b91 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -73,7 +73,9 @@ public:
icon_width,
text_pad,
text_pad_right,
+ text_pad_top,
arrow_size,
+ arrow_pad_top,
max_folder_item_overlap;
Optional<bool> single_folder_mode,
double_click_override;
@@ -117,7 +119,9 @@ protected:
mIconWidth,
mTextPad,
mTextPadRight,
+ mTextPadTop,
mArrowSize,
+ mArrowPadTop,
mMaxFolderItemOverlap;
F32 mControlLabelRotation;
diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index 953963b683..40a3e439a6 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -29,8 +29,9 @@
#define LL_LLFUNCTORREGISTRY_H
#include <string>
-#include <map>
+#include <unordered_map>
+#include "llstring.h"
#include "llsd.h"
#include "llsingleton.h"
@@ -56,7 +57,7 @@ class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >
public:
typedef FUNCTOR_TYPE ResponseFunctor;
- typedef typename std::map<std::string, FUNCTOR_TYPE> FunctorMap;
+ typedef typename std::unordered_map<std::string, FUNCTOR_TYPE, ll::string_hash, std::equal_to<>> FunctorMap;
bool registerFunctor(const std::string& name, ResponseFunctor f)
{
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 5892238593..53b5435324 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -194,7 +194,7 @@ protected:
token_list_t mLineTokenList;
token_list_t mDelimiterTokenList;
- typedef std::map<std::string, std::string, std::less<>> element_attributes_t;
+ typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> element_attributes_t;
typedef element_attributes_t::const_iterator attribute_iterator_t;
element_attributes_t mAttributes;
std::string getAttribute(std::string_view key);
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index fe0591ce4b..1dc80671cc 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -48,17 +48,21 @@ static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layo
LLLayoutPanel::Params::Params()
: expanded_min_dim("expanded_min_dim", 0),
min_dim("min_dim", -1),
+ max_dim("max_dim", -1),
user_resize("user_resize", false),
auto_resize("auto_resize", true)
{
addSynonym(min_dim, "min_width");
addSynonym(min_dim, "min_height");
+ addSynonym(max_dim, "max_width");
+ addSynonym(max_dim, "max_height");
}
LLLayoutPanel::LLLayoutPanel(const Params& p)
: LLPanel(p),
mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim),
mMinDim(p.min_dim),
+ mMaxDim(p.max_dim),
mAutoResize(p.auto_resize),
mUserResize(p.user_resize),
mCollapsed(false),
@@ -75,6 +79,7 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
{
mVisibleAmt = 0.f;
}
+ setMaxDim(mMaxDim);
}
void LLLayoutPanel::initFromParams(const Params& p)
@@ -113,6 +118,8 @@ S32 LLLayoutPanel::getTargetDim() const
void LLLayoutPanel::setTargetDim(S32 value)
{
+ value = llmin(value, mMaxDim);
+
LLRect new_rect(getRect());
if (mOrientation == LLLayoutStack::HORIZONTAL)
{
@@ -145,6 +152,7 @@ void LLLayoutPanel::setOrientation( LLView::EOrientation orientation )
setMinDim(layout_dim);
}
mTargetDim = llmax(layout_dim, getMinDim());
+ mTargetDim = llmin(mTargetDim, mMaxDim);
}
void LLLayoutPanel::setVisible( bool visible )
@@ -167,6 +175,7 @@ void LLLayoutPanel::reshape( S32 width, S32 height, bool called_from_parent /*=
if (!mIgnoreReshape && !mAutoResize)
{
mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height;
+ mTargetDim = llmin(mTargetDim, mMaxDim);
LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent());
if (stackp)
{
@@ -439,6 +448,7 @@ void LLLayoutStack::updateLayout()
F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction);
S32 delta = ll_round((F32)space_to_distribute * fraction_to_distribute);
panelp->mTargetDim += delta;
+ panelp->mTargetDim = llmin(panelp->mTargetDim, panelp->mMaxDim);
remaining_space -= delta;
}
}
@@ -455,6 +465,7 @@ void LLLayoutStack::updateLayout()
{
S32 space_for_panel = remaining_space > 0 ? 1 : -1;
panelp->mTargetDim += space_for_panel;
+ panelp->mTargetDim = llmin(panelp->mTargetDim, panelp->mMaxDim);
remaining_space -= space_for_panel;
}
}
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 9e3536aaff..4c78c8a289 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -140,7 +140,8 @@ public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Optional<S32> expanded_min_dim,
- min_dim;
+ min_dim,
+ max_dim;
Optional<bool> user_resize,
auto_resize;
@@ -164,6 +165,8 @@ public:
S32 getMinDim() const { return llmax(0, mMinDim); }
void setMinDim(S32 value) { mMinDim = value; }
+ void setMaxDim(S32 value) { mMaxDim = value < 0 ? S32_MAX : value; }
+
S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }
void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }
@@ -198,6 +201,7 @@ protected:
S32 mExpandedMinDim;
S32 mMinDim;
+ S32 mMaxDim;
bool mCollapsed;
F32 mVisibleAmt;
F32 mCollapseAmt;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index b534c8d4e8..9a88083a5d 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -97,6 +97,7 @@ LLLineEditor::Params::Params()
ignore_tab("ignore_tab", true),
is_password("is_password", false),
allow_emoji("allow_emoji", true),
+ draw_focus_border("draw_focus_border", true),
cursor_color("cursor_color"),
use_bg_color("use_bg_color", false),
bg_color("bg_color"),
@@ -122,6 +123,7 @@ LLLineEditor::Params::Params()
LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
: LLUICtrl(p),
+ mDefaultText(p.default_text),
mMaxLengthBytes(p.max_length.bytes),
mMaxLengthChars(p.max_length.chars),
mCursorPos( 0 ),
@@ -146,6 +148,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mIgnoreTab( p.ignore_tab ),
mDrawAsterixes( p.is_password ),
mAllowEmoji( p.allow_emoji ),
+ mDrawFocusBorder(p.draw_focus_border),
mSpellCheck( p.spellcheck ),
mSpellCheckStart(-1),
mSpellCheckEnd(-1),
@@ -1794,7 +1797,7 @@ void LLLineEditor::drawBackground()
if (!image) return;
// optionally draw programmatic border
- if (has_focus)
+ if (has_focus && mDrawFocusBorder)
{
LLColor4 tmp_color = gFocusMgr.getFocusColor();
tmp_color.setAlpha(alpha);
@@ -1954,12 +1957,11 @@ void LLLineEditor::draw()
width = llmin(width, mTextRightEdge - ll_round(rendered_pixels_right));
gl_rect_2d(ll_round(rendered_pixels_right), cursor_top, ll_round(rendered_pixels_right)+width, cursor_bottom, color);
- LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
rendered_text += mFontBufferSelection.render(
mGLFont,
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
- tmp_color,
+ LLColor4::black,
LLFontGL::LEFT, LLFontGL::BOTTOM,
0,
LLFontGL::NO_SHADOW,
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 3f762822ee..fd248edda3 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -95,7 +95,8 @@ public:
show_label_focused,
is_password,
allow_emoji,
- use_bg_color;
+ use_bg_color,
+ draw_focus_border;
// colors
Optional<LLUIColor> cursor_color,
@@ -202,6 +203,7 @@ public:
void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; }
const std::string& getLabel() { return mLabel.getString(); }
+ void setDefaultText() { setText(mDefaultText); }
void setText(const LLStringExplicit &new_text);
const std::string& getText() const override { return mText.getString(); }
@@ -347,6 +349,7 @@ protected:
LLFontVertexBuffer mFontBufferSelection;
LLFontVertexBuffer mFontBufferPostSelection;
LLFontVertexBuffer mFontBufferLabel;
+ std::string mDefaultText;
S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes
S32 mMaxLengthChars; // Maximum number of characters in the string
S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
@@ -409,6 +412,7 @@ protected:
bool mAllowEmoji;
bool mUseBgColor;
+ bool mDrawFocusBorder;
LLWString mPreeditWString;
LLWString mPreeditOverwrittenWString;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 6ba31c251e..3b21ed8f47 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -73,7 +73,7 @@ S32 MENU_BAR_WIDTH = 410;
/// Local function declarations, constants, enums, and typedefs
///============================================================================
-const S32 LABEL_BOTTOM_PAD_PIXELS = 2;
+const S32 LABEL_BOTTOM_PAD_PIXELS = 1;
const U32 LEFT_PAD_PIXELS = 3;
const U32 LEFT_WIDTH_PIXELS = 15;
@@ -519,21 +519,25 @@ void LLMenuItemGL::draw( void )
}
else
{
+ // Munus are all of the same size, so fixed offset works here,
+ // but it won't work if somebody decides to use different font
+ // todo: adjust logic to work of rect and font height
+ F32 y = (F32)MENU_ITEM_PADDING / 2.f;
if( !mDrawBoolLabel.empty() )
{
- mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
+ mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, false );
}
- mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
+ mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, false );
if( !mDrawAccelLabel.empty() )
{
- mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
+ mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, y, color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, false );
}
if( !mDrawBranchLabel.empty() )
{
- mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
+ mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, y, color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, false );
}
}
@@ -1638,6 +1642,9 @@ void LLMenuItemBranchDownGL::draw( void )
{
color = mDisabledColor.get();
}
+ // Munus are all of the same size, so fixed offset works here,
+ // but it won't work if somebody decides to use different font
+ // todo: adjust logic to work of rect and font height
getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color,
LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL);
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 0ffe6cff5e..56475a2d8d 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1424,6 +1424,7 @@ LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelN
// this function is called once at construction time, after the object is constructed.
void LLNotifications::initSingleton()
{
+ LL_PROFILE_ZONE_SCOPED;
loadTemplates();
loadVisibilityRules();
createDefaultChannels();
@@ -1436,6 +1437,8 @@ void LLNotifications::cleanupSingleton()
void LLNotifications::createDefaultChannels()
{
+ LL_PROFILE_ZONE_SCOPED;
+
LL_INFOS("Notifications") << "Generating default notification channels" << LL_ENDL;
// now construct the various channels AFTER loading the notifications,
// because the history channel is going to rewrite the stored notifications file
@@ -1578,6 +1581,8 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path
bool LLNotifications::loadTemplates()
{
+ LL_PROFILE_ZONE_SCOPED;
+
LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL;
// Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it
// output all relevant pathnames instead of just the ones from the most
@@ -1663,6 +1668,8 @@ bool LLNotifications::loadTemplates()
bool LLNotifications::loadVisibilityRules()
{
+ LL_PROFILE_ZONE_SCOPED;
+
const std::string xml_filename = "notification_visibility.xml";
// Note that here we're looking for the "en" version, the default
// language, rather than the most localized version of this file.
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index d56c459560..ea1cb7f638 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -93,6 +93,7 @@
#include "llinitparam.h"
#include "llinstancetracker.h"
#include "llmortician.h"
+#include "llmutex.h"
#include "llnotificationptr.h"
#include "llpointer.h"
#include "llrefcount.h"
@@ -945,7 +946,7 @@ public:
typedef std::vector<std::string> TemplateNames;
TemplateNames getTemplateNames() const; // returns a list of notification names
- typedef std::map<std::string, LLNotificationTemplatePtr, std::less<>> TemplateMap;
+ typedef std::unordered_map<std::string, LLNotificationTemplatePtr, ll::string_hash, std::equal_to<>> TemplateMap;
TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); }
TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); }
@@ -991,7 +992,7 @@ private:
LLNotificationMap mUniqueNotifications;
- typedef std::map<std::string, std::string, std::less<>> GlobalStringMap;
+ typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> GlobalStringMap;
GlobalStringMap mGlobalStrings;
bool mIgnoreAllNotifications;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 2100b23783..ff5a28b250 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -489,58 +489,69 @@ bool LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
LL_RECORD_BLOCK_TIME(FTM_PANEL_SETUP);
LLXMLNodePtr referenced_xml;
- std::string xml_filename = mXMLFilename;
// if the panel didn't provide a filename, check the node
- if (xml_filename.empty())
+ if (mXMLFilename.empty())
{
- node->getAttributeString("filename", xml_filename);
- setXMLFilename(xml_filename);
+ std::string temp_filename;
+ node->getAttributeString("filename", temp_filename);
+ setXMLFilename(temp_filename);
}
+ // Cache singleton and filename to avoid repeated calls
+ LLUICtrlFactory* factory = LLUICtrlFactory::getInstance();
+
+ // Cache node name pointer to avoid repeated dereferencing
+ const LLStringTableEntry* node_name = node->getName();
+
+ // Cache registry to avoid repeated singleton access
+ const child_registry_t& registry = child_registry_t::instance();
+
LLXUIParser parser;
- if (!xml_filename.empty())
+ if (!mXMLFilename.empty())
{
if (output_node)
{
//if we are exporting, we want to export the current xml
//not the referenced xml
- parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ parser.readXUI(node, params, factory->getCurFileName());
Params output_params(params);
setupParamsForExport(output_params, parent);
- output_node->setName(node->getName()->mString);
+ output_node->setName(node_name->mString);
parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
return true;
}
- LLUICtrlFactory::instance().pushFileName(xml_filename);
+ factory->pushFileName(mXMLFilename);
LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_PANEL_LOAD);
- if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
+ if (!LLUICtrlFactory::getLayeredXMLNode(mXMLFilename, referenced_xml))
{
- LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL;
+ LL_WARNS() << "Couldn't parse panel from: " << mXMLFilename << LL_ENDL;
return false;
}
- parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ // Get filename after pushFileName
+ const std::string& updated_filename = factory->getCurFileName();
+ parser.readXUI(referenced_xml, params, updated_filename);
// add children using dimensions from referenced xml for consistent layout
setShape(params.rect);
- LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
+ LLUICtrlFactory::createChildren(this, referenced_xml, registry);
- LLUICtrlFactory::instance().popFileName();
+ factory->popFileName();
}
// ask LLUICtrlFactory for filename, since xml_filename might be empty
- parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ parser.readXUI(node, params, factory->getCurFileName());
if (output_node)
{
Params output_params(params);
setupParamsForExport(output_params, parent);
- output_node->setName(node->getName()->mString);
+ output_node->setName(node_name->mString);
parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
}
@@ -552,7 +563,7 @@ bool LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
}
// add children
- LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
+ LLUICtrlFactory::createChildren(this, node, registry, output_node);
// Connect to parent after children are built, because tab containers
// do a reshape() on their child panels, which requires that the children
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index fe861dc719..a928997c7d 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -250,7 +250,7 @@ private:
LLButton* mDefaultBtn;
LLUIString mLabel;
- typedef std::map<std::string, std::string, std::less<>> ui_string_map_t;
+ typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> ui_string_map_t;
ui_string_map_t mUIStrings;
@@ -292,7 +292,7 @@ public:
}
private:
- typedef std::map< std::string, LLPanelClassCreatorFunc, std::less<>> param_name_map_t;
+ typedef std::unordered_map<std::string, LLPanelClassCreatorFunc, ll::string_hash, std::equal_to<>> param_name_map_t;
param_name_map_t mPanelClassesNames;
};
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 2aff434612..1dbd9f5b0c 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -67,7 +67,7 @@ protected:
LLSD mPayload; // stores data that this item represents in the radio group
};
-static LLWidgetNameRegistry::StaticRegistrar register_radio_item(&typeid(LLRadioGroup::ItemParams), "radio_item");
+static LLWidgetNameRegistry::StaticRegistrar register_radio_item(typeid(LLRadioGroup::ItemParams), "radio_item");
LLRadioGroup::Params::Params()
: allow_deselect("allow_deselect"),
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
index 1b4008cff2..5b0d2315c1 100644
--- a/indra/llui/llrngwriter.cpp
+++ b/indra/llui/llrngwriter.cpp
@@ -94,7 +94,7 @@ void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam:
block.inspectBlock(*this);
// add includes for all possible children
- const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
+ const std::type_index& type = *LLWidgetTypeRegistry::instance().getValue(type_name);
const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
// add include declarations for all valid children
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index df99c4f636..e36fd45bb4 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -480,6 +480,7 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height
void LLScrollContainer::draw()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
static LLUICachedControl<S32> scrollbar_size_control ("UIScrollbarSize", 0);
S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize);
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index a4510d1fc2..b5ba466750 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -39,7 +39,7 @@
const S32 MIN_COLUMN_WIDTH = 20;
// defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(typeid(LLScrollColumnHeader::Params), "scroll_column_header");
//---------------------------------------------------------------------------
// LLScrollColumnHeader
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index b459c67dad..558ce6a7fd 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -3185,6 +3185,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS
if (cell_p.width.isProvided())
{
new_column.width.pixel_width = cell_p.width;
+ new_column.width.pixel_width.choose();
}
addColumn(new_column);
columnp = mColumns[column];
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 5e0985c79c..27f1dcb03d 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -483,7 +483,7 @@ void LLTabContainer::draw()
tuple->mButton->setVisible( true );
}
- S32 max_scroll_visible = getTabCount() - getMaxScrollPos() + getScrollPos();
+ S32 max_scroll_visible = getVisibleTabCount() - getMaxScrollPos() + getScrollPos();
S32 idx = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
@@ -1380,6 +1380,20 @@ S32 LLTabContainer::getTabCount() const
return static_cast<S32>(mTabList.size());
}
+S32 LLTabContainer::getVisibleTabCount() const
+{
+ S32 visible_count = 0;
+ for (tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr)
+ {
+ const LLTabTuple* pTT = *itr;
+ if (pTT->mVisible)
+ {
+ visible_count++;
+ }
+ }
+ return visible_count;
+}
+
LLPanel* LLTabContainer::getPanelByIndex(S32 index) const
{
if (index >= 0 && index < (S32)mTabList.size())
@@ -2109,6 +2123,14 @@ void LLTabContainer::updateMaxScrollPos()
S32 tab_space = 0;
S32 available_space = 0;
tab_space = mTotalTabWidth;
+ for(tuple_list_t::const_iterator tab_it = mTabList.begin(); tab_it != mTabList.end(); ++tab_it)
+ {
+ const LLTabTuple* tuple = *tab_it;
+ if (!tuple->mVisible)
+ {
+ tab_space -= tuple->mButton->getRect().getWidth();
+ }
+ }
available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_tab_h_pad);
if( tab_space > available_space )
@@ -2118,7 +2140,7 @@ void LLTabContainer::updateMaxScrollPos()
available_width_with_arrows -= tabcntr_tab_partial_width;
S32 running_tab_width = 0;
- setMaxScrollPos(getTabCount());
+ setMaxScrollPos(getVisibleTabCount());
for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
{
running_tab_width += (*tab_it)->mButton->getRect().getWidth();
@@ -2129,7 +2151,7 @@ void LLTabContainer::updateMaxScrollPos()
setMaxScrollPos(getMaxScrollPos()-1);
}
// in case last tab doesn't actually fit on screen, make it the last scrolling position
- setMaxScrollPos(llmin(getMaxScrollPos(), getTabCount() - 1));
+ setMaxScrollPos(llmin(getMaxScrollPos(), getVisibleTabCount() - 1));
no_scroll = false;
}
}
@@ -2202,3 +2224,16 @@ void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible )
updateMaxScrollPos();
}
+
+bool LLTabContainer::getTabVisibility(const LLPanel* panel) const
+{
+ for (tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr)
+ {
+ LLTabTuple const* pTT = *itr;
+ if (pTT->mTabPanel == panel)
+ {
+ return pTT->mVisible;
+ }
+ }
+ return false;
+}
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 4ac7e73d25..3095e641f8 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -188,6 +188,7 @@ public:
LLPanel* getCurrentPanel();
S32 getCurrentPanelIndex() const;
S32 getTabCount() const;
+ S32 getVisibleTabCount() const;
LLPanel* getPanelByIndex(S32 index) const;
S32 getIndexForPanel(LLPanel* panel) const;
S32 getPanelIndexByTitle(std::string_view title) const;
@@ -225,6 +226,7 @@ public:
S32 getMaxTabWidth() const { return mMaxTabWidth; }
void setTabVisibility( LLPanel const *aPanel, bool );
+ bool getTabVisibility(const LLPanel* panel) const;
void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); }
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 2079ff17fc..0521853b02 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -51,6 +51,9 @@ const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
const S32 CURSOR_THICKNESS = 2;
const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click.
+constexpr F32 FOCUSED_SELECTION_BG_ALPHA = 1;
+constexpr F32 UNFOCUSED_SELECTION_BG_ALPHA = 0.7f;
+
LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num)
: mDocIndexStart(index_start),
mDocIndexEnd(index_end),
@@ -129,7 +132,7 @@ struct LLTextBase::line_end_compare
//
// register LLTextBase::Params under name "textbase"
-static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(&typeid(LLTextBase::Params), "textbase");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(typeid(LLTextBase::Params), "textbase");
LLTextBase::LineSpacingParams::LineSpacingParams()
: multiple("multiple", 1.f),
@@ -222,6 +225,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mTrustedContent(p.trusted_content),
mAlwaysShowIcons(p.always_show_icons),
mTrackEnd( p.track_end ),
+ mTrackValueChange(true),
mScrollIndex(-1),
mSelectionStart( 0 ),
mSelectionEnd( 0 ),
@@ -529,7 +533,7 @@ void LLTextBase::drawSelectionBackground()
// Draw the selection box (we're using a box instead of reversing the colors on the selected text).
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
const LLColor4& color = mSelectedBGColor;
- F32 alpha = hasFocus() ? 0.7f : 0.3f;
+ F32 alpha = hasFocus() ? FOCUSED_SELECTION_BG_ALPHA : UNFOCUSED_SELECTION_BG_ALPHA;
alpha *= getDrawContext().mAlpha;
LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha);
@@ -964,7 +968,10 @@ void LLTextBase::drawText()
S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments )
{
- beforeValueChange();
+ if (mTrackValueChange)
+ {
+ beforeValueChange();
+ }
S32 old_len = getLength(); // length() returns character length
S32 insert_len = static_cast<S32>(wstr.length());
@@ -1087,12 +1094,14 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
getViewModel()->getEditableDisplay().insert(pos, wstr);
- if ( truncate() )
+ if (mTrackValueChange)
{
- insert_len = getLength() - old_len;
+ if (truncate())
+ {
+ insert_len = getLength() - old_len;
+ }
+ onValueChange(pos, pos + insert_len);
}
-
- onValueChange(pos, pos + insert_len);
needsReflow(pos);
return insert_len;
@@ -1108,7 +1117,10 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
// Clamp length to not go past the end of the text
length = std::min(length, text_length - pos);
- beforeValueChange();
+ if (mTrackValueChange)
+ {
+ beforeValueChange();
+ }
segment_set_t::iterator seg_iter = getSegIterContaining(pos);
while(seg_iter != mSegments.end())
{
@@ -1159,7 +1171,10 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
// recreate default segment in case we erased everything
createDefaultSegment();
- onValueChange(pos, pos);
+ if (mTrackValueChange)
+ {
+ onValueChange(pos, pos);
+ }
needsReflow(pos);
return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
@@ -1167,7 +1182,10 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
{
- beforeValueChange();
+ if (mTrackValueChange)
+ {
+ beforeValueChange();
+ }
if (pos > (S32)getLength())
{
@@ -1175,7 +1193,10 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
}
getViewModel()->getEditableDisplay()[pos] = wc;
- onValueChange(pos, pos + 1);
+ if (mTrackValueChange)
+ {
+ onValueChange(pos, pos + 1);
+ }
needsReflow(pos);
return 1;
@@ -1622,7 +1643,7 @@ void LLTextBase::deselect()
bool LLTextBase::getSpellCheck() const
{
- return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck);
+ return (!mReadOnly) && (LLSpellChecker::getUseSpellCheck()) && (mSpellCheck);
}
const std::string& LLTextBase::getSuggestion(U32 index) const
@@ -2330,6 +2351,10 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
+ beforeValueChange();
+ // Can insert a lot of different segments, don't want to spam events.
+ mTrackValueChange = false;
+
// clear out the existing text and segments
getViewModel()->setDisplay(LLWStringUtil::null);
@@ -2350,6 +2375,8 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params&
startOfDoc();
}
+ truncate(); // was postponed to avoid micro truncations and expensive checks
+ mTrackValueChange = true;
onValueChange(0, getLength());
}
@@ -2380,6 +2407,10 @@ void LLTextBase::appendTextImpl(const std::string& new_text, const LLStyle::Para
LLStyle::Params style_params(getStyleParams());
style_params.overwriteFrom(input_params);
+ // todo: this does not check for maximum size, might
+ // want to stop once maximum size was reached to avoid
+ // expensive findUrl, replaceUrl calls.
+
S32 part = (S32)LLTextParser::WHOLE;
if ((mParseHTML || force_slurl) && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
{
@@ -2553,6 +2584,10 @@ void LLTextBase::copyContents(const LLTextBase* source)
beforeValueChange();
deselect();
+ // Can insert a lot of different segments, don't want to spam events.
+ // Do one full length onValueChange() at the end of this function.
+ mTrackValueChange = false;
+
mSegments.clear();
for (const LLTextSegmentPtr& segp : source->mSegments)
{
@@ -2567,6 +2602,8 @@ void LLTextBase::copyContents(const LLTextBase* source)
getViewModel()->setDisplay(source->getViewModel()->getDisplay());
+ truncate(); // was postponed to avoid micro truncations and expensive checks
+ mTrackValueChange = true;
onValueChange(0, getLength());
needsReflow();
}
@@ -2821,7 +2858,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round,
line_seg_iter != mSegments.end();
++line_seg_iter, line_seg_offset = 0)
{
- const LLTextSegmentPtr segmentp = *line_seg_iter;
+ LLTextSegmentPtr segmentp = *line_seg_iter;
S32 segment_line_start = segmentp->getStart() + line_seg_offset;
S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd) - segment_line_start;
@@ -2912,7 +2949,7 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
while(line_seg_iter != mSegments.end())
{
- const LLTextSegmentPtr segmentp = *line_seg_iter;
+ LLTextSegmentPtr segmentp = *line_seg_iter;
if (line_seg_iter == cursor_seg_iter)
{
@@ -3463,8 +3500,8 @@ LLStyleSP LLTextSegment::cloneStyle(LLTextBase& target, const LLStyle* source)
}
-bool LLTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = 0; return false; }
-bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+bool LLTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) { width = 0; height = 0; return false; }
+bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height)
{
F32 fwidth = 0;
bool result = getDimensionsF32(first_char, num_chars, fwidth, height);
@@ -3561,6 +3598,7 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
+ mFontWidthBuffer.reset();
}
return draw_rect.mLeft;
}
@@ -3586,6 +3624,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
+ mFontWidthBuffer.reset();
}
const LLFontGL* font = mStyle->getFont();
@@ -3817,17 +3856,19 @@ LLTextSegmentPtr LLNormalTextSegment::clone(LLTextBase& target) const
return new LLNormalTextSegment(sp, mStart, mEnd, target);
}
-bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
{
height = 0;
width = 0;
if (num_chars > 0 && (mStart + first_char >= 0))
{
height = mFontHeight;
- const LLWString &text = getWText();
- // if last character is a newline, then return true, forcing line break
- width = mStyle->getFont()->getWidthF32(text.c_str(), mStart + first_char, num_chars, true);
+
+ const LLWString& text = getWText();
+ const LLFontGL* font = mStyle->getFont();
+ width += mFontWidthBuffer.getWidth(font, text.c_str(), mStart + first_char, num_chars, true);
}
+ // if last character is a newline, then return true, forcing line break
return false;
}
@@ -3909,6 +3950,7 @@ void LLNormalTextSegment::updateLayout(const class LLTextBase& editor)
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
+ mFontWidthBuffer.reset();
}
void LLNormalTextSegment::dump() const
@@ -4060,7 +4102,7 @@ LLTextSegmentPtr LLInlineViewSegment::clone(LLTextBase& target) const
return nullptr;
}
-bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
{
if (first_char == 0 && num_chars == 0)
{
@@ -4152,7 +4194,7 @@ LLTextSegmentPtr LLLineBreakTextSegment::clone(LLTextBase& target) const
copy->mFontHeight = mFontHeight;
return copy;
}
-bool LLLineBreakTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+bool LLLineBreakTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
{
width = 0;
height = mFontHeight;
@@ -4189,7 +4231,7 @@ LLTextSegmentPtr LLImageTextSegment::clone(LLTextBase& target) const
static const S32 IMAGE_HPAD = 3;
// virtual
-bool LLImageTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+bool LLImageTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
{
width = 0;
height = mStyle->getFont()->getLineHeight();
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 3ab5e905e3..bc39d9732c 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -68,10 +68,10 @@ public:
virtual LLTextSegmentPtr clone(LLTextBase& terget) const { return new LLTextSegment(mStart, mEnd); }
static LLStyleSP cloneStyle(LLTextBase& target, const LLStyle* source);
- bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
+ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height);
bool getPermitsEmoji() const { return mPermitsEmoji; };
- virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height);
virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
/**
@@ -139,7 +139,7 @@ public:
virtual ~LLNormalTextSegment();
/*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height);
/*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
/*virtual*/ void updateLayout(const class LLTextBase& editor);
@@ -182,6 +182,7 @@ protected:
LLFontVertexBuffer mFontBufferPreSelection;
LLFontVertexBuffer mFontBufferSelection;
LLFontVertexBuffer mFontBufferPostSelection;
+ LLFontWidthBuffer mFontWidthBuffer;
S32 mLastGeneration = -1;
};
@@ -254,7 +255,7 @@ public:
~LLInlineViewSegment();
/*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height);
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
/*virtual*/ void updateLayout(const class LLTextBase& editor);
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
@@ -280,7 +281,7 @@ public:
LLLineBreakTextSegment(S32 pos);
~LLLineBreakTextSegment();
/*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height);
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
@@ -295,7 +296,7 @@ public:
~LLImageTextSegment();
/*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height);
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
@@ -408,6 +409,7 @@ public:
/*virtual*/ void setColor(const LLUIColor& c) override;
virtual void setReadOnlyColor(const LLUIColor& c);
/*virtual*/ void onVisibilityChange(bool new_visibility) override;
+ void setBgReadOnlyColor(const LLUIColor& c) { mReadOnlyBgColor = c; }
/*virtual*/ void setValue(const LLSD& value) override;
/*virtual*/ LLTextViewModel* getViewModel() const override;
@@ -761,6 +763,7 @@ protected:
bool mUseEmoji;
bool mUseColor;
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
+ bool mTrackValueChange; // if true, send out onValueChange() from low level text modification methods
bool mReadOnly;
bool mBGVisible; // render background?
bool mClip; // clip text to widget rect
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index fcdf3782ae..7689b93374 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -581,7 +581,7 @@ S32 LLTextEditor::indentLine( S32 pos, S32 spaces )
LLWString wtext = getWText();
if (wtext[pos] == ' ')
{
- delta_spaces += remove( pos, 1, false );
+ delta_spaces -= remove( pos, 1, false );
}
}
}
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 74f03618cf..c5b1b5ba1d 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -129,7 +129,7 @@ void LLToolTipView::drawStickyRect()
}
// defaults for floater param block pulled from widgets/floater.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(&typeid(LLInspector::Params), "inspector");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(typeid(LLInspector::Params), "inspector");
//
// LLToolTip
diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h
index c5d01e6f8d..4dba4c5c3e 100644
--- a/indra/llui/lltrans.h
+++ b/indra/llui/lltrans.h
@@ -125,7 +125,7 @@ public:
}
private:
- typedef std::map<std::string, LLTransTemplate, std::less<>> template_map_t;
+ typedef std::unordered_map<std::string, LLTransTemplate, ll::string_hash, std::equal_to<>> template_map_t;
static template_map_t sStringTemplates;
static template_map_t sDefaultStringTemplates;
static LLStringUtil::format_map_t sDefaultArgs;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 179d1dcaff..5e01cffe38 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -65,7 +65,6 @@
// for XUIParse
#include "llquaternion.h"
-#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#include <boost/algorithm/string/finder.hpp>
@@ -157,6 +156,7 @@ mWindow(NULL), // set later in startup
mRootView(NULL),
mHelpImpl(NULL)
{
+ LL_PROFILE_ZONE_SCOPED;
LLRender2D::createInstance(image_provider);
LLSpellChecker::createInstance();
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 2ef64baaf6..091e0ab1cf 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -114,7 +114,7 @@ class LLUI : public LLSimpleton<LLUI>
{
LOG_CLASS(LLUI);
public:
- typedef std::map<std::string, LLControlGroup*, std::less<> > settings_map_t;
+ typedef std::unordered_map<std::string, LLControlGroup*, ll::string_hash, std::equal_to<>> settings_map_t;
LLUI(const settings_map_t &settings,
LLImageProviderInterface* image_provider,
diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index a792cb8103..7a4f72fe4f 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -198,8 +198,8 @@ LLUIColor LLUIColorTable::getColor(std::string_view name, const LLColor4& defaul
// update user color, loaded colors are parsed on initialization
void LLUIColorTable::setColor(std::string_view name, const LLColor4& color)
{
- auto it = mUserSetColors.lower_bound(name);
- if(it != mUserSetColors.end() && !(mUserSetColors.key_comp()(name, it->first)))
+ auto it = mUserSetColors.find(name);
+ if(it != mUserSetColors.end())
{
it->second = color;
}
@@ -330,9 +330,8 @@ void LLUIColorTable::clearTable(string_color_map_t& table)
// if the color already exists it changes the color
void LLUIColorTable::setColor(std::string_view name, const LLColor4& color, string_color_map_t& table)
{
- string_color_map_t::iterator it = table.lower_bound(name);
- if(it != table.end()
- && !(table.key_comp()(name, it->first)))
+ string_color_map_t::iterator it = table.find(name);
+ if(it != table.end())
{
it->second = color;
}
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
index 0c6286e5eb..aff6f59db6 100644
--- a/indra/llui/lluicolortable.h
+++ b/indra/llui/lluicolortable.h
@@ -27,7 +27,7 @@
#ifndef LL_LLUICOLORTABLE_H_
#define LL_LLUICOLORTABLE_H_
-#include <map>
+#include <unordered_map>
#include "llinitparam.h"
#include "llsingleton.h"
@@ -42,7 +42,7 @@ class LLUIColorTable : public LLSingleton<LLUIColorTable>
LOG_CLASS(LLUIColorTable);
// consider using sorted vector, can be much faster
- typedef std::map<std::string, LLUIColor, std::less<>> string_color_map_t;
+ typedef std::unordered_map<std::string, LLUIColor, ll::string_hash, std::equal_to<>> string_color_map_t;
public:
struct ColorParams : LLInitParam::ChoiceBlock<ColorParams>
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 05461edd82..9a27049d37 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -80,7 +80,7 @@ LLUICtrl::Params::Params()
mouseenter_callback("mouseenter_callback"),
mouseleave_callback("mouseleave_callback"),
control_name("control_name"),
- font("font", LLFontGL::getFontEmojiMedium()),
+ font("font", LLFontGL::getFontEmojiSmall()),
font_halign("halign"),
font_valign("valign"),
length("length"), // ignore LLXMLNode cruft
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 9abccfd9a0..740f187ed8 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -67,7 +67,7 @@ public:
static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate");
// Build time optimization, generate this once in .cpp file
-template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
+template class LLUICtrlFactory* LLSimpleton<class LLUICtrlFactory>::getInstance();
//-----------------------------------------------------------------------------
// LLUICtrlFactory()
@@ -253,7 +253,7 @@ const LLInitParam::BaseBlock& get_empty_param_block()
// adds a widget and its param block to various registries
//static
-void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name)
+void LLUICtrlFactory::registerWidget(std::type_index widget_type, std::type_index param_block_type, const std::string& name)
{
// associate parameter block type with template .xml file
std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type);
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index fc069c078f..75cee5f004 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -65,7 +65,7 @@ class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
// lookup widget name by type
class LLWidgetNameRegistry
-: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
+: public LLRegistrySingleton<std::type_index, std::string, LLWidgetNameRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLWidgetNameRegistry);
};
@@ -74,19 +74,20 @@ class LLWidgetNameRegistry
// this is used for schema generation
//typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
//class LLDefaultParamBlockRegistry
-//: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
+//: public LLRegistrySingleton<std::type_index, empty_param_block_func_t, LLDefaultParamBlockRegistry>
//{
// LLSINGLETON(LLDefaultParamBlockRegistry);
//};
// Build time optimization, generate this once in .cpp file
#ifndef LLUICTRLFACTORY_CPP
-extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
+extern template class LLUICtrlFactory* LLSimpleton<class LLUICtrlFactory>::getInstance();
#endif
-class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
+class LLUICtrlFactory : public LLSimpleton<LLUICtrlFactory>
{
- LLSINGLETON(LLUICtrlFactory);
+public:
+ LLUICtrlFactory();
~LLUICtrlFactory();
// only partial specialization allowed in inner classes, so use extra dummy parameter
@@ -202,7 +203,7 @@ private:
static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest);
// helper function for adding widget type info to various registries
- static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag);
+ static void registerWidget(std::type_index widget_type, std::type_index param_block_type, const std::string& tag);
static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
@@ -290,7 +291,7 @@ template <typename PARAM_BLOCK, int DUMMY>
LLUICtrlFactory::ParamDefaults<PARAM_BLOCK, DUMMY>::ParamDefaults()
{
// look up template file for this param block...
- const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));
+ const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(typeid(PARAM_BLOCK));
if (param_block_tag)
{ // ...and if it exists, back fill values using the most specific template first
PARAM_BLOCK params;
@@ -313,13 +314,17 @@ template<typename T>
LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func)
: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func == nullptr ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func)
{
+ if (!LLUICtrlFactory::instanceExists())
+ {
+ LLUICtrlFactory::createInstance();
+ }
// add this widget to various registries
- LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), tag);
+ LLUICtrlFactory::instance().registerWidget(typeid(T), typeid(typename T::Params), tag);
// since registry_t depends on T, do this in line here
// TODO: uncomment this for schema generation
//typedef typename T::child_registry_t registry_t;
- //LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance());
+ //LLChildRegistryRegistry::instance().defaultRegistrar().add(typeid(T), registry_t::instance());
}
#endif //LLUICTRLFACTORY_H
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index cb101d325d..8a21222b3c 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -149,12 +149,77 @@ static bool stringHasUrl(const std::string &text)
// fast heuristic test for a URL in a string. This is used
// to avoid lots of costly regex calls, BUT it needs to be
// kept in sync with the LLUrlEntry regexes we support.
- return (text.find("://") != std::string::npos ||
- text.find("www.") != std::string::npos ||
- text.find(".com") != std::string::npos ||
- text.find("<nolink>") != std::string::npos ||
- text.find("<icon") != std::string::npos ||
- text.find("@") != std::string::npos);
+
+ // Early exit for empty or very short strings
+ // Smallest url is 5 characters
+ if (text.length() < 3)
+ {
+ return false;
+ }
+
+ // Single pass search for common URL indicators
+ for (size_t i = 0; i < text.length(); ++i)
+ {
+ char c = text[i];
+
+ // Check for @ (email or mention)
+ if (c == '@')
+ {
+ return true;
+ }
+
+ if (i + 3 >= text.length())
+ {
+ // Nothing else is going to match or fit if we don't
+ // have at least 4 characters left
+ // Ex: expectation is that there is something after protocol delimiter
+ // and .com takes 4 characters.
+ return false;
+ }
+
+ // Check for protocol delimiter
+ if (c == ':' && text[i + 1] == '/' && text[i + 2] == '/')
+ {
+ return true;
+ }
+
+ // Check for www. at start of word
+ if (c == 'w'
+ && text[i + 1] == 'w'
+ && text[i + 2] == 'w'
+ && text[i + 3] == '.')
+ {
+ return true;
+ }
+
+ // Check for .com (and similar)
+ if (c == '.')
+ {
+ const char* suffix = text.c_str() + i + 1;
+ if ((suffix[0] == 'c' && suffix[1] == 'o' && suffix[2] == 'm') ||
+ (suffix[0] == 'n' && suffix[1] == 'e' && suffix[2] == 't') ||
+ (suffix[0] == 'o' && suffix[1] == 'r' && suffix[2] == 'g') ||
+ (suffix[0] == 'e' && suffix[1] == 'd' && suffix[2] == 'u'))
+ {
+ return true;
+ }
+ }
+
+ // Check for <nolink> or <icon
+ if (c == '<')
+ {
+ if (i + 7 < text.length() && text.compare(i + 1, 6, "nolink") == 0)
+ {
+ return true;
+ }
+ if (i + 4 < text.length() && text.compare(i + 1, 4, "icon") == 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted, bool skip_non_mentions)
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index d53fd6eb91..68ca61681c 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -149,7 +149,7 @@ void LLViewBorder::drawOnePixelLines()
top_color = gFocusMgr.getFocusColor();
bottom_color = top_color;
- LLUI::setLineWidth(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt()));
+ LLUI::setLineWidth(lerp(1.f, 2.f, gFocusMgr.getFocusFlashAmt()));
}
S32 left = 0;
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index 8cd11b86b3..52afac430e 100644
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -602,7 +602,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui");
// add includes for all possible children
- const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
+ const std::type_index& type = *LLWidgetTypeRegistry::instance().getValue(type_name);
const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
// add choices for valid children
@@ -1459,7 +1459,7 @@ void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int
void LLSimpleXUIParser::characterData(const char *s, int len)
{
- mTextContents += std::string(s, len);
+ mTextContents.append(s, len);
}
void LLSimpleXUIParser::startElement(const char *name, const char **atts)
@@ -1480,24 +1480,24 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
mOutputStack.back().second++;
S32 num_tokens_pushed = 0;
- std::string child_name(name);
+ std::string_view child_name(name);
if (mOutputStack.back().second == 1)
{ // root node for this block
- mScope.push_back(child_name);
+ mScope.emplace_back(child_name);
}
else
{ // compound attribute
if (child_name.find(".") == std::string::npos)
{
- mNameStack.push_back(std::make_pair(child_name, true));
+ mNameStack.emplace_back(child_name, true);
num_tokens_pushed++;
- mScope.push_back(child_name);
+ mScope.emplace_back(child_name);
}
else
{
// parse out "dotted" name into individual tokens
- tokenizer name_tokens(child_name, sep);
+ tokenizer name_tokens(std::string(child_name), sep);
tokenizer::iterator name_token_it = name_tokens.begin();
if(name_token_it == name_tokens.end())
@@ -1603,8 +1603,8 @@ bool LLSimpleXUIParser::processText()
LLStringUtil::trim(mTextContents);
if (!mTextContents.empty())
{
- mNameStack.push_back(std::make_pair(std::string("value"), true));
- mCurAttributeValueBegin = mTextContents.c_str();
+ mNameStack.emplace_back("value", true);
+ mCurAttributeValueBegin = std::move(mTextContents);
mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
mNameStack.pop_back();
}
@@ -1648,12 +1648,12 @@ bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr)
bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- if (!strcmp(self.mCurAttributeValueBegin, "true"))
+ if (!strcmp(self.mCurAttributeValueBegin.c_str(), "true"))
{
*((bool*)val_ptr) = true;
return true;
}
- else if (!strcmp(self.mCurAttributeValueBegin, "false"))
+ else if (!strcmp(self.mCurAttributeValueBegin.c_str(), "false"))
{
*((bool*)val_ptr) = false;
return true;
@@ -1665,56 +1665,56 @@ bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- *((std::string*)val_ptr) = self.mCurAttributeValueBegin;
+ *((std::string*)val_ptr) = std::move(self.mCurAttributeValueBegin);
return true;
}
bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U8*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S8*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U16*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S16*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U32*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S32*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(*(F32*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
{
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
- return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
+ return parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(*(F64*)val_ptr)]).full;
}
bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
@@ -1722,7 +1722,7 @@ bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
LLColor4 value;
- if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+ if (parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
{
*(LLColor4*)(val_ptr) = value;
return true;
@@ -1736,7 +1736,7 @@ bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
LLColor4 value;
LLUIColor* colorp = (LLUIColor*)val_ptr;
- if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+ if (parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
{
colorp->set(value);
return true;
@@ -1749,7 +1749,7 @@ bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
LLUUID temp_id;
// LLUUID::set is destructive, so use temporary value
- if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
+ if (temp_id.set(self.mCurAttributeValueBegin))
{
*(LLUUID*)(val_ptr) = temp_id;
return true;
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
index 2179ae54d3..3cc564772e 100644
--- a/indra/llui/llxuiparser.h
+++ b/indra/llui/llxuiparser.h
@@ -40,7 +40,7 @@ class LLView;
// lookup widget type by name
class LLWidgetTypeRegistry
-: public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry>
+: public LLRegistrySingleton<std::string, std::type_index, LLWidgetTypeRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLWidgetTypeRegistry);
};
@@ -52,7 +52,7 @@ typedef std::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
class LLChildRegistryRegistry
-: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
+: public LLRegistrySingleton<std::type_index, widget_registry_t, LLChildRegistryRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLChildRegistryRegistry);
};
@@ -247,7 +247,7 @@ private:
S32 mCurReadDepth;
std::string mCurFileName;
std::string mTextContents;
- const char* mCurAttributeValueBegin;
+ std::string mCurAttributeValueBegin;
std::vector<S32> mTokenSizeStack;
std::vector<std::string> mScope;
std::vector<bool> mEmptyLeafNode;
diff --git a/indra/llwebrtc/CMakeLists.txt b/indra/llwebrtc/CMakeLists.txt
index a01d9fc632..31ba0af208 100644
--- a/indra/llwebrtc/CMakeLists.txt
+++ b/indra/llwebrtc/CMakeLists.txt
@@ -47,7 +47,14 @@ if (WINDOWS)
set_target_properties(llwebrtc PROPERTIES PDB_OUTPUT_DIRECTORY "${SYMBOLS_STAGING_DIR}")
endif (USE_BUGSPLAT)
elseif (DARWIN)
- target_link_libraries(llwebrtc PRIVATE ll::webrtc)
+ target_link_libraries(llwebrtc PRIVATE ll::webrtc
+ "-framework AVFoundation"
+ "-framework AudioToolbox"
+ "-framework CoreAudio"
+ "-framework CoreMedia"
+ "-framework CoreVideo"
+ "-framework Foundation"
+ )
if (USE_BUGSPLAT)
set_target_properties(llwebrtc PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym"
XCODE_ATTRIBUTE_DWARF_DSYM_FOLDER_PATH "${SYMBOLS_STAGING_DIR}/dSYMs")
@@ -69,6 +76,14 @@ ADD_CUSTOM_COMMAND(TARGET llwebrtc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:llwebrtc>
${SHARED_LIB_STAGING_DIR})
+
+if (CMAKE_BUILD_TYPE MATCHES Release AND (CMAKE_CXX_COMPILER_ID STREQUAL Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU))
+ add_custom_command(
+ TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_STRIP} lib${PROJECT_NAME}.so
+ )
+endif ()
+
# Add tests
if (LL_TESTS)
endif (LL_TESTS)
@@ -76,12 +91,14 @@ endif (LL_TESTS)
if (INSTALL)
if (DARWIN)
set(_LIB ../Frameworks)
+ elseif (${LINUX_DISTRO} MATCHES freedesktop)
+ set(_LIB lib)
elseif (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
- set(_LIB lib/${ARCH}-linux-gnu)
+ set(_LIB lib/${ARCH}-linux-gnu/${VIEWER_BINARY_NAME})
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR (${LINUX_DISTRO} MATCHES gentoo))
- set(_LIB lib${ADDRESS_SIZE})
+ set(_LIB lib${ADDRESS_SIZE}/${VIEWER_BINARY_NAME})
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
if (WINDOWS)
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index d780b1d606..8b77a39541 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -26,8 +26,11 @@
#include "llwebrtc_impl.h"
#include <algorithm>
+#include <chrono>
+#include <future>
+#include <thread>
#include <string.h>
-
+#include "api/audio/create_audio_device_module.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/audio_encoder_factory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
@@ -56,8 +59,8 @@ webrtc::LossBasedBweV2::Config::Config()
namespace llwebrtc
{
#if WEBRTC_WIN
-static int16_t PLAYOUT_DEVICE_DEFAULT = webrtc::AudioDeviceModule::kDefaultDevice;
-static int16_t RECORD_DEVICE_DEFAULT = webrtc::AudioDeviceModule::kDefaultDevice;
+static int16_t PLAYOUT_DEVICE_DEFAULT = webrtc::AudioDeviceModule::kDefaultCommunicationDevice;
+static int16_t RECORD_DEVICE_DEFAULT = webrtc::AudioDeviceModule::kDefaultCommunicationDevice;
#else
static int16_t PLAYOUT_DEVICE_DEFAULT = 0;
static int16_t RECORD_DEVICE_DEFAULT = 0;
@@ -148,7 +151,9 @@ int32_t LLWebRTCAudioTransport::NeedMorePlayData(size_t number_of_frames,
if (!engine)
{
// No engine sink; output silence to be safe.
- const size_t bytes = number_of_frames * bytes_per_frame * number_of_channels;
+ // bytes_per_frame already accounts for all channels, so do not multiply
+ // by number_of_channels again (that would overrun the playout buffer).
+ const size_t bytes = number_of_frames * bytes_per_frame;
memset(audio_data, 0, bytes);
number_of_samples_out = bytes_per_frame;
return 0;
@@ -264,17 +269,47 @@ void LLCustomProcessor::Process(webrtc::AudioBuffer *audio)
mState->setMicrophoneEnergy(std::sqrt(totalSum / (audio->num_channels() * audio->num_frames() * buffer_size)));
}
+
+//
+// LLWebRTCImpl implementation
+//
+
+void LLWebRTCAudioDeviceModule::SetTuning(bool tuning, bool mute)
+{
+ tuning_ = tuning;
+ if (tuning)
+ {
+ // Ensure capture is running (it's normally already running -- capture is
+ // session-long) so the mic-level meter works, and stop rendering the
+ // call while tuning. The recording calls are no-ops if capture is
+ // already active, so this won't cold-start it.
+ inner_->InitMicrophone();
+ inner_->InitRecording();
+ inner_->StartRecording();
+ inner_->StopPlayout();
+ }
+ // On exit, capture is deliberately left running (mute is handled by gain,
+ // not by stopping the device, so there's no AEC cold-start hiss). Playout
+ // is restored by the caller via workerOpenPlayout(), keeping it gated on
+ // there being a connection to render.
+}
+
//
// LLWebRTCImpl implementation
//
LLWebRTCImpl::LLWebRTCImpl(LLWebRTCLogCallback* logCallback) :
+ mEnv(webrtc::CreateEnvironment(webrtc::CreateDefaultTaskQueueFactory())),
mLogSink(new LLWebRTCLogSink(logCallback)),
mPeerCustomProcessor(nullptr),
mMute(true),
+ mVoiceEnabled(false),
mTuningMode(false),
mDevicesDeploying(0),
- mGain(0.0f)
+ mGain(0.0f),
+ mBuiltinNS(false),
+ mBuiltinAGC(false),
+ mBuiltinAEC(false)
{
}
@@ -287,8 +322,6 @@ void LLWebRTCImpl::init()
webrtc::LogMessage::SetLogToStderr(true);
webrtc::LogMessage::AddLogToStream(mLogSink, webrtc::LS_VERBOSE);
- mTaskQueueFactory = webrtc::CreateDefaultTaskQueueFactory();
-
// Create the native threads.
mNetworkThread = webrtc::Thread::CreateWithSocketServer();
mNetworkThread->SetName("WebRTCNetworkThread", nullptr);
@@ -304,11 +337,19 @@ void LLWebRTCImpl::init()
[this]()
{
webrtc::scoped_refptr<webrtc::AudioDeviceModule> realADM =
- webrtc::AudioDeviceModule::Create(webrtc::AudioDeviceModule::AudioLayer::kPlatformDefaultAudio, mTaskQueueFactory.get());
+ webrtc::CreateAudioDeviceModule(mEnv, webrtc::AudioDeviceModule::AudioLayer::kPlatformDefaultAudio);
mDeviceModule = webrtc::make_ref_counted<LLWebRTCAudioDeviceModule>(realADM);
#if !CM_WEBRTC
mDeviceModule->SetObserver(this);
#endif
+ mDeviceModule->Init();
+
+ mBuiltinNS = mDeviceModule->BuiltInNSIsAvailable();
+ mBuiltinAEC = mDeviceModule->BuiltInAECIsAvailable();
+ mBuiltinAGC = mDeviceModule->BuiltInAGCIsAvailable();
+ // All audio processing is done by WebRTC's software APM (configured
+ // below); make sure the hardware processors stay off.
+ workerDisableBuiltInAudioProcessing();
});
// The custom processor allows us to retrieve audio data (and levels)
@@ -318,17 +359,22 @@ void LLWebRTCImpl::init()
apb.SetCapturePostProcessing(std::make_unique<LLCustomProcessor>(mPeerCustomProcessor));
mAudioProcessingModule = apb.Build(webrtc::CreateEnvironment());
+ // Initial software-APM state, matching setAudioConfig() so there's no
+ // window where processing differs before the viewer's first config call.
+ // All processing is done here in software (the hardware AEC/AGC/NS is kept
+ // disabled), so enable echo cancellation from the very first frame.
webrtc::AudioProcessing::Config apm_config;
- apm_config.echo_canceller.enabled = false;
- apm_config.echo_canceller.mobile_mode = false;
- apm_config.gain_controller1.enabled = false;
- apm_config.gain_controller2.enabled = true;
- apm_config.high_pass_filter.enabled = true;
- apm_config.noise_suppression.enabled = true;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
- apm_config.transient_suppression.enabled = true;
- apm_config.pipeline.multi_channel_render = true;
- apm_config.pipeline.multi_channel_capture = false;
+ apm_config.echo_canceller.enabled = true;
+ apm_config.echo_canceller.mobile_mode = false;
+ apm_config.gain_controller1.enabled = false;
+ apm_config.gain_controller2.enabled = true;
+ apm_config.gain_controller2.adaptive_digital.enabled = true; // auto-level speech
+ apm_config.high_pass_filter.enabled = true;
+ apm_config.noise_suppression.enabled = true;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
+ apm_config.transient_suppression.enabled = true;
+ apm_config.pipeline.multi_channel_render = true;
+ apm_config.pipeline.multi_channel_capture = true;
mAudioProcessingModule->ApplyConfig(apm_config);
@@ -360,7 +406,6 @@ void LLWebRTCImpl::init()
{
if (mDeviceModule)
{
- mDeviceModule->EnableBuiltInAEC(false);
updateDevices();
}
});
@@ -369,8 +414,23 @@ void LLWebRTCImpl::init()
void LLWebRTCImpl::terminate()
{
- mWorkerThread->BlockingCall(
- [this]()
+ // Run all blocking WebRTC shutdown calls on a separate thread so that a
+ // hung BlockingCall cannot block the viewer shutdown indefinitely.
+ // Webrtc is not mission critical, we need to save personal data.
+ auto done_promise = std::make_shared<std::promise<void> >();
+ std::future<void> done_future = done_promise->get_future();
+
+ // Hand ownership of the connections to the shutdown thread. Nothing on
+ // this thread may touch them afterwards -- in the timeout case below the
+ // shutdown thread is detached and may still be working through them.
+ std::vector<webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl>> connections;
+ connections.swap(mPeerConnections);
+
+ std::thread shutdown_thread(
+ [this, connections = std::move(connections), done_promise]() mutable
+ {
+ mWorkerThread->BlockingCall(
+ [this]()
{
if (mDeviceModule)
{
@@ -379,79 +439,155 @@ void LLWebRTCImpl::terminate()
}
});
- for (auto &connection : mPeerConnections)
- {
- connection->terminate();
- }
+ // Close the connections inline on the signaling thread. This can't be
+ // connection->terminate(), which only *posts* the close: that queues the
+ // real work behind everything below, so the connections would be closed
+ // after the factory and the device module are gone -- or not at all, if
+ // the thread is destroyed with the task still queued.
+ //
+ // It matters that the close completes here because closing a peer
+ // connection flushes any in-flight GetStats request and runs its
+ // callback inline, and that callback calls back into the viewer's
+ // signaling observers. Those observers are only valid until
+ // llwebrtc::terminate() returns.
+ mSignalingThread->BlockingCall(
+ [&connections]()
+ {
+ for (auto& connection : connections)
+ {
+ connection->closeOnSignalingThread();
+ }
+ // Destroy the connections here, on the signaling thread, while
+ // it's still running.
+ connections.clear();
+ });
- // connection->terminate() above spawns a number of Signaling thread calls to
- // shut down the connection. The following Blocking Call will wait
- // until they're done before it's executed, allowing time to clean up.
+ // Drain anything the closes posted before dropping the factory.
+ mSignalingThread->BlockingCall([]() {});
- mSignalingThread->BlockingCall([this]() { mPeerConnectionFactory = nullptr; });
+ mSignalingThread->BlockingCall([this]() {
+ mPeerConnectionFactory = nullptr;
+ });
- mWorkerThread->BlockingCall(
- [this]()
+ mWorkerThread->BlockingCall(
+ [this]()
{
if (mDeviceModule)
{
- mDeviceModule->Terminate();
+ mDeviceModule->ForceTerminate();
}
- mDeviceModule = nullptr;
- mTaskQueueFactory = nullptr;
+ mDeviceModule = nullptr;
});
- // In case peer connections still somehow have jobs in workers,
- // only clear connections up after clearing workers.
+ done_promise->set_value();
+ });
+
+ constexpr auto WEBRTC_TERMINATE_TIMEOUT = std::chrono::seconds(10);
+ if (done_future.wait_for(WEBRTC_TERMINATE_TIMEOUT) == std::future_status::timeout)
+ {
+ RTC_LOG(LS_WARNING) << __FUNCTION__
+ << ": timed out waiting for WebRTC thread shutdown."
+ " Detaching — some WebRTC resources will be leaked.";
+ shutdown_thread.detach();
+
+ // Release the unique_ptrs WITHOUT joining/deleting: the detached thread
+ // may still be using these thread objects.
+ // The raw pointers are intentionally leaked — the process is exiting anyway
+ // and our priority is saving cache and personal data.
+ (void)mNetworkThread.release();
+ (void)mWorkerThread.release();
+ (void)mSignalingThread.release();
+
+ // mPeerConnections is already empty -- the detached thread owns the
+ // connections now and must be left to finish with them.
+ webrtc::LogMessage::RemoveLogToStream(mLogSink);
+ return;
+ }
+
+ shutdown_thread.join();
+
+ // The connections were closed and destroyed on the signaling thread before
+ // the shutdown thread finished, so it's safe to drop the threads now.
mNetworkThread = nullptr;
mWorkerThread = nullptr;
mSignalingThread = nullptr;
- mPeerConnections.clear();
webrtc::LogMessage::RemoveLogToStream(mLogSink);
}
+
void LLWebRTCImpl::setAudioConfig(LLWebRTCDeviceInterface::AudioConfig config)
{
+ // All audio processing is handled by WebRTC's software APM here. The
+ // platform/hardware AEC/AGC/NS is always disabled (see
+ // workerDisableBuiltInAudioProcessing), so these are enabled purely on the
+ // requested config without deferring to any built-in processor.
webrtc::AudioProcessing::Config apm_config;
- apm_config.echo_canceller.enabled = config.mEchoCancellation;
- apm_config.echo_canceller.mobile_mode = false;
- apm_config.gain_controller1.enabled = false;
- apm_config.gain_controller2.enabled = config.mAGC;
+ apm_config.echo_canceller.enabled = config.mEchoCancellation;
+ apm_config.echo_canceller.mobile_mode = false;
+ apm_config.gain_controller1.enabled = false;
+ apm_config.gain_controller2.enabled = config.mAGC;
apm_config.gain_controller2.adaptive_digital.enabled = true; // auto-level speech
- apm_config.high_pass_filter.enabled = true;
- apm_config.transient_suppression.enabled = true;
- apm_config.pipeline.multi_channel_render = true;
- apm_config.pipeline.multi_channel_capture = true;
- apm_config.pipeline.multi_channel_capture = true;
+ apm_config.high_pass_filter.enabled = true;
+ apm_config.transient_suppression.enabled = true;
+ apm_config.pipeline.multi_channel_render = true;
+ apm_config.pipeline.multi_channel_capture = true;
switch (config.mNoiseSuppressionLevel)
{
case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_NONE:
apm_config.noise_suppression.enabled = false;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
break;
case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_LOW:
apm_config.noise_suppression.enabled = true;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
break;
case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_MODERATE:
apm_config.noise_suppression.enabled = true;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
break;
case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_HIGH:
apm_config.noise_suppression.enabled = true;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kHigh;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kHigh;
break;
case LLWebRTCDeviceInterface::AudioConfig::NOISE_SUPPRESSION_LEVEL_VERY_HIGH:
apm_config.noise_suppression.enabled = true;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
break;
default:
apm_config.noise_suppression.enabled = false;
- apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
+ apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kLow;
}
mAudioProcessingModule->ApplyConfig(apm_config);
+
+ // Keep the hardware processors off; the APM above is the only processing.
+ PostWorkerTask([this]() { workerDisableBuiltInAudioProcessing(); });
+}
+
+void LLWebRTCImpl::workerDisableBuiltInAudioProcessing()
+{
+ if (!mDeviceModule)
+ {
+ return;
+ }
+
+ // We always use WebRTC's internal (software APM) audio processing. Running
+ // the platform/hardware AEC, AGC, or NS alongside it causes the two to
+ // fight -- pumping levels, double noise suppression, and mismatched AEC
+ // references -- so disable any that the device exposes.
+ if (mBuiltinNS)
+ {
+ mDeviceModule->EnableBuiltInNS(false);
+ }
+ if (mBuiltinAGC)
+ {
+ mDeviceModule->EnableBuiltInAGC(false);
+ }
+ if (mBuiltinAEC)
+ {
+ mDeviceModule->EnableBuiltInAEC(false);
+ }
}
void LLWebRTCImpl::refreshDevices()
@@ -471,20 +607,25 @@ void LLWebRTCImpl::unsetDevicesObserver(LLWebRTCDevicesObserver *observer)
}
}
-// must be run in the worker thread.
-void LLWebRTCImpl::workerDeployDevices()
+// must be run in the worker thread. Selects the configured capture device and
+// starts recording. Capture runs the whole time voice is enabled (it's never
+// stopped for mute or between calls, so the AEC never cold-starts -- there's no
+// hiss on unmute), so this is a no-op when already recording. Device changes
+// go through workerDeployDevices(), which stops recording first to force a
+// clean re-select; voice off goes through setVoiceEnabled(false).
+void LLWebRTCImpl::workerStartRecording()
{
- if (!mDeviceModule)
+ // Only run capture while voice is enabled, and never cold-start it when
+ // it's already running (that would cause the unmute hiss).
+ if (!mDeviceModule || !mVoiceEnabled || mDeviceModule->Recording())
{
return;
}
int16_t recordingDevice = RECORD_DEVICE_DEFAULT;
- int16_t recording_device_start = 0;
-
if (mRecordingDevice != "Default")
{
- for (int16_t i = recording_device_start; i < mRecordingDeviceList.size(); i++)
+ for (int16_t i = 0; i < mRecordingDeviceList.size(); i++)
{
if (mRecordingDeviceList[i].mID == mRecordingDevice)
{
@@ -500,8 +641,6 @@ void LLWebRTCImpl::workerDeployDevices()
}
}
- mDeviceModule->StopPlayout();
- mDeviceModule->ForceStopRecording();
#if WEBRTC_WIN
if (recordingDevice < 0)
{
@@ -516,13 +655,32 @@ void LLWebRTCImpl::workerDeployDevices()
#endif
mDeviceModule->InitMicrophone();
mDeviceModule->SetStereoRecording(false);
+ // A newly-selected capture device may default its hardware AEC/AGC/NS on;
+ // disable before InitRecording so the recording stream is configured to
+ // use only WebRTC's software APM.
+ workerDisableBuiltInAudioProcessing();
mDeviceModule->InitRecording();
+ mDeviceModule->ForceStartRecording();
+}
+
+// must be run in the worker thread. Selects the configured playout device and
+// starts playout. Playout only runs while there's a connection to render
+// (running the output device with no engine data is heard as a buzz), so this
+// is a no-op when there are no connections or when already playing. Device
+// changes go through workerDeployDevices(), which stops playout first.
+void LLWebRTCImpl::workerStartPlayout()
+{
+ // Only run playout while voice is enabled and there's a connection to
+ // render (running the output device otherwise is heard as a buzz).
+ if (!mDeviceModule || !mVoiceEnabled || mTuningMode || mDeviceModule->Playing() || mPeerConnections.empty())
+ {
+ return;
+ }
int16_t playoutDevice = PLAYOUT_DEVICE_DEFAULT;
- int16_t playout_device_start = 0;
if (mPlayoutDevice != "Default")
{
- for (int16_t i = playout_device_start; i < mPlayoutDeviceList.size(); i++)
+ for (int16_t i = 0; i < mPlayoutDeviceList.size(); i++)
{
if (mPlayoutDeviceList[i].mID == mPlayoutDevice)
{
@@ -553,16 +711,29 @@ void LLWebRTCImpl::workerDeployDevices()
mDeviceModule->InitSpeaker();
mDeviceModule->SetStereoPlayout(true);
mDeviceModule->InitPlayout();
+ mDeviceModule->StartPlayout();
+}
- if ((!mMute && mPeerConnections.size()) || mTuningMode)
+// must be run in the worker thread. Used for device changes and tuning: forces
+// a clean re-select of both devices, then re-applies per-connection mute/track
+// state. To merely bring playout up when a connection is established (without
+// disturbing the connection's own mute/track management) call
+// workerOpenPlayout() directly -- see startPlayout().
+void LLWebRTCImpl::workerDeployDevices()
+{
+ if (!mDeviceModule)
{
- mDeviceModule->ForceStartRecording();
+ return;
}
- if (!mTuningMode)
- {
- mDeviceModule->StartPlayout();
- }
+ // Stop first so the start helpers (which no-op when already running) will
+ // re-select the now-current device.
+ mDeviceModule->StopPlayout();
+ mDeviceModule->ForceStopRecording();
+
+ workerStartRecording();
+ workerStartPlayout();
+
mSignalingThread->PostTask(
[this]
{
@@ -604,6 +775,35 @@ void LLWebRTCImpl::setRenderDevice(const std::string &id)
}
}
+void LLWebRTCImpl::setVoiceEnabled(bool enable)
+{
+ mVoiceEnabled = enable;
+ mWorkerThread->PostTask(
+ [this, enable]()
+ {
+ if (!mDeviceModule)
+ {
+ return;
+ }
+ if (enable)
+ {
+ // Voice on: start the capture device (it then stays running
+ // across calls and mute/unmute), and start playout if there's
+ // already a connection to render.
+ mDeviceModule->Init();
+ workerDeployDevices();
+ }
+ else
+ {
+ // Voice off: release both devices so the OS mic/speaker aren't
+ // held open.
+ mDeviceModule->ForceStopRecording();
+ mDeviceModule->StopPlayout();
+ mDeviceModule->ForceTerminate();
+ }
+ });
+}
+
// updateDevices needs to happen on the worker thread.
void LLWebRTCImpl::updateDevices()
{
@@ -627,6 +827,7 @@ void LLWebRTCImpl::updateDevices()
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mDeviceModule->PlayoutDeviceName(index, name, guid);
+ RTC_LOG(LS_VERBOSE) << "updateDevices: playout device [" << index << "] name='" << name << "' guid='" << guid << "'";
mPlayoutDeviceList.emplace_back(name, guid);
}
@@ -645,13 +846,18 @@ void LLWebRTCImpl::updateDevices()
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mDeviceModule->RecordingDeviceName(index, name, guid);
+ RTC_LOG(LS_VERBOSE) << "updateDevices: recording device [" << index << "] name='" << name << "' guid='" << guid << "'";
mRecordingDeviceList.emplace_back(name, guid);
}
+ RTC_LOG(LS_INFO) << "updateDevices, playout count: " << renderDeviceCount << "; capture count: " << captureDeviceCount;
+
for (auto &observer : mVoiceDevicesObserverList)
{
observer->OnDevicesChanged(mPlayoutDeviceList, mRecordingDeviceList);
}
+
+ deployDevices();
}
void LLWebRTCImpl::OnDevicesUpdated()
@@ -674,6 +880,13 @@ void LLWebRTCImpl::setTuningMode(bool enable)
[this]
{
mDeviceModule->SetTuning(mTuningMode, mMute);
+ if (!mTuningMode)
+ {
+ // Restore playout after tuning, gated on there being a
+ // connection to render (so the output device isn't left
+ // spinning with no engine data).
+ workerStartPlayout();
+ }
mSignalingThread->PostTask(
[this]
{
@@ -745,34 +958,16 @@ void LLWebRTCImpl::setMute(bool mute, int delay_ms)
void LLWebRTCImpl::intSetMute(bool mute, int delay_ms)
{
+ // Mute by zeroing the captured (post-APM) gain; the sender track is also
+ // disabled per connection (see LLWebRTCPeerConnectionImpl::setMute). The
+ // capture device deliberately stays running for the whole session, so
+ // muting/unmuting never stops or starts it -- that's what avoids the AEC
+ // cold-start hiss on unmute. Capture start/stop is tied to device
+ // selection (workerStartRecording) and shutdown, not to mute.
if (mPeerCustomProcessor)
{
mPeerCustomProcessor->setGain(mMute ? 0.0f : mGain);
}
- if (mMute)
- {
- mWorkerThread->PostDelayedTask(
- [this]
- {
- if (mDeviceModule)
- {
- mDeviceModule->ForceStopRecording();
- }
- },
- webrtc::TimeDelta::Millis(delay_ms));
- }
- else
- {
- mWorkerThread->PostTask(
- [this]
- {
- if (mDeviceModule)
- {
- mDeviceModule->InitRecording();
- mDeviceModule->ForceStartRecording();
- }
- });
- }
}
//
@@ -781,8 +976,7 @@ void LLWebRTCImpl::intSetMute(bool mute, int delay_ms)
LLWebRTCPeerConnectionInterface *LLWebRTCImpl::newPeerConnection()
{
- bool empty = mPeerConnections.empty();
- webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> peerConnection = webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl>(new webrtc::RefCountedObject<LLWebRTCPeerConnectionImpl>());
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> peerConnection = webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl>(new webrtc::RefCountedObject<LLWebRTCPeerConnectionImpl>(mEnv));
peerConnection->init(this);
if (mPeerConnections.empty())
{
@@ -790,6 +984,13 @@ LLWebRTCPeerConnectionInterface *LLWebRTCImpl::newPeerConnection()
}
mPeerConnections.emplace_back(peerConnection);
+ // Playout is intentionally NOT started here. This runs when the connection
+ // is created/connecting; starting the output device now leaves it spinning
+ // with no decoded audio during the handshake, which is heard as a buzz.
+ // Playout is started from OnConnectionChange(kConnected) instead, once audio
+ // is actually established (see startPlayout()). Capture follows
+ // voice-enabled state, so it's not touched here either.
+
peerConnection->enableSenderTracks(false);
peerConnection->resetMute();
return peerConnection.get();
@@ -806,10 +1007,45 @@ void LLWebRTCImpl::freePeerConnection(LLWebRTCPeerConnectionInterface* peer_conn
if (mPeerConnections.empty())
{
intSetMute(true);
+ // Last connection gone: stop playout (there's nothing to render).
+ // Capture stays running while voice is enabled so it's ready -- with
+ // no cold-start hiss -- when the next call comes up. But if voice
+ // has been disabled, stop capture now: setVoiceEnabled(false) tried
+ // to, but the engine's send stream was still active then (and the
+ // engine's own StopRecording is intentionally a no-op), so the stop
+ // only sticks once the connection -- and its stream -- is gone.
+ mWorkerThread->PostTask(
+ [this]()
+ {
+ if (mDeviceModule)
+ {
+ mDeviceModule->StopPlayout();
+ if (!mVoiceEnabled)
+ {
+ mDeviceModule->ForceStopRecording();
+ }
+ }
+ });
}
}
}
+void LLWebRTCImpl::startPlayout()
+{
+ // Called when a connection's audio is established. Only playout is started
+ // here: it's gated on there being a connection to render, because running
+ // the output device with no engine data is heard as a buzz. Capture is
+ // NOT touched here -- it follows voice-enabled state (setVoiceEnabled), so
+ // it's already running if voice is on and must stay off if voice is off.
+ // Starting it here would also let a stray kConnected during voice-disable
+ // teardown re-open the mic.
+ mWorkerThread->PostTask(
+ [this]()
+ {
+ workerStartPlayout();
+ });
+}
+
//
// LLWebRTCPeerConnectionImpl implementation.
@@ -817,11 +1053,16 @@ void LLWebRTCImpl::freePeerConnection(LLWebRTCPeerConnectionInterface* peer_conn
// Most peer connection (signaling) happens on
// the signaling thread.
-LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() :
+LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl(const webrtc::Environment& env) :
+ mEnv(env),
mWebRTCImpl(nullptr),
mPeerConnection(nullptr),
mMute(MUTE_INITIAL),
mAnswerReceived(false),
+ mPeerConnectionState(webrtc::PeerConnectionInterface::PeerConnectionState::kNew),
+ mDisconnectCount(0),
+ mStatsRequestPending(false),
+ mShuttingDown(false),
mPendingJobs(0)
{
}
@@ -850,50 +1091,68 @@ void LLWebRTCPeerConnectionImpl::init(LLWebRTCImpl * webrtc_impl)
void LLWebRTCPeerConnectionImpl::terminate()
{
mPendingJobs++;
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> self(this);
mWebRTCImpl->PostSignalingTask(
- [this]()
+ [self]()
{
- if (mPeerConnection)
- {
- if (mDataChannel)
- {
- {
- mDataChannel->Close();
- mDataChannel = nullptr;
- }
- }
+ self->closeOnSignalingThread();
+ self->mPendingJobs--;
+ });
+}
- // to remove 'Secondlife is recording' icon from taskbar
- // if user was speaking
- auto senders = mPeerConnection->GetSenders();
- for (auto& sender : senders)
- {
- auto track = sender->track();
- if (track)
- {
- track->set_enabled(false);
- }
- }
+// Signaling thread only.
+void LLWebRTCPeerConnectionImpl::closeOnSignalingThread()
+{
+ // Stop issuing stats requests; one may already be in flight, and
+ // Close() below will flush it.
+ mShuttingDown = true;
- mPeerConnection->Close();
- if (mLocalStream)
- {
- auto tracks = mLocalStream->GetAudioTracks();
- for (auto& track : tracks)
- {
- mLocalStream->RemoveTrack(track);
- }
- mLocalStream = nullptr;
- }
- mPeerConnection = nullptr;
+ if (mPeerConnection)
+ {
+ if (mDataChannel)
+ {
+ mDataChannel->Close();
+ mDataChannel = nullptr;
+ }
- for (auto &observer : mSignalingObserverList)
- {
- observer->OnPeerConnectionClosed();
- }
+ // to remove 'Secondlife is recording' icon from taskbar
+ // if user was speaking
+ auto senders = mPeerConnection->GetSenders();
+ for (auto& sender : senders)
+ {
+ auto track = sender->track();
+ if (track)
+ {
+ track->set_enabled(false);
}
- mPendingJobs--;
- });
+ }
+
+ // NOTE: Close() delivers any pending GetStats report inline, before it
+ // returns, so the observer list below must still be valid here.
+ mPeerConnection->Close();
+ if (mLocalStream)
+ {
+ auto tracks = mLocalStream->GetAudioTracks();
+ for (auto& track : tracks)
+ {
+ mLocalStream->RemoveTrack(track);
+ }
+ mLocalStream = nullptr;
+ }
+ mPeerConnection = nullptr;
+
+ for (auto &observer : mSignalingObserverList)
+ {
+ observer->OnPeerConnectionClosed();
+ }
+ }
+
+ // Nothing may call back into the viewer past this point. On shutdown the
+ // viewer's connection objects are torn down as soon as llwebrtc::terminate()
+ // returns and they deliberately don't unset themselves as observers, so any
+ // late callback would be reaching into freed memory.
+ mSignalingObserverList.clear();
+ mDataObserverList.clear();
}
void LLWebRTCPeerConnectionImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); }
@@ -915,8 +1174,9 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
mAnswerReceived = false;
mPendingJobs++;
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> self(this);
mWebRTCImpl->PostSignalingTask(
- [this,options]()
+ [self,options]()
{
webrtc::PeerConnectionInterface::RTCConfiguration config;
for (auto server : options.mServers)
@@ -935,42 +1195,42 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
config.set_min_port(60000);
config.set_max_port(60100);
- webrtc::PeerConnectionDependencies pc_dependencies(this);
+ webrtc::PeerConnectionDependencies pc_dependencies(self.get());
// Other thread manages mPeerConnectionFactory's lifetime and it can be reset
// at any momment, create own scoped_refptr (atomic).
- webrtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory = mPeerConnectionFactory;
+ webrtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory = self->mPeerConnectionFactory;
if (peer_connection_factory == nullptr)
{
RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection, factory doesn't exist";
// Too early?
- mPendingJobs--;
+ self->mPendingJobs--;
return;
}
auto error_or_peer_connection = peer_connection_factory->CreatePeerConnectionOrError(config, std::move(pc_dependencies));
if (error_or_peer_connection.ok())
{
- mPeerConnection = std::move(error_or_peer_connection.value());
+ self->mPeerConnection = std::move(error_or_peer_connection.value());
}
else
{
RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection: " << error_or_peer_connection.error().message();
- for (auto &observer : mSignalingObserverList)
+ for (auto &observer : self->mSignalingObserverList)
{
observer->OnRenegotiationNeeded();
}
- mPendingJobs--;
+ self->mPendingJobs--;
return;
}
webrtc::DataChannelInit init;
init.ordered = true;
- auto data_channel_or_error = mPeerConnection->CreateDataChannelOrError("SLData", &init);
+ auto data_channel_or_error = self->mPeerConnection->CreateDataChannelOrError("SLData", &init);
if (data_channel_or_error.ok())
{
- mDataChannel = std::move(data_channel_or_error.value());
+ self->mDataChannel = std::move(data_channel_or_error.value());
- mDataChannel->RegisterObserver(this);
+ self->mDataChannel->RegisterObserver(self.get());
}
webrtc::AudioOptions audioOptions;
@@ -979,16 +1239,16 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
audioOptions.noise_suppression = true;
audioOptions.init_recording_on_send = false;
- mLocalStream = peer_connection_factory->CreateLocalMediaStream("SLStream");
+ self->mLocalStream = peer_connection_factory->CreateLocalMediaStream("SLStream");
webrtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
peer_connection_factory->CreateAudioTrack("SLAudio", peer_connection_factory->CreateAudioSource(audioOptions).get()));
audio_track->set_enabled(false);
- mLocalStream->AddTrack(audio_track);
+ self->mLocalStream->AddTrack(audio_track);
- mPeerConnection->AddTrack(audio_track, {"SLStream"});
+ self->mPeerConnection->AddTrack(audio_track, {"SLStream"});
- auto senders = mPeerConnection->GetSenders();
+ auto senders = self->mPeerConnection->GetSenders();
for (auto &sender : senders)
{
@@ -1004,7 +1264,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
sender->SetParameters(params);
}
- auto receivers = mPeerConnection->GetReceivers();
+ auto receivers = self->mPeerConnection->GetReceivers();
for (auto &receiver : receivers)
{
webrtc::RtpParameters params;
@@ -1020,9 +1280,9 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
}
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions;
- this->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called.
- mPeerConnection->CreateOffer(this, offerOptions);
- mPendingJobs--;
+ self->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called.
+ self->mPeerConnection->CreateOffer(self.get(), offerOptions);
+ self->mPendingJobs--;
});
return true;
@@ -1099,14 +1359,15 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
mPendingJobs++;
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> self(this);
mWebRTCImpl->PostSignalingTask(
- [this, force_reset, enable]()
+ [self, force_reset, enable]()
{
- if (mPeerConnection)
+ if (self->mPeerConnection)
{
- auto senders = mPeerConnection->GetSenders();
+ auto senders = self->mPeerConnection->GetSenders();
- RTC_LOG(LS_INFO) << __FUNCTION__ << (mMute ? "disabling" : "enabling") << " streams count " << senders.size();
+ RTC_LOG(LS_INFO) << __FUNCTION__ << (self->mMute ? "disabling" : "enabling") << " streams count " << senders.size();
for (auto &sender : senders)
{
auto track = sender->track();
@@ -1122,7 +1383,7 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
track->set_enabled(enable);
}
}
- mPendingJobs--;
+ self->mPendingJobs--;
}
});
}
@@ -1248,33 +1509,65 @@ void LLWebRTCPeerConnectionImpl::OnIceGatheringChange(webrtc::PeerConnectionInte
}
}
+static const webrtc::TimeDelta DISCONNECT_RENEGOTIATE_DELAY = webrtc::TimeDelta::Millis(10000);
+
// Called any time the PeerConnectionState changes.
void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state)
{
RTC_LOG(LS_ERROR) << __FUNCTION__ << " Peer Connection State Change " << new_state;
+ mPeerConnectionState = new_state;
+
switch (new_state)
{
case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
{
+ // Audio is established now -- start playout for this connection.
+ // (Capture follows voice-enabled state, so it's already running and
+ // isn't touched here.) Doing playout here rather than at connection
+ // creation avoids running the output device with no decoded audio
+ // during the handshake (heard as a buzz).
+ mWebRTCImpl->startPlayout();
mPendingJobs++;
- mWebRTCImpl->PostWorkerTask([this]() {
- for (auto &observer : mSignalingObserverList)
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> self(this);
+ mWebRTCImpl->PostWorkerTask([self]()
+ {
+ for (auto &observer : self->mSignalingObserverList)
{
- observer->OnAudioEstablished(this);
+ observer->OnAudioEstablished(self.get());
}
- mPendingJobs--;
+ self->mPendingJobs--;
});
break;
}
+
case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
- case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
{
for (auto &observer : mSignalingObserverList)
{
observer->OnRenegotiationNeeded();
}
-
+ break;
+ }
+ case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
+ {
+ // Wait 10 seconds before renegotiating in case the connection recovers on its own.
+ // Use a sequence count so that only the most recent disconnect transition can trigger
+ // a renegotiation, avoiding stale delayed tasks from earlier disconnect/reconnect cycles.
+ uint32_t disconnect_count = ++mDisconnectCount;
+ mWebRTCImpl->PostDelayedSignalingTask(
+ [this, disconnect_count]()
+ {
+ if (disconnect_count == mDisconnectCount
+ && mPeerConnectionState == webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected)
+ {
+ for (auto &observer : mSignalingObserverList)
+ {
+ observer->OnRenegotiationNeeded();
+ }
+ }
+ },
+ DISCONNECT_RENEGOTIATE_DELAY);
break;
}
default:
@@ -1547,6 +1840,82 @@ void LLWebRTCPeerConnectionImpl::unsetDataObserver(LLWebRTCDataObserver* observe
}
}
+class LLStatsCollectorCallback : public webrtc::RTCStatsCollectorCallback
+{
+public:
+ typedef std::function<void(const LLWebRTCStatsMap&)> StatsCallback;
+
+ LLStatsCollectorCallback(StatsCallback callback) : callback_(callback) {}
+
+ void OnStatsDelivered(const webrtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override
+ {
+ if (callback_)
+ {
+ // Transform RTCStatsReport stats to simple map
+ LLWebRTCStatsMap stats_map;
+ for (const auto& stats : *report)
+ {
+ std::map<std::string, std::string> stat_attributes;
+
+ // Convert each attribute to string format
+ for (const auto& attribute : stats.Attributes())
+ {
+ stat_attributes[attribute.name()] = attribute.ToString();
+ }
+ stats_map[stats.id()] = stat_attributes;
+ }
+ callback_(stats_map);
+ }
+ }
+
+private:
+ StatsCallback callback_;
+};
+
+void LLWebRTCPeerConnectionImpl::gatherConnectionStats()
+{
+ if (!mPeerConnection)
+ {
+ return;
+ }
+
+ webrtc::scoped_refptr<LLWebRTCPeerConnectionImpl> self(this);
+ mWebRTCImpl->PostSignalingTask(
+ [self]()
+ {
+ if (!self->mPeerConnection
+ || self->mShuttingDown
+ || self->mPeerConnectionState != webrtc::PeerConnectionInterface::PeerConnectionState::kConnected
+ || self->mStatsRequestPending) // signaling thread only
+ {
+ return;
+ }
+
+ self->mStatsRequestPending = true;
+
+ auto stats_callback = webrtc::make_ref_counted<LLStatsCollectorCallback>(
+ [self](const LLWebRTCStatsMap& generic_stats)
+ {
+ self->mStatsRequestPending = false;
+
+ // This can be delivered inline from PeerConnection::Close(), which
+ // flushes pending stats requests as it tears down. Don't call out
+ // to the observers in that case -- we're on our way out.
+ if (!self->mPeerConnection || self->mShuttingDown)
+ {
+ return;
+ }
+
+ for (auto& observer : self->mSignalingObserverList)
+ {
+ observer->OnStatsDelivered(generic_stats);
+ }
+ });
+
+ self->mPeerConnection->GetStats(stats_callback.get());
+ });
+}
+
LLWebRTCImpl * gWebRTCImpl = nullptr;
LLWebRTCDeviceInterface * getDeviceInterface()
{
diff --git a/indra/llwebrtc/llwebrtc.h b/indra/llwebrtc/llwebrtc.h
index 7d06b7d2b4..821400cfe8 100644
--- a/indra/llwebrtc/llwebrtc.h
+++ b/indra/llwebrtc/llwebrtc.h
@@ -38,6 +38,7 @@
#ifndef LLWEBRTC_H
#define LLWEBRTC_H
+#include <map>
#include <string>
#include <vector>
@@ -55,6 +56,7 @@
namespace llwebrtc
{
+typedef std::map<std::string, std::map<std::string, std::string>> LLWebRTCStatsMap;
class LLWebRTCLogCallback
{
@@ -151,6 +153,14 @@ class LLWebRTCDeviceInterface
virtual void setCaptureDevice(const std::string& id) = 0;
virtual void setRenderDevice(const std::string& id) = 0;
+ // Enable/disable the audio devices, set when voice is enabled/disabled.
+ // The capture (microphone) and playout (speaker) devices only run while this
+ // is enabled, so neither is held open when the user has voice off. While
+ // enabled, capture stays running across calls and mute/unmute so the AEC
+ // never cold-starts (no unmute hiss); playout still only runs when there's a
+ // connection to render.
+ virtual void setVoiceEnabled(bool enable) = 0;
+
// Device observers for device change callbacks.
virtual void setDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
virtual void unsetDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
@@ -240,6 +250,8 @@ class LLWebRTCSignalingObserver
// Called when the data channel has been established and data
// transfer can begin.
virtual void OnDataChannelReady(LLWebRTCDataInterface *data_interface) = 0;
+
+ virtual void OnStatsDelivered(const LLWebRTCStatsMap& stats_data) {}
};
// LLWebRTCPeerConnectionInterface representsd a connection to a peer,
@@ -273,6 +285,8 @@ class LLWebRTCPeerConnectionInterface
virtual void unsetSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
virtual void AnswerAvailable(const std::string &sdp) = 0;
+
+ virtual void gatherConnectionStats() = 0;
};
// The following define the dynamic linked library
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index 9d3af985ef..71b63b8b76 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -180,7 +180,7 @@ private:
class LLWebRTCAudioDeviceModule : public webrtc::AudioDeviceModule
{
public:
- explicit LLWebRTCAudioDeviceModule(webrtc::scoped_refptr<webrtc::AudioDeviceModule> inner) : inner_(std::move(inner)), tuning_(false)
+ explicit LLWebRTCAudioDeviceModule(webrtc::scoped_refptr<webrtc::AudioDeviceModule> inner) : inner_(inner), tuning_(false)
{
RTC_CHECK(inner_);
}
@@ -197,9 +197,15 @@ public:
}
int32_t Init() override { return inner_->Init(); }
- int32_t Terminate() override { return inner_->Terminate(); }
+ int32_t Terminate() override {
+ // libwebrtc attempts to terminate the adm when peer connections go to zero, but we don't want that,
+ // now that we're keeping the adm active throughout the session.
+ return 0;
+ }
bool Initialized() const override { return inner_->Initialized(); }
+ int32_t ForceTerminate() { return inner_->Terminate(); }
+
// --- Device enumeration/selection (forward) ---
int16_t PlayoutDevices() override { return inner_->PlayoutDevices(); }
int16_t RecordingDevices() override { return inner_->RecordingDevices(); }
@@ -325,29 +331,8 @@ public:
// tuning microphone energy calculations
float GetMicrophoneEnergy() { return audio_transport_.GetMicrophoneEnergy(); }
void SetTuningMicGain(float gain) { audio_transport_.SetGain(gain); }
- void SetTuning(bool tuning, bool mute)
- {
- tuning_ = tuning;
- if (tuning)
- {
- inner_->InitRecording();
- inner_->StartRecording();
- inner_->StopPlayout();
- }
- else
- {
- if (mute)
- {
- inner_->StopRecording();
- }
- else
- {
- inner_->InitRecording();
- inner_->StartRecording();
- }
- inner_->StartPlayout();
- }
- }
+
+ void SetTuning(bool tuning, bool mute);
protected:
~LLWebRTCAudioDeviceModule() override = default;
@@ -441,7 +426,6 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
//
void setAudioConfig(LLWebRTCDeviceInterface::AudioConfig config = LLWebRTCDeviceInterface::AudioConfig()) override;
-
void refreshDevices() override;
void setDevicesObserver(LLWebRTCDevicesObserver *observer) override;
@@ -450,6 +434,8 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
void setCaptureDevice(const std::string& id) override;
void setRenderDevice(const std::string& id) override;
+ void setVoiceEnabled(bool enable) override;
+
void setTuningMode(bool enable) override;
float getTuningAudioLevel() override;
float getPeerConnectionAudioLevel() override;
@@ -489,6 +475,13 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
mSignalingThread->PostTask(std::move(task), location);
}
+ void PostDelayedSignalingTask(absl::AnyInvocable<void() &&> task,
+ webrtc::TimeDelta delay,
+ const webrtc::Location& location = webrtc::Location::Current())
+ {
+ mSignalingThread->PostDelayedTask(std::move(task), delay, location);
+ }
+
void PostNetworkTask(absl::AnyInvocable<void() &&> task,
const webrtc::Location& location = webrtc::Location::Current())
{
@@ -524,9 +517,23 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
LLWebRTCPeerConnectionInterface* newPeerConnection();
void freePeerConnection(LLWebRTCPeerConnectionInterface* peer_connection);
+ // Start playout once a connection's audio is established (playout is gated
+ // on there being a connection to render). Capture is not touched here --
+ // it follows voice-enabled state, not connection state. Safe to call from
+ // any thread (work is posted to the worker thread).
+ void startPlayout();
+
protected:
+ const webrtc::Environment mEnv;
+ void workerStartRecording();
+ void workerStartPlayout();
void workerDeployDevices();
+ // We always rely on WebRTC's internal (software APM) audio processing, so
+ // any platform/hardware AEC/AGC/NS must be kept disabled.
+ void workerDisableBuiltInAudioProcessing();
+
+
LLWebRTCLogSink* mLogSink;
// The native webrtc threads
@@ -539,10 +546,6 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
webrtc::scoped_refptr<webrtc::AudioProcessing> mAudioProcessingModule;
- // more native webrtc stuff
- std::unique_ptr<webrtc::TaskQueueFactory> mTaskQueueFactory;
-
-
// Devices
void updateDevices();
void deployDevices();
@@ -550,6 +553,10 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
webrtc::scoped_refptr<LLWebRTCAudioDeviceModule> mDeviceModule;
std::vector<LLWebRTCDevicesObserver *> mVoiceDevicesObserverList;
+ bool mBuiltinNS;
+ bool mBuiltinAGC;
+ bool mBuiltinAEC;
+
// accessors in native webrtc for devices aren't apparently implemented yet.
bool mTuningMode;
std::string mRecordingDevice;
@@ -559,6 +566,8 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO
LLWebRTCVoiceDeviceList mPlayoutDeviceList;
bool mMute;
+ // Whether voice is enabled; gates whether the capture/playout devices run.
+ bool mVoiceEnabled;
float mGain;
LLCustomProcessorStatePtr mPeerCustomProcessor;
@@ -582,11 +591,16 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
{
public:
- LLWebRTCPeerConnectionImpl();
+ LLWebRTCPeerConnectionImpl(const webrtc::Environment& env);
~LLWebRTCPeerConnectionImpl();
void init(LLWebRTCImpl * webrtc_impl);
+ // Posts closeOnSignalingThread() and returns immediately.
void terminate();
+ // The actual close. Signaling thread only. Callable directly (via a
+ // BlockingCall) when the caller needs the connection to be fully closed
+ // before it continues -- see LLWebRTCImpl::terminate().
+ void closeOnSignalingThread();
virtual void AddRef() const override = 0;
virtual webrtc::RefCountReleaseStatus Release() const override = 0;
@@ -658,8 +672,10 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
void enableSenderTracks(bool enable);
void enableReceiverTracks(bool enable);
- protected:
+ void gatherConnectionStats() override;
+ protected:
+ const webrtc::Environment mEnv;
LLWebRTCImpl * mWebRTCImpl;
webrtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
@@ -683,6 +699,18 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
std::vector<LLWebRTCDataObserver *> mDataObserverList;
webrtc::scoped_refptr<webrtc::DataChannelInterface> mDataChannel;
+ // connection state tracking for delayed renegotiation on disconnect
+ webrtc::PeerConnectionInterface::PeerConnectionState mPeerConnectionState;
+ uint32_t mDisconnectCount;
+
+ // Accessed only on the WebRTC signaling thread.
+ bool mStatsRequestPending;
+
+ // Set by closeOnSignalingThread() so that no new stats request (or other
+ // callback into the viewer) is issued while we're tearing down.
+ // Accessed only on the WebRTC signaling thread.
+ bool mShuttingDown;
+
std::atomic<int> mPendingJobs;
};
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp
index 89ff7c6d3f..101e035135 100644
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -32,9 +32,32 @@
#include "llwindowmacosx-objc.h"
+#include <CoreServices/CoreServices.h> // Required for TIS functions
+#include <Carbon/Carbon.h>
+
LLKeyboardMacOSX::LLKeyboardMacOSX()
{
// Virtual keycode mapping table. Yes, this was as annoying to generate as it looks.
+
+ bool isAzerty = false;
+
+ TISInputSourceRef source = TISCopyCurrentKeyboardLayoutInputSource();
+ if (source)
+ {
+ CFStringRef inputSourceID = (CFStringRef)TISGetInputSourceProperty(source, kTISPropertyInputSourceID);
+ if (inputSourceID)
+ {
+ char buf[128];
+ // Convert CFString to a C-string for easy comparison
+ if (CFStringGetCString(inputSourceID, buf, sizeof(buf), kCFStringEncodingUTF8))
+ {
+ // On macOS, AZERTY layouts are identified by "French" in their Input Source ID
+ isAzerty = (strstr(buf, "French") != nullptr);
+ }
+ }
+ CFRelease(source);
+ }
+
mTranslateKeyMap[0x00] = 'A';
mTranslateKeyMap[0x01] = 'S';
mTranslateKeyMap[0x02] = 'D';
@@ -52,6 +75,7 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
mTranslateKeyMap[0x0f] = 'R';
mTranslateKeyMap[0x10] = 'Y';
mTranslateKeyMap[0x11] = 'T';
+
mTranslateKeyMap[0x12] = '1';
mTranslateKeyMap[0x13] = '2';
mTranslateKeyMap[0x14] = '3';
@@ -132,6 +156,16 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
mTranslateKeyMap[0x7d] = KEY_DOWN;
mTranslateKeyMap[0x7e] = KEY_UP;
+ // azerty fix
+ if(isAzerty)
+ {
+ LL_WARNS() << "keyboard is AZERTY" << LL_ENDL;
+ mTranslateKeyMap[0x00] = 'Q';
+ mTranslateKeyMap[0x06] = 'W';
+ mTranslateKeyMap[0x0c] = 'A';
+ mTranslateKeyMap[0x0d] = 'Z';
+ }
+
// Build inverse map
std::map<U16, KEY>::iterator iter;
for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index bdb5d8def0..3030169d58 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -226,12 +226,12 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (id) init
{
- return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
+ return [self initWithFrame:[self bounds] withSamples:0 andVsync:FALSE];
}
- (id) initWithSamples:(NSUInteger)samples
{
- return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE];
+ return [self initWithFrame:[self bounds] withSamples:samples andVsync:FALSE];
}
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync
@@ -247,8 +247,9 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
{
- [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeURL]];
- [self initWithFrame:frame];
+ NSRect fixedFrame = NSMakeRect(0, 0, NSWidth(frame), NSHeight(frame));
+ [self initWithFrame:fixedFrame];
+ [self setWantsBestResolutionOpenGLSurface:gHiDPISupport];
// Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6.
// Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat.
@@ -260,7 +261,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAAccelerated,
NSOpenGLPFADepthSize, 24,
- NSOpenGLPFAColorSize, 32,
+ NSOpenGLPFAColorSize, 24,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
0
};
@@ -271,8 +272,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorFloat,
- NSOpenGLPFAColorSize, 64,
NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAColorSize, 48,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
0
};
@@ -327,9 +328,6 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSLog(@"Extended color space applied for HDR Display", nil);
}
- //for retina support
- [self setWantsBestResolutionOpenGLSurface:gHiDPISupport];
-
[self setOpenGLContext:glContext];
[glContext setView:self];
@@ -351,6 +349,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
GLint opacity = 1;
[glContext setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
+ [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeURL]];
+
return self;
}
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 7331f50ba0..4b804c82cc 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -190,7 +190,7 @@ bool LLWindowCallbacks::handleTimerEvent(LLWindow *window)
return false;
}
-bool LLWindowCallbacks::handleDeviceChange(LLWindow *window)
+bool LLWindowCallbacks::handleDeviceChange(LLWindow *window, const std::string& change_type)
{
return false;
}
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 59dcdd3ade..6d1990e92b 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -68,7 +68,7 @@ public:
virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
virtual bool handleTimerEvent(LLWindow *window);
- virtual bool handleDeviceChange(LLWindow *window);
+ virtual bool handleDeviceChange(LLWindow *window, const std::string& change_type);
virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
virtual bool handleDisplayChanged();
virtual bool handleWindowDidChangeScreen(LLWindow *window);
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index b302a705da..ec9afb1844 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -78,6 +78,8 @@ void initMainLoop();
void cleanupViewer();
void handleUrl(const char* url);
void dispatchUrl(std::string url);
+void startWatchdog(std::string_view state);
+void stopWatchdog();
/* Defined in llwindowmacosx-objc.mm: */
int createNSApp(int argc, const char **argv);
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index d902a82a3c..85208a5ac3 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -223,8 +223,8 @@ OSErr setImageCursor(CursorRef ref)
NSWindowRef createNSWindow(int x, int y, int width, int height)
{
LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
- styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable
- backing:NSBackingStoreBuffered defer:NO];
+ styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskFullSizeContentView
+ backing:NSBackingStoreBuffered defer:YES];
[window makeKeyAndOrderFront:nil];
[window setAcceptsMouseMovedEvents:TRUE];
[window setRestorable:FALSE]; // Viewer manages state from own settings
@@ -347,7 +347,7 @@ void convertWindowToScreen(NSWindowRef window, float *coord)
NSRect rect = NSMakeRect(coord[0], coord[1], 0, 0);
rect = [(LLNSWindow*)window convertRectToScreen:rect];
- coord[0] = rect.origin.x;
+ coord[0] = rect.origin.x;
coord[1] = [[NSScreen screens][0] frame].size.height - rect.origin.y;
}
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 42250535f0..5a85887143 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -51,7 +51,7 @@
#include <IOKit/usb/IOUSBLib.h>
extern bool gDebugWindowProc;
-bool gHiDPISupport = true;
+bool gHiDPISupport = false;
bool gHDRDisplaySupport = false;
const S32 BITS_PER_PIXEL = 32;
@@ -761,7 +761,7 @@ bool LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
kCGLPFAMultisample,
kCGLPFASampleBuffers, static_cast<CGLPixelFormatAttribute>((mFSAASamples > 0 ? 1 : 0)),
kCGLPFASamples, static_cast<CGLPixelFormatAttribute>(mFSAASamples),
- kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8),
+ //kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8),
kCGLPFADepthSize, static_cast<CGLPixelFormatAttribute>(24),
kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8),
kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24),
@@ -939,9 +939,10 @@ bool LLWindowMacOSX::getVisible()
if(mFullscreen)
{
result = true;
- }if (mWindow)
+ }
+ if (mWindow)
{
- result = true;
+ result = true;
}
return(result);
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index dbdbfe390f..5793254ded 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -65,6 +65,7 @@
#include <utility> // std::pair
#include <d3d9.h>
+#include <d3d11.h>
#include <dxgi1_4.h>
#include <timeapi.h>
@@ -115,7 +116,15 @@ static std::thread::id sMainThreadId;
LPWSTR gIconResource = IDI_APPLICATION;
LPWSTR gIconSmallResource = IDI_APPLICATION;
-LPDIRECTINPUT8 gDirectInput8;
+
+namespace
+{
+ LPDIRECTINPUT8 gDirectInput8;
+ ID3D11Device* gD3D11Device = nullptr;
+ ID3D11DeviceContext* gD3D11Context = nullptr;
+ LUID gExpectedAdapterLUID;
+ HMODULE gD3D11Library;
+}
LLW32MsgCallback gAsyncMsgCallback = NULL;
@@ -443,6 +452,16 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
}
});
}
+
+ // For mainWindowProc, it should not unpause watchdog if it was paused
+ void pingWindowTimeout(std::string_view state)
+ {
+ if (mWindowTimeout && mWindowTimeout->started())
+ {
+ mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC);
+ mWindowTimeout->ping(state);
+ }
+ }
private:
// These timeout related functions are strictly for the thread.
void resumeTimeout(std::string_view state)
@@ -508,6 +527,10 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
LoadLibrary(L"opengl32.dll");
+ // Request high-performance GPU before creating OpenGL context
+ // This increases probability of discrete GPU being used when
+ // the context is created.
+ requestHighPerformanceGPU();
if (mMaxCores != 0)
{
@@ -523,6 +546,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
SetProcessAffinityMask(hProcess, mask);
}
+ setThreadPriorityHigh();
+
#if 0 // this is probably a bad idea, but keep it in your back pocket if you see what looks like
// process deprioritization during profiles
// force high thread priority
@@ -545,41 +570,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
}
#endif
-#if 0 // this is also probably a bad idea, but keep it in your back pocket for getting main thread off of background thread cores (see also LLThread::threadRun)
- HANDLE hThread = GetCurrentThread();
-
- SYSTEM_INFO sysInfo;
-
- GetSystemInfo(&sysInfo);
- U32 core_count = sysInfo.dwNumberOfProcessors;
-
- if (max_cores != 0)
- {
- core_count = llmin(core_count, max_cores);
- }
-
- if (hThread)
- {
- int priority = GetThreadPriority(hThread);
-
- if (priority < THREAD_PRIORITY_TIME_CRITICAL)
- {
- if (SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL))
- {
- LL_INFOS() << "Set thread priority to THREAD_PRIORITY_TIME_CRITICAL" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Failed to set thread priority: " << std::hex << GetLastError() << LL_ENDL;
- }
-
- // tell main thread to prefer core 0
- SetThreadIdealProcessor(hThread, 0);
- }
- }
-#endif
-
-
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
mIconSmallResource = gIconSmallResource;
@@ -1009,6 +999,7 @@ void LLWindowWin32::close()
}
mDragDrop->reset();
+ clearHighPerformanceGPURequest();
// Go back to screen mode written in the registry.
@@ -1073,6 +1064,52 @@ bool LLWindowWin32::isValid()
return (mWindowHandle != NULL);
}
+void LLWindowWin32::setThreadPriorityHigh()
+{
+ // Threads start at normal priority. But this is our main window/rendering thread,
+ // even if window handle belongs to another thread. So we can raise its priority
+ // to ensure better responsiveness and less blocking by lack of resources.
+ HANDLE hThread = GetCurrentThread();
+ if (hThread)
+ {
+ int priority = GetThreadPriority(hThread);
+
+ if (priority == THREAD_PRIORITY_ERROR_RETURN)
+ {
+ LL_WARNS_ONCE("Window") << "Failed to get thread priority: " << std::hex << GetLastError() << LL_ENDL;
+ }
+ else if (priority > THREAD_PRIORITY_HIGHEST)
+ {
+ // At the moment nothing should be setting 'critical' priority,
+ // but if that happens for some reason, we don't want to mess with it.
+ LL_WARNS("Window") << "setThreadPriorityHigh ignored, priority was " << (S32)priority << LL_ENDL;
+ }
+ else if (priority != THREAD_PRIORITY_HIGHEST)
+ {
+ if (SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST))
+ {
+ LL_DEBUGS("Window") << "Set thread priority to THREAD_PRIORITY_HIGHEST" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Window") << "Failed to set thread priority: " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+ }
+}
+
+void LLWindowWin32::setThreadPriorityNormal()
+{
+ HANDLE hThread = GetCurrentThread();
+ if (hThread)
+ {
+ if (!SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL))
+ {
+ LL_WARNS_ONCE("Window") << "Failed to set thread priority: " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+}
+
bool LLWindowWin32::getVisible()
{
return (mWindowHandle && IsWindowVisible(mWindowHandle));
@@ -2388,18 +2425,45 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DEVICECHANGE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DEVICECHANGE");
+ window_imp->mWindowThread->pingWindowTimeout("WM_DEVICECHANGE");
+
+ // Log detailed device change information
+ std::string change_type = "UNKNOWN";
+ switch (w_param)
+ {
+ case DBT_DEVICEARRIVAL: change_type = "DBT_DEVICEARRIVAL"; break;
+ case DBT_DEVICEREMOVECOMPLETE: change_type = "DBT_DEVICEREMOVECOMPLETE"; break;
+ case DBT_DEVNODES_CHANGED: change_type = "DBT_DEVNODES_CHANGED"; break;
+ case DBT_DEVICEQUERYREMOVE: change_type = "DBT_DEVICEQUERYREMOVE"; break;
+ case DBT_DEVICEQUERYREMOVEFAILED: change_type = "DBT_DEVICEQUERYREMOVEFAILED"; break;
+ case DBT_DEVICEREMOVEPENDING: change_type = "DBT_DEVICEREMOVEPENDING"; break;
+ case DBT_CONFIGCHANGED: change_type = "DBT_CONFIGCHANGED"; break;
+ }
+
if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp));
+ WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp, change_type));
return 1;
}
+ else if (l_param)
+ {
+ const auto* hdr = reinterpret_cast<const DEV_BROADCAST_HDR*>(l_param);
+ if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ {
+ // Might need to register for monitor device notifications
+ // to get this message when monitor is suspended or resumed.
+ // TODO: log monitor suspending and resuming.
+ LL_INFOS("Window") << "DEVICEINTERFACE: " << change_type << LL_ENDL;
+ }
+ }
break;
}
case WM_PAINT:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_PAINT");
+ window_imp->mWindowThread->pingWindowTimeout("WM_PAINT");
GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE);
update_width = update_rect.right - update_rect.left + 1;
update_height = update_rect.bottom - update_rect.top + 1;
@@ -2442,6 +2506,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
}
+ case WM_POWERBROADCAST:
+ {
+ // Might need to register for power broadcast interface
+ // Todo: log monitor suspending and resuming.
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_POWERBROADCAST");
+ LL_INFOS("Window") << "Received WM_POWERBROADCAST with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
+ break;
+ }
+
case WM_ACTIVATEAPP:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ACTIVATEAPP");
@@ -2515,6 +2588,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CLOSE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
+ window_imp->mWindowThread->pingWindowTimeout("WM_CLOSE");
// todo: WM_CLOSE can be caused by user and by task manager,
// distinguish these cases.
// For now assume it is always user.
@@ -2552,6 +2626,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// Comes after WM_QUERYENDSESSION
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ENDSESSION");
LL_INFOS("Window") << "Received WM_ENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
+ window_imp->mWindowThread->pingWindowTimeout("WM_ENDSESSION");
unsigned int end_session_flags = (U32)l_param;
if (w_param == TRUE // if true, session is ending
@@ -3043,19 +3118,31 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// means that the window was un-minimized.
if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, true));
+ window_imp->post([=]()
+ {
+ window_imp->setThreadPriorityHigh();
+ window_imp->mCallbacks->handleActivate(window_imp, true);
+ });
}
// handle case of window being maximized from fully minimized state
if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, true));
+ window_imp->post([=]()
+ {
+ window_imp->setThreadPriorityHigh();
+ window_imp->mCallbacks->handleActivate(window_imp, true);
+ });
}
// Also handle the minimization case
if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, false));
+ window_imp->post([=]()
+ {
+ window_imp->setThreadPriorityNormal();
+ window_imp->mCallbacks->handleActivate(window_imp, false);
+ });
}
// Actually resize all of our views
@@ -3075,6 +3162,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DPICHANGED:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DPICHANGED");
+ window_imp->mWindowThread->pingWindowTimeout("WM_DPICHANGED");
LPRECT lprc_new_scale;
F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI);
lprc_new_scale = (LPRECT)l_param;
@@ -3095,7 +3183,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DISPLAYCHANGE:
{
+ window_imp->mWindowThread->pingWindowTimeout("WM_DISPLAYCHANGE");
WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged());
+ break;
}
case WM_SETFOCUS:
@@ -3133,6 +3223,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_SETTINGCHANGE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETTINGCHANGE");
+ // Can be called on OS user switching
+ LL_INFOS("Window") << "WM_SETTINGCHANGE, with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
+ window_imp->mWindowThread->pingWindowTimeout("WM_SETTINGCHANGE");
if (w_param == SPI_SETMOUSEVANISH)
{
if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0))
@@ -4620,6 +4713,248 @@ void LLWindowWin32::setDPIAwareness()
}
}
+void LLWindowWin32::requestHighPerformanceGPU() const
+{
+ // Try to load d3d11.dll and request high performance adapter
+ gD3D11Library = LoadLibraryA("d3d11.dll");
+ if (gD3D11Library)
+ {
+ typedef HRESULT(WINAPI* PFN_D3D11_CREATE_DEVICE)(
+ IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT,
+ const D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**,
+ D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
+
+ PFN_D3D11_CREATE_DEVICE pD3D11CreateDevice =
+ (PFN_D3D11_CREATE_DEVICE)GetProcAddress(gD3D11Library, "D3D11CreateDevice");
+
+ if (pD3D11CreateDevice)
+ {
+ // Try to enumerate adapters and select the best one
+ IDXGIFactory1* pFactory = nullptr;
+ IDXGIAdapter1* pSelectedAdapter = nullptr;
+ std::string selected_descr;
+ HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);
+
+ if (SUCCEEDED(hr) && pFactory)
+ {
+ IDXGIAdapter1* pAdapter = nullptr;
+ SIZE_T maxDedicatedMemory = 0;
+ UINT adapterIndex = 0;
+ S32 adapter_count = 0;
+
+ // Enumerate all adapters and find the one with the most dedicated video memory
+ while (pFactory->EnumAdapters1(adapterIndex, &pAdapter) != DXGI_ERROR_NOT_FOUND)
+ {
+ DXGI_ADAPTER_DESC1 desc;
+ pAdapter->GetDesc1(&desc);
+
+ std::wstring description_w(desc.Description);
+ std::string description = ll_convert_wide_to_string(description_w);
+
+
+ // Skip software adapters
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ {
+ LL_DEBUGS("Window") << "Adapter " << adapterIndex << ": " << description
+ << ", Dedicated VRAM: " << (desc.DedicatedVideoMemory / 1024 / 1024) << " MB"
+ << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec
+ << ", Flags: " << desc.Flags << LL_ENDL;
+ }
+ // Skip Microsoft Basic Render Driver, it's a placeholder for missing drivers
+ else if (description.find("Microsoft Basic Render Driver") != std::string::npos)
+ {
+ // User is likely missing drivers, so log a warning.
+ // Don't consider this adapter as a valid selection.
+ LL_WARNS("Window") << "Adapter " << adapterIndex << ": " << description
+ << ", Dedicated VRAM: " << (desc.DedicatedVideoMemory / 1024 / 1024) << " MB"
+ << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec
+ << ", Flags: " << desc.Flags << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("Window") << "Adapter " << adapterIndex << ": " << description
+ << ", Dedicated VRAM: " << (desc.DedicatedVideoMemory / 1024 / 1024) << " MB"
+ << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec
+ << ", Flags: " << desc.Flags << LL_ENDL;
+
+ adapter_count++;
+ // Select adapter with most dedicated video memory (typically the discrete GPU)
+ if (desc.DedicatedVideoMemory > maxDedicatedMemory)
+ {
+ if (pSelectedAdapter)
+ {
+ pSelectedAdapter->Release();
+ }
+ pSelectedAdapter = pAdapter;
+ pSelectedAdapter->AddRef();
+ maxDedicatedMemory = desc.DedicatedVideoMemory;
+ gExpectedAdapterLUID = desc.AdapterLuid;
+ selected_descr = description;
+ }
+ }
+
+ pAdapter->Release();
+ adapterIndex++;
+ }
+ pFactory->Release();
+
+ if (adapter_count < 2)
+ {
+ // Only one adapter, no need to request high-performance GPU
+ if (pSelectedAdapter)
+ {
+ pSelectedAdapter->Release();
+ }
+ gExpectedAdapterLUID = { 0, 0 };
+ FreeLibrary(gD3D11Library);
+ gD3D11Library = nullptr;
+ return;
+ }
+
+ LL_INFOS("Window") << "Selected as preferred adapter (highest VRAM): " << selected_descr << LL_ENDL;
+ }
+
+ // Create a temporary device to ensure high-performance GPU is selected
+ // This initialization can help "wake up" the discrete GPU
+ D3D_FEATURE_LEVEL featureLevel;
+ D3D_FEATURE_LEVEL requestedLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1 };
+
+ bool adapterSelected = (pSelectedAdapter != nullptr);
+ if (adapterSelected)
+ {
+ hr = pD3D11CreateDevice(
+ pSelectedAdapter,
+ D3D_DRIVER_TYPE_UNKNOWN,
+ nullptr,
+ 0,
+ requestedLevels,
+ _countof(requestedLevels),
+ D3D11_SDK_VERSION,
+ &gD3D11Device,
+ &featureLevel,
+ &gD3D11Context
+ );
+ pSelectedAdapter->Release();
+
+ if (!SUCCEEDED(hr))
+ {
+ LL_WARNS("Window") << "D3D11 failed to use preffered adapter " << selected_descr << LL_ENDL;
+ gExpectedAdapterLUID = { 0, 0 };
+ adapterSelected = false;
+ }
+ }
+
+ if (!adapterSelected)
+ {
+ // Either failed to select or didn't find an adapter.
+ hr = pD3D11CreateDevice(
+ nullptr,
+ D3D_DRIVER_TYPE_HARDWARE,
+ nullptr,
+ 0,
+ requestedLevels,
+ _countof(requestedLevels),
+ D3D11_SDK_VERSION,
+ &gD3D11Device,
+ &featureLevel,
+ &gD3D11Context
+ );
+ if (!SUCCEEDED(hr))
+ {
+ LL_WARNS("Window") << "D3D11 failed to use hardware adapter" << LL_ENDL;
+ FreeLibrary(gD3D11Library);
+ gD3D11Library = nullptr;
+ // These shouldn't be set, but make sure they are null.
+ gD3D11Device = nullptr;
+ gD3D11Context = nullptr;
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("Window") << "Failed to get D3D11CreateDevice function from d3d11.dll. High-performance GPU request failed." << LL_ENDL;
+ FreeLibrary(gD3D11Library);
+ gD3D11Library = nullptr;
+ }
+ }
+}
+
+bool LLWindowWin32::detectGPUChange() const
+{
+ if (!gD3D11Device)
+ {
+ // Can't detect without D3D11 device
+ return false;
+ }
+
+ if (gExpectedAdapterLUID.LowPart == 0 && gExpectedAdapterLUID.HighPart == 0)
+ {
+ // No specific adapter was selected, can't detect changes.
+ return false;
+ }
+
+ IDXGIDevice* pDXGIDevice = nullptr;
+ HRESULT hr = gD3D11Device->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
+
+ if (SUCCEEDED(hr) && pDXGIDevice)
+ {
+ IDXGIAdapter* pCurrentAdapter = nullptr;
+ hr = pDXGIDevice->GetAdapter(&pCurrentAdapter);
+
+ if (SUCCEEDED(hr) && pCurrentAdapter)
+ {
+ DXGI_ADAPTER_DESC desc;
+ pCurrentAdapter->GetDesc(&desc);
+
+ std::wstring description_w(desc.Description);
+
+ bool changed = false;
+
+ // Check if LUID has changed
+ if (desc.AdapterLuid.LowPart != gExpectedAdapterLUID.LowPart ||
+ desc.AdapterLuid.HighPart != gExpectedAdapterLUID.HighPart)
+ {
+ changed = true;
+ std::string current_gpu_name = ll_convert_wide_to_string(description_w);
+ LL_WARNS("Window") << "GPU change detected! Current adapter: " << current_gpu_name << LL_ENDL;
+ }
+
+ pCurrentAdapter->Release();
+ pDXGIDevice->Release();
+
+ return changed;
+ }
+
+ if (pDXGIDevice)
+ {
+ pDXGIDevice->Release();
+ }
+ }
+
+ return false;
+}
+
+void LLWindowWin32::clearHighPerformanceGPURequest() const
+{
+ detectGPUChange();
+ gExpectedAdapterLUID = { 0, 0 };
+ if (gD3D11Context)
+ {
+ gD3D11Context->Release();
+ gD3D11Context = nullptr;
+ }
+ if (gD3D11Device)
+ {
+ gD3D11Device->Release();
+ gD3D11Device = nullptr;
+ }
+ if (gD3D11Library)
+ {
+ FreeLibrary(gD3D11Library);
+ gD3D11Library = nullptr;
+ }
+}
+
void* LLWindowWin32::getDirectInput8()
{
return &gDirectInput8;
@@ -4648,6 +4983,12 @@ bool LLWindowWin32::getInputDevices(U32 device_type_filter,
void LLWindowWin32::initWatchdog()
{
mWindowThread->initTimeout();
+
+ // Watchdog is effectively a 'login complete event', as the
+ // 'unstable' part is done and from now on we are tracking
+ // performance.
+ // No need to hold D3D11 context/device any more.
+ clearHighPerformanceGPURequest();
}
F32 LLWindowWin32::getSystemUISize()
@@ -4729,6 +5070,13 @@ inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{
LL::ThreadPool::start();
+
+ // Set thread name for the window thread
+ // This will make it distinguishable in Visual Studio debugger
+ post([this]()
+ {
+ SetThreadDescription(GetCurrentThread(), L"LLWindowWin32 Thread");
+ });
}
/**
@@ -4910,7 +5258,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
// Normally won't exist yet, but in case of re-init, make sure it's cleaned up
- resumeTimeout("WindowThread");
+ resumeTimeout("Window:WindowThread");
while (! getQueue().done())
{
@@ -4921,23 +5269,25 @@ void LLWindowWin32::LLWindowWin32Thread::run()
if (mWindowHandleThrd != 0)
{
- pingTimeout("messages");
MSG msg;
BOOL status;
if (mhDCThrd == 0)
{
+ pingTimeout("Window:PeekMessage");
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage");
logger.onChange("PeekMessage(", std::hex, mWindowHandleThrd, ")");
status = PeekMessage(&msg, mWindowHandleThrd, 0, 0, PM_REMOVE);
}
else
{
+ pingTimeout("Window:GetMessage");
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage");
logger.always("GetMessage(", std::hex, mWindowHandleThrd, ")");
status = GetMessage(&msg, NULL, 0, 0);
}
if (status > 0)
{
+ pingTimeout("Window:TranslateMessage");
logger.always("got MSG (", std::hex, msg.hwnd, ", ", msg.message,
", ", msg.wParam, ")");
TranslateMessage(&msg);
@@ -4949,7 +5299,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Function Queue");
- pingTimeout("queue");
+ pingTimeout("Window:Queue");
logger.onChange("runPending()");
//process any pending functions
getQueue().runPending();
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 8159092794..aab2635a34 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -148,6 +148,8 @@ protected:
void initCursors();
HCURSOR loadColorCursor(LPCTSTR name);
bool isValid();
+ void setThreadPriorityHigh();
+ void setThreadPriorityNormal();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
virtual LLSD getNativeKeyData();
@@ -170,6 +172,17 @@ protected:
void handleCompositionMessage(U32 indexes);
bool handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
+ // Additional function to request and hold a high-performance GPU on Windows 10+
+ //
+ // Laptops can dynamically switch between integrated and discrete GPUs.
+ // The Viewer has gpu-specific optimizations, and this switching can cause problems and crashes.
+ // The login screen requires low performance, which can lead to the OS deciding to switch to the integrated GPU.
+ // To avoid this, we request and hold a high-performance GPU using A D3D11 context until login.
+ // For diagnostics, we also log GPU changes.
+ void requestHighPerformanceGPU() const;
+ bool detectGPUChange() const;
+ void clearHighPerformanceGPURequest() const;
+
protected:
//
// Platform specific methods
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 562a30e8d1..34643d5f5c 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -157,9 +157,12 @@ LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
{
if ((persist != PERSIST_NO) && mComment.empty())
{
- // File isn't actually missing, but something is wrong with it
- // so the main point is to warn user to reinstall
- LLError::LLUserWarningMsg::showMissingFiles();
+ std::string error_string =
+ "Second Life failed to initialize settings. Setting " + mName + " is invalid. "
+ "Either settings' files were supplied incorrectly or default files were corrupted."
+ "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and "
+ "contact https://support.secondlife.com if issue persists after reinstall.";
+ LLError::LLUserWarningMsg::show(error_string);
LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL;
}
//Push back versus setValue'ing here, since we don't want to call a signal yet
@@ -758,6 +761,7 @@ void LLControlGroup::setUntypedValue(std::string_view name, const LLSD& val)
// Returns number of controls loaded, so 0 if failure
U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, bool require_declaration, eControlType declare_as)
{
+ LL_PROFILE_ZONE_SCOPED;
std::string name;
LLXmlTree xml_controls;
@@ -990,8 +994,9 @@ U32 LLControlGroup::saveToFile(const std::string& filename, bool nondefault_only
return num_saved;
}
-U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values)
+U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values, bool error_when_no_comment)
{
+ LL_PROFILE_ZONE_SCOPED;
LLSD settings;
llifstream infile;
infile.open(filename.c_str());
@@ -1105,10 +1110,26 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
}
}
+ std::string comment = control_map["Comment"].asString();
+ if (!error_when_no_comment
+ && !set_default_values
+ && comment.empty())
+ {
+ // Only error for default settings that should remind the developer to provide comments
+ // and otherwise indicate a problem with viewer's files.
+ // But permit this minor transgression in user's files.
+ // Otherwise user might have a hard time figuring out source of the error or how to fix it.
+ // Instead make setting to not persist so that unrecognized invalid settings won't be saved
+ // for the next run.
+ persist = LLControlVariable::PERSIST_NO;
+ comment = "Comment not provided, setting won't persist";
+ LL_WARNS() << "Control " << name << " is missing a comment value. Setting will be marked as PERSIST_NO" << LL_ENDL;
+ }
+
declareControl(name,
typeStringToEnum(control_map["Type"].asString()),
control_map["Value"],
- control_map["Comment"].asString(),
+ comment,
persist,
hidefromsettingseditor
);
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index da7268bf45..5aa2b9715e 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -33,8 +33,10 @@
#include "llrect.h"
#include "llrefcount.h"
#include "llinstancetracker.h"
+#include "llstl.h"
#include <functional>
+#include <unordered_map>
#include <vector>
#include <boost/signals2.hpp>
@@ -165,7 +167,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
LOG_CLASS(LLControlGroup);
protected:
- typedef std::map<std::string, LLControlVariablePtr, std::less<> > ctrl_name_table_t;
+ using ctrl_name_table_t = std::unordered_map<std::string, LLControlVariablePtr, ll::string_hash, std::equal_to<>>;
ctrl_name_table_t mNameTable;
static const std::string mTypeString[TYPE_COUNT];
@@ -278,7 +280,7 @@ public:
// as the given type.
U32 loadFromFileLegacy(const std::string& filename, bool require_declaration = true, eControlType declare_as = TYPE_STRING);
U32 saveToFile(const std::string& filename, bool nondefault_only);
- U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
+ U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true, bool error_when_no_comment = true);
void resetToDefaults();
void incrCount(std::string_view name);
diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index a815b1cf4f..666826dc89 100644
--- a/indra/media_plugins/cef/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -37,8 +37,7 @@ if (LINUX)
include(FindPipeWire)
include_directories(SYSTEM ${PIPEWIRE_INCLUDE_DIRS} ${SPA_INCLUDE_DIRS})
- #message( "Building with Linux volume catcher for PipeWire and PulseAudio" )
- message( "Building with Linux volume catcher for PulseAudio" )
+ message( "Building with Linux volume catcher for PipeWire and PulseAudio" )
list(APPEND media_plugin_cef_HEADER_FILES
linux/volume_catcher_linux.h
@@ -47,11 +46,17 @@ if (LINUX)
set(LINUX_VOLUME_CATCHER
linux/volume_catcher_linux.cpp
linux/volume_catcher_pulseaudio.cpp
- #linux/volume_catcher_pipewire.cpp
+ linux/volume_catcher_pipewire.cpp
)
list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER})
- set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'")
+ set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id")
+ if (${LINUX_DISTRO} MATCHES arch AND (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64) OR (${LINUX_DISTRO} MATCHES fedora))
+ if (${LINUX_DISTRO} MATCHES fedora)
+ set(LIB_SUFFIX ${ADDRESS_SIZE})
+ endif ()
+ set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH};${INSTALL_PREFIX}/lib${LIB_SUFFIX}/cef)
+ endif ()
list(APPEND media_plugin_cef_LINK_LIBRARIES llwindow )
elseif (DARWIN)
list(APPEND media_plugin_cef_SOURCE_FILES volume_catcher_null.cpp)
@@ -72,8 +77,6 @@ add_library(media_plugin_cef
${media_plugin_cef_SOURCE_FILES}
)
-#target_compile_definitions(media_plugin_cef PRIVATE USE_VOLUME_CATCHER_PW=1)
-
#add_dependencies(media_plugin_cef
# ${MEDIA_PLUGIN_BASE_LIBRARIES}
#)
@@ -130,6 +133,13 @@ if (DARWIN)
endif (DARWIN)
+if (CMAKE_BUILD_TYPE MATCHES Release AND (CMAKE_CXX_COMPILER_ID STREQUAL Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU))
+ add_custom_command(
+ TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_STRIP} lib${PROJECT_NAME}.so
+ )
+endif ()
+
if (INSTALL)
if (DARWIN)
set(_LIB SLPlugin.app/Contents/Frameworks)
@@ -147,46 +157,67 @@ if (INSTALL)
DESTINATION ${_LIB}
)
elseif (LINUX)
- if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
- set(_LIB lib/${ARCH}-linux-gnu)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ set(_LIB lib)
+ elseif (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
+ set(_LIB lib/${ARCH}-linux-gnu/${VIEWER_BINARY_NAME})
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR (${LINUX_DISTRO} MATCHES gentoo))
- set(_LIB lib${ADDRESS_SIZE})
+ set(_LIB lib${ADDRESS_SIZE}/${VIEWER_BINARY_NAME})
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
- if (${LINUX_DISTRO} MATCHES arch)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
install(
PROGRAMS
${AUTOBUILD_INSTALL_DIR}/bin/release/chrome-sandbox
${AUTOBUILD_INSTALL_DIR}/bin/release/dullahan_host
+ DESTINATION libexec
+ )
+ elseif (${LINUX_DISTRO} MATCHES arch)
+ install(
+ PROGRAMS ${AUTOBUILD_INSTALL_DIR}/bin/release/dullahan_host
DESTINATION lib/${VIEWER_BINARY_NAME}
- #PERMISSIONS SETUID OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
- else (${LINUX_DISTRO} MATCHES arch)
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
+ install(
+ PROGRAMS ${AUTOBUILD_INSTALL_DIR}/bin/release/chrome-sandbox
+ DESTINATION lib/${VIEWER_BINARY_NAME}
+ )
+ endif ()
+ elseif (${LINUX_DISTRO} MATCHES fedora)
+ install(
+ PROGRAMS ${AUTOBUILD_INSTALL_DIR}/bin/release/dullahan_host
+ DESTINATION libexec/${VIEWER_BINARY_NAME}
+ )
+ else ()
install(
PROGRAMS
${AUTOBUILD_INSTALL_DIR}/bin/release/chrome-sandbox
${AUTOBUILD_INSTALL_DIR}/bin/release/dullahan_host
DESTINATION libexec/${VIEWER_BINARY_NAME}
- #PERMISSIONS SETUID OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
- endif (${LINUX_DISTRO} MATCHES arch)
- install(
- FILES
- ${ARCH_PREBUILT_DIRS_RELEASE}/libcef.so
- ${ARCH_PREBUILT_DIRS_RELEASE}/libvk_swiftshader.so
- ${AUTOBUILD_INSTALL_DIR}/bin/release/snapshot_blob.bin
- ${AUTOBUILD_INSTALL_DIR}/bin/release/v8_context_snapshot.bin
- ${AUTOBUILD_INSTALL_DIR}/resources/chrome_100_percent.pak
- ${AUTOBUILD_INSTALL_DIR}/resources/chrome_200_percent.pak
- ${AUTOBUILD_INSTALL_DIR}/resources/icudtl.dat
- ${AUTOBUILD_INSTALL_DIR}/resources/resources.pak
- DESTINATION ${_LIB}
+ endif ()
+ if (NOT (${LINUX_DISTRO} MATCHES arch AND (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64) OR (${LINUX_DISTRO} MATCHES fedora)))
+ install(
+ FILES
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libEGL.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libGLESv2.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libcef.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvk_swiftshader.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvulkan.so.1
+ ${ARCH_PREBUILT_DIRS_RELEASE}/v8_context_snapshot.bin
+ ${ARCH_PREBUILT_DIRS_RELEASE}/vk_swiftshader_icd.json
+ ${AUTOBUILD_INSTALL_DIR}/resources/chrome_100_percent.pak
+ ${AUTOBUILD_INSTALL_DIR}/resources/chrome_200_percent.pak
+ ${AUTOBUILD_INSTALL_DIR}/resources/icudtl.dat
+ ${AUTOBUILD_INSTALL_DIR}/resources/resources.pak
+ DESTINATION ${_LIB}
)
- install(
- DIRECTORY ${AUTOBUILD_INSTALL_DIR}/resources/locales
- DESTINATION ${_LIB}
+ install(
+ DIRECTORY ${AUTOBUILD_INSTALL_DIR}/resources/locales
+ DESTINATION ${_LIB}
)
+ endif ()
elseif (WINDOWS)
set(_LIB llplugin)
install(
@@ -216,7 +247,7 @@ if (INSTALL)
DESTINATION llplugin
)
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
if (NOT WINDOWS)
install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB})
diff --git a/indra/media_plugins/cef/linux/volume_catcher_linux.cpp b/indra/media_plugins/cef/linux/volume_catcher_linux.cpp
index ba2ed1aa56..7d33242063 100644
--- a/indra/media_plugins/cef/linux/volume_catcher_linux.cpp
+++ b/indra/media_plugins/cef/linux/volume_catcher_linux.cpp
@@ -37,14 +37,12 @@ void VolumeCatcher::onEnablePipeWireVolumeCatcher(bool enable)
if (pimpl != nullptr)
return;
-#if USE_VOLUME_CATCHER_PW
if (enable)
{
LL_DEBUGS() << "volume catcher using pipewire" << LL_ENDL;
pimpl = new VolumeCatcherPipeWire();
}
else
-#endif
{
LL_DEBUGS() << "volume catcher using pulseaudio" << LL_ENDL;
pimpl = new VolumeCatcherPulseAudio();
diff --git a/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
index 27fea547c9..04bbbcff6c 100755
--- a/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
+++ b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
@@ -207,7 +207,7 @@ void VolumeCatcherPipeWire::ChildNode::updateVolume()
{
std::lock_guard pwLock(*mImpl);
- pw_node_set_param(mProxy, SPA_PARAM_Props, 0, pod);
+ pw_node_set_param((pw_node*)mProxy, SPA_PARAM_Props, 0, pod);
}
}
@@ -303,7 +303,7 @@ void VolumeCatcherPipeWire::handleRegistryEventGlobal(
childNode->mProxy = proxy;
childNode->mImpl = this;
- pw_node_add_listener(proxy, &childNode->mNodeListener, &NODE_EVENTS, childNode);
+ pw_node_add_listener((pw_node*)proxy, &childNode->mNodeListener, &NODE_EVENTS, childNode);
llpw_proxy_add_listener(proxy, &childNode->mProxyListener, &PROXY_EVENTS, childNode);
}
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index a2b664c755..d5ec3dbb20 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -957,7 +957,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
authResponse(message_in);
}
-#if !LL_LINUX
if (message_name == "edit_undo")
{
mCEFLib->editUndo();
@@ -966,7 +965,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
mCEFLib->editRedo();
}
-#endif
if (message_name == "edit_cut")
{
mCEFLib->editCut();
@@ -979,7 +977,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
mCEFLib->editPaste();
}
-#if !LL_LINUX
if (message_name == "edit_delete")
{
mCEFLib->editDelete();
@@ -992,7 +989,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
mCEFLib->viewSource();
}
-#endif
}
else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
{
@@ -1176,28 +1172,19 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD
//
void MediaPluginCEF::checkEditState()
{
-#if !LL_LINUX
bool can_undo = mCEFLib->editCanUndo();
bool can_redo = mCEFLib->editCanRedo();
-#endif
bool can_cut = mCEFLib->editCanCut();
bool can_copy = mCEFLib->editCanCopy();
bool can_paste = mCEFLib->editCanPaste();
-#if !LL_LINUX
bool can_delete = mCEFLib->editCanDelete();
bool can_select_all = mCEFLib->editCanSelectAll();
-#endif
-#if LL_LINUX
- if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste))
-#else
if ((can_undo != mCanUndo) || (can_redo != mCanRedo) || (can_cut != mCanCut) || (can_copy != mCanCopy)
|| (can_paste != mCanPaste) || (can_delete != mCanDelete) || (can_select_all != mCanSelectAll))
-#endif
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state");
-#if !LL_LINUX
if (can_undo != mCanUndo)
{
mCanUndo = can_undo;
@@ -1209,7 +1196,6 @@ void MediaPluginCEF::checkEditState()
mCanRedo = can_redo;
message.setValueBoolean("redo", can_redo);
}
-#endif
if (can_cut != mCanCut)
{
@@ -1229,7 +1215,6 @@ void MediaPluginCEF::checkEditState()
message.setValueBoolean("paste", can_paste);
}
-#if !LL_LINUX
if (can_delete != mCanDelete)
{
mCanDelete = can_delete;
@@ -1241,7 +1226,6 @@ void MediaPluginCEF::checkEditState()
mCanSelectAll = can_select_all;
message.setValueBoolean("select_all", can_select_all);
}
-#endif
sendMessage(message);
}
diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt
index b8b3bd68f3..ae0b35b1b0 100644
--- a/indra/media_plugins/libvlc/CMakeLists.txt
+++ b/indra/media_plugins/libvlc/CMakeLists.txt
@@ -72,6 +72,13 @@ if (DARWIN)
endif (DARWIN)
+if (CMAKE_BUILD_TYPE MATCHES Release AND (CMAKE_CXX_COMPILER_ID STREQUAL Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU))
+ add_custom_command(
+ TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_STRIP} lib${PROJECT_NAME}.so
+ )
+endif ()
+
if (INSTALL)
if (DARWIN)
set(_LIB SLPlugin.app/Contents/Frameworks)
@@ -87,12 +94,28 @@ if (INSTALL)
/Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib/libvlccore.dylib
DESTINATION ${_LIB}/plugins
)
+ elseif (${LINUX_DISTRO} MATCHES freedesktop)
+ set(_LIB lib)
+ install(
+ DIRECTORY ${ARCH_PREBUILT_DIRS_RELEASE}/vlc
+ DESTINATION ${_LIB}
+ )
+ install(
+ FILES
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlc.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlc.so.5
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlc.so.5.6.1
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlccore.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlccore.so.9
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libvlccore.so.9.0.1
+ DESTINATION ${_LIB}
+ )
elseif (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
- set(_LIB lib/${ARCH}-linux-gnu)
+ set(_LIB lib/${ARCH}-linux-gnu/${VIEWER_BINARY_NAME})
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR (${LINUX_DISTRO} MATCHES gentoo))
- set(_LIB lib${ADDRESS_SIZE})
+ set(_LIB lib${ADDRESS_SIZE}/${VIEWER_BINARY_NAME})
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
if (WINDOWS)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${PROJECT_NAME}.dll DESTINATION llplugin)
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
index 3fe2c2b193..edf93f359a 100644
--- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -191,7 +191,11 @@ void MediaPluginLibVLC::initVLC()
//
void MediaPluginLibVLC::resetVLC()
{
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_stop(mLibVLCMediaPlayer);
+#else
+ libvlc_media_player_stop_async(mLibVLCMediaPlayer);
+#endif
libvlc_media_player_release(mLibVLCMediaPlayer);
libvlc_release(mLibVLC);
}
@@ -258,7 +262,11 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
parent->mVlcStatus = STATUS_DONE;
break;
+#if LIBVLC_VERSION_MAJOR < 4
case libvlc_MediaPlayerEndReached:
+#else
+ case libvlc_MediaPlayerStopping:
+#endif
parent->mVlcStatus = STATUS_DONE;
parent->mCurTime = parent->mDuration;
parent->setDurationDirty();
@@ -285,6 +293,7 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
parent->setDurationDirty();
break;
+#if LIBVLC_VERSION_MAJOR < 4
case libvlc_MediaPlayerTitleChanged:
{
char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
@@ -294,6 +303,7 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
}
}
break;
+#endif
case libvlc_MediaMetaChanged:
auto title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
if (title)
@@ -331,10 +341,18 @@ void MediaPluginLibVLC::playMedia()
// memory.
if (mLibVLCMediaPlayer)
{
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_stop(mLibVLCMediaPlayer);
+#else
+ libvlc_media_player_stop_async(mLibVLCMediaPlayer);
+#endif
}
+#if LIBVLC_VERSION_MAJOR < 4
mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
+#else
+ mLibVLCMedia = libvlc_media_new_location(mURL.c_str());
+#endif
if (!mLibVLCMedia)
{
mLibVLCMediaPlayer = 0;
@@ -342,7 +360,11 @@ void MediaPluginLibVLC::playMedia()
return;
}
+#if LIBVLC_VERSION_MAJOR < 4
mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia);
+#else
+ mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLC, mLibVLCMedia);
+#endif
if (!mLibVLCMediaPlayer)
{
setStatus(STATUS_ERROR);
@@ -357,12 +379,18 @@ void MediaPluginLibVLC::playMedia()
libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this);
libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this);
libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this);
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this);
+#else
+ libvlc_event_attach(em, libvlc_MediaPlayerStopping, eventCallbacks, this);
+#endif
libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this);
libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this);
libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this);
libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this);
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
+#endif
}
auto event_manager = libvlc_media_event_manager(mLibVLCMedia);
if (event_manager)
@@ -548,7 +576,11 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
{
if (mPixels == iter->second.mAddress)
{
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_stop(mLibVLCMediaPlayer);
+#else
+ libvlc_media_player_stop_async(mLibVLCMediaPlayer);
+#endif
libvlc_media_player_release(mLibVLCMediaPlayer);
mLibVLCMediaPlayer = 0;
@@ -612,7 +644,11 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
if (mLibVLCMediaPlayer)
{
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_set_time(mLibVLCMediaPlayer, time);
+#else
+ libvlc_media_player_set_time(mLibVLCMediaPlayer, time, true);
+#endif
time = libvlc_media_player_get_time(mLibVLCMediaPlayer);
if (time < 0)
{
@@ -648,7 +684,11 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
{
if (mLibVLCMediaPlayer)
{
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_stop(mLibVLCMediaPlayer);
+#else
+ libvlc_media_player_stop_async(mLibVLCMediaPlayer);
+#endif
}
}
else if (message_name == "start")
@@ -658,9 +698,13 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
if (mVlcStatus == STATUS_DONE && !libvlc_media_player_is_playing(mLibVLCMediaPlayer))
{
// stop or vlc will ignore 'play', it will just
- // make an MediaPlayerEndReached event even if
+ // make an MediaPlayerEndReached/MediaPlayerStopping event even if
// seek was used
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_stop(mLibVLCMediaPlayer);
+#else
+ libvlc_media_player_stop_async(mLibVLCMediaPlayer);
+#endif
}
libvlc_media_player_play(mLibVLCMediaPlayer);
}
@@ -677,7 +721,11 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
if (mLibVLCMediaPlayer)
{
libvlc_time_t time = (libvlc_time_t)(1000.0 * message_in.getValueReal("time"));
+#if LIBVLC_VERSION_MAJOR < 4
libvlc_media_player_set_time(mLibVLCMediaPlayer, time);
+#else
+ libvlc_media_player_set_time(mLibVLCMediaPlayer, time, true);
+#endif
time = libvlc_media_player_get_time(mLibVLCMediaPlayer);
if (time < 0)
{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 90a62bce79..81ac89695b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -50,9 +50,6 @@ include(VisualLeakDetector)
#include(VulkanGltf)
include(ZLIBNG)
include(LLPrimitive)
-if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
- include(UnixInstall)
-endif ()
if (ENABLE_MEDIA_PLUGINS)
include(LibVLCPlugin)
@@ -206,7 +203,6 @@ set(viewer_SOURCE_FILES
llfloateravatartextures.cpp
llfloaterbanduration.cpp
llfloaterbeacons.cpp
- llfloaterbigpreview.cpp
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbulkupload.cpp
@@ -290,7 +286,6 @@ set(viewer_SOURCE_FILES
llfloaterpay.cpp
llfloaterperformance.cpp
llfloaterperms.cpp
- llfloaterpostprocess.cpp
llfloaterprofile.cpp
llfloaterpreference.cpp
llfloaterpreferencesgraphicsadvanced.cpp
@@ -315,7 +310,6 @@ set(viewer_SOURCE_FILES
llfloatersidepanelcontainer.cpp
llfloaterslapptest.cpp
llfloatersnapshot.cpp
- llfloatersounddevices.cpp
llfloaterspellchecksettings.cpp
llfloatertelehub.cpp
llfloatertestinspectors.cpp
@@ -327,7 +321,6 @@ set(viewer_SOURCE_FILES
llfloatertranslationsettings.cpp
llfloateruipreview.cpp
llfloaterurlentry.cpp
- llfloatervoiceeffect.cpp
llfloatervoicevolume.cpp
llfloaterwebcontent.cpp
llfloaterwhitelistentry.cpp
@@ -346,6 +339,7 @@ set(viewer_SOURCE_FILES
llgltfmateriallist.cpp
llgltfmaterialpreviewmgr.cpp
llgroupactions.cpp
+ llgroupcolormap.cpp # group-based nameplate tinting
llgroupiconctrl.cpp
llgrouplist.cpp
llgroupmgr.cpp
@@ -430,6 +424,7 @@ set(viewer_SOURCE_FILES
llfloaterimnearbychat.cpp
llfloaterimnearbychathandler.cpp
llfloaterimnearbychatlistener.cpp
+ llnearbyvoicemoderation.cpp
llnetmap.cpp
llnotificationalerthandler.cpp
llnotificationgrouphandler.cpp
@@ -523,7 +518,6 @@ set(viewer_SOURCE_FILES
llpanelsnapshotprofile.cpp
llpanelteleporthistory.cpp
llpaneltiptoast.cpp
- llpanelvoiceeffect.cpp
llpaneltopinfobar.cpp
llpanelpulldown.cpp
llpanelvoicedevicesettings.cpp
@@ -564,6 +558,7 @@ set(viewer_SOURCE_FILES
llpreviewtexture.cpp
llproductinforequest.cpp
llprogressview.cpp
+ llquickprefs.cpp # Firestorm port: Quick Preferences floater
llrecentpeople.cpp
llreflectionmap.cpp
llreflectionmapmanager.cpp
@@ -601,6 +596,7 @@ set(viewer_SOURCE_FILES
llslurl.cpp
llsnapshotlivepreview.cpp
llspatialpartition.cpp
+ llstatslistener.cpp
llspeakers.cpp
llspeakingindicatormanager.cpp
llsplitbutton.cpp
@@ -737,7 +733,6 @@ set(viewer_SOURCE_FILES
llvoicechannel.cpp
llvoiceclient.cpp
llvoicevisualizer.cpp
- llvoicevivox.cpp
llvoicewebrtc.cpp
llvoinventorylistener.cpp
llvopartgroup.cpp
@@ -770,7 +765,7 @@ set(viewer_SOURCE_FILES
rlvhandler.cpp
)
-if (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64) OR (${LINUX_DISTRO} MATCHES gentoo) OR (${LINUX_DISTRO} MATCHES debian AND CMAKE_SYSTEM_PROCESSOR MATCHES aarch64))
+if (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64))
list(REMOVE_ITEM viewer_SOURCE_FILES llvoicewebrtc.cpp)
endif ()
@@ -901,7 +896,6 @@ set(viewer_HEADER_FILES
llfloateravatartextures.h
llfloaterbanduration.h
llfloaterbeacons.h
- llfloaterbigpreview.h
llfloaterbuildoptions.h
llfloaterbulkpermission.h
llfloaterbulkupload.h
@@ -989,7 +983,6 @@ set(viewer_HEADER_FILES
llfloaterpay.h
llfloaterperformance.h
llfloaterperms.h
- llfloaterpostprocess.h
llfloaterprofile.h
llfloaterpreference.h
llfloaterpreferencesgraphicsadvanced.h
@@ -1014,7 +1007,6 @@ set(viewer_HEADER_FILES
llfloatersidepanelcontainer.h
llfloaterslapptest.h
llfloatersnapshot.h
- llfloatersounddevices.h
llfloaterspellchecksettings.h
llfloatertelehub.h
llfloatertestinspectors.h
@@ -1026,7 +1018,6 @@ set(viewer_HEADER_FILES
llfloatertranslationsettings.h
llfloateruipreview.h
llfloaterurlentry.h
- llfloatervoiceeffect.h
llfloatervoicevolume.h
llfloaterwebcontent.h
llfloaterwhitelistentry.h
@@ -1044,6 +1035,7 @@ set(viewer_HEADER_FILES
llgltfmateriallist.h
llgltfmaterialpreviewmgr.h
llgroupactions.h
+ llgroupcolormap.h # group-based nameplate tinting
llgroupiconctrl.h
llgrouplist.h
llgroupmgr.h
@@ -1123,6 +1115,7 @@ set(viewer_HEADER_FILES
llnameeditor.h
llnamelistctrl.h
llnavigationbar.h
+ llnearbyvoicemoderation.h
llnetmap.h
llnotificationhandler.h
llnotificationlistitem.h
@@ -1208,7 +1201,6 @@ set(viewer_HEADER_FILES
llpaneltiptoast.h
llpanelpulldown.h
llpanelvoicedevicesettings.h
- llpanelvoiceeffect.h
llpaneltopinfobar.h
llpanelvolume.h
llpanelvolumepulldown.h
@@ -1247,6 +1239,7 @@ set(viewer_HEADER_FILES
llpreviewtexture.h
llproductinforequest.h
llprogressview.h
+ llquickprefs.h # Firestorm port: Quick Preferences floater
llrecentpeople.h
llreflectionmap.h
llreflectionmapmanager.h
@@ -1287,6 +1280,7 @@ set(viewer_HEADER_FILES
llsnapshotlivepreview.h
llsnapshotmodel.h
llspatialpartition.h
+ llstatslistener.h
llspeakers.h
llspeakingindicatormanager.h
llsplitbutton.h
@@ -1425,7 +1419,6 @@ set(viewer_HEADER_FILES
llvoicechannel.h
llvoiceclient.h
llvoicevisualizer.h
- llvoicevivox.h
llvoicewebrtc.h
llvoinventorylistener.h
llvopartgroup.h
@@ -1538,7 +1531,6 @@ if (NOT (DARWIN OR WINDOWS))
llappviewerlinux.cpp
PROPERTIES
COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
- COMPILE_FLAGS "-DAPP_PLUGIN_DIR=\\\"${INSTALL_LIBRARY_DIR}\\\""
)
#LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
if (NOT CMAKE_CXX_COMPILER_ID MATCHES AppleClang)
@@ -1882,6 +1874,13 @@ else ()
)
endif ()
+if (CMAKE_BUILD_TYPE MATCHES Release AND (CMAKE_CXX_COMPILER_ID STREQUAL Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU))
+ add_custom_command(
+ TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+ COMMAND ${CMAKE_STRIP} ${VIEWER_BINARY_NAME}
+ )
+endif ()
+
if(USE_PRECOMPILED_HEADERS)
target_precompile_headers( ${VIEWER_BINARY_NAME} PRIVATE llviewerprecompiledheaders.h )
endif(USE_PRECOMPILED_HEADERS)
@@ -1916,9 +1915,7 @@ if (WINDOWS)
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
${SHARED_LIB_STAGING_DIR}/openjp2.dll
${SHARED_LIB_STAGING_DIR}/llwebrtc.dll
- #${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/SLVoice.exe
#${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/libsndfile-1.dll
- #${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/vivoxoal.dll
${AUTOBUILD_INSTALL_DIR}/ca-bundle.crt
${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
@@ -1929,18 +1926,6 @@ if (WINDOWS)
media_plugin_example
)
- if (ADDRESS_SIZE EQUAL 64)
- list(APPEND COPY_INPUT_DEPENDENCIES
- ${SHARED_LIB_STAGING_DIR}/vivoxsdk_x64.dll
- ${SHARED_LIB_STAGING_DIR}/ortp_x64.dll
- )
- else (ADDRESS_SIZE EQUAL 64)
- list(APPEND COPY_INPUT_DEPENDENCIES
- ${SHARED_LIB_STAGING_DIR}/vivoxsdk.dll
- ${SHARED_LIB_STAGING_DIR}/ortp.dll
- )
- endif (ADDRESS_SIZE EQUAL 64)
-
if (TARGET ll::discord_sdk)
list(APPEND COPY_INPUT_DEPENDENCIES
${SHARED_LIB_STAGING_DIR}/discord_partner_sdk.dll
@@ -2204,16 +2189,21 @@ target_link_libraries(${VIEWER_BINARY_NAME}
ll::openxr
)
-if (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64) OR (${LINUX_DISTRO} MATCHES gentoo) OR (${LINUX_DISTRO} MATCHES debian AND CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)))
- target_compile_definitions(${VIEWER_BINARY_NAME} INTERFACE USE_WEBRTC=1)
+if (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD OR ($ENV{MSYSTEM_CARCH} MATCHES aarch64)))
target_link_libraries(${VIEWER_BINARY_NAME} llwebrtc )
endif ()
if (ENABLE_MEDIA_PLUGINS)
target_link_libraries(${VIEWER_BINARY_NAME} ll::libvlc )
- if (DARWIN OR LINUX)
+ if (NOT (CMAKE_SYSTEM_NAME MATCHES FreeBSD))
target_link_libraries(${VIEWER_BINARY_NAME} ll::cef )
endif ()
+ # Tell the viewer source which media-library version headers are
+ # actually available in this build, so version reporting in
+ # llappviewer.cpp is gated on the build configuration rather than on
+ # a CPU/compiler macro. Mirrors the link availability above exactly.
+ target_compile_definitions(${VIEWER_BINARY_NAME} PRIVATE LL_VLC=1)
+ target_compile_definitions(${VIEWER_BINARY_NAME} PRIVATE LL_CEF=1)
endif ()
if (USE_DISCORD)
@@ -2365,6 +2355,11 @@ if (LINUX)
if (PACKAGE)
if (${LINUX_DISTRO} MATCHES arch)
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES x86_64)
+ set(ARCH_DEPS cef)
+ else ()
+ set(ARCH_DEPS "at-spi2-core minizip")
+ endif ()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/PKGBUILD.in
${CMAKE_BINARY_DIR}/PKGBUILD
@@ -2383,15 +2378,10 @@ if (LINUX)
set(CPACK_DEBIAN_PACKAGE_SECTION net
CACHE STRING "Debian package section.")
if (${LINUX_DISTRO} MATCHES debian)
- if (CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "libalut0, libaprutil1t64, libboost-fiber1.83.0, libboost-filesystem1.83.0, libboost-program-options1.83.0, libboost-regex1.83.0, libboost-thread1.83.0, libboost-url1.83.0, libexpat1, libfltk1.4, libgles-dev, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libminizip1t64, libnghttp2-14, libnspr4, libnss3, libopenjp2-7, libsdl2-2.0-0, libvlc5, libvorbisenc2, libvorbisfile3, vlc-plugin-base"
- CACHE STRING "Debian package dependencies.")
- else ()
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "libaprutil1t64, libboost-fiber1.83.0, libboost-filesystem1.83.0, libboost-program-options1.83.0, libboost-regex1.83.0, libboost-thread1.83.0, libboost-url1.83.0, libexpat1, libfltk1.4, libgles-dev, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libminizip1t64, libnghttp2-14, libnspr4, libnss3, libopenjp2-7, libsdl2-2.0-0, libvlc5, libvorbisenc2, libvorbisfile3, vlc-plugin-base"
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libalut0, libaprutil1t64, libboost-fiber1.83.0, libboost-filesystem1.83.0, libboost-program-options1.83.0, libboost-regex1.83.0, libboost-thread1.83.0, libboost-url1.83.0, libexpat1, libfltk1.4, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libminizip1t64, libnghttp2-14, libnspr4, libnss3, libopenjp2-7, libsdl2-2.0-0, libvlc5, libvorbisenc2, libvorbisfile3, vlc-plugin-base"
CACHE STRING "Debian package dependencies.")
- endif ()
else ()
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "libaprutil1t64, libboost-fiber1.90.0, libboost-filesystem1.90.0, libboost-program-options1.90.0, libboost-regex1.90.0, libboost-thread1.90.0, libboost-url1.90.0, libexpat1, libfltk1.3t64, libgles-dev, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libminizip1t64, libnghttp2-14, libnspr4, libnss3, libsdl2-2.0-0, libvlc5, libvorbisenc2, libvorbisfile3, vlc-plugin-base"
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libalut0, libaprutil1t64, libboost-fiber1.90.0, libboost-filesystem1.90.0, libboost-program-options1.90.0, libboost-regex1.90.0, libboost-thread1.90.0, libboost-url1.90.0, libexpat1, libfltk1.4, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libminizip1t64, libnghttp2-14, libnspr4, libnss3, libopenjp2-7, libsdl2-2.0-0, libvlc5, libvorbisenc2, libvorbisfile3, vlc-plugin-base"
CACHE STRING "Debian package dependencies.")
endif ()
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed))
@@ -2409,10 +2399,10 @@ if (LINUX)
set(CPACK_RPM_PACKAGE_DESCRIPTION ${VIEWER_PACKAGE_DESCRIPTION}
CACHE STRING "RPM package description.")
if (${LINUX_DISTRO} MATCHES fedora)
- set(CPACK_RPM_PACKAGE_REQUIRES "apr-util, boost-fiber, boost-program-options, boost-regex, boost-thread, boost-url, expat, fltk, mesa-libGLU, hunspell, libnghttp2, openjpeg, sdl2-compat, vlc-libs, vlc-plugins-base, libvorbis"
+ set(CPACK_RPM_PACKAGE_REQUIRES "freealut, apr-util, boost-fiber, boost-program-options, boost-regex, boost-thread, boost-url, cef, expat, fltk, mesa-libGLU, hunspell, minizip-ng-compat, libnghttp2, openjpeg, sdl2-compat, vlc-libs, vlc-plugins-base, libvorbis"
CACHE STRING "RPM package requirements.")
else ()
- set(CPACK_RPM_PACKAGE_REQUIRES "libapr-util1-0, libboost_fiber1_91_0, libboost_program_options1_91_0, libboost_regex1_91_0, libboost_thread1_91_0, libboost_url1_91_0, libboost_url1_91_0-x86-64-v3, libpng16-16 expat, libfltk1_3, libGLU1, libhunspell-1_7-0, libnghttp2-14, openjpeg2, libSDL2-2_0-0, libvlc5, libvorbis0"
+ set(CPACK_RPM_PACKAGE_REQUIRES "libalut0, libapr-util1-0, libboost_fiber1_91_0, libboost_program_options1_91_0, libboost_regex1_91_0, libboost_thread1_91_0, libboost_url1_91_0, libboost_url1_91_0-x86-64-v3, libpng16-16 expat, libfltk1_3, libGLU1, libhunspell-1_7-0, libnghttp2-14, openjpeg2, libSDL2-2_0-0, libvlc5, libvorbis0"
CACHE STRING "RPM package requirements.")
endif ()
endif ()
diff --git a/indra/newview/FixBundle.cmake.in b/indra/newview/FixBundle.cmake.in
index 77b4683c88..1d4192c94c 100644
--- a/indra/newview/FixBundle.cmake.in
+++ b/indra/newview/FixBundle.cmake.in
@@ -158,9 +158,9 @@ execute_process(
COMMAND lipo libbz2.1.0.8.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
-output libbz2.1.0.8.dylib
- COMMAND lipo libexpat.1.11.3.dylib
+ COMMAND lipo libexpat.1.12.2.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
- -output libexpat.1.11.3.dylib
+ -output libexpat.1.12.2.dylib
COMMAND lipo libfreetype.6.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
-output libfreetype.6.dylib
@@ -233,440 +233,3 @@ execute_process(
WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Frameworks
ERROR_QUIET
)
-
-message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Running a native self-built viewer on it without correct codesigning would lead to a crash. Also, codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libEGL.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libGLESv2.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libcef_sandbox.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libvk_swiftshader.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework
- Frameworks/libalut.0.dylib
- Frameworks/libapr-1.0.dylib
- Frameworks/libaprutil-1.0.dylib
- Frameworks/libboost_atomic-mt.dylib
- Frameworks/libboost_context-mt.dylib
- Frameworks/libboost_fiber-mt.dylib
- Frameworks/libboost_filesystem-mt.dylib
- Frameworks/libboost_program_options-mt.dylib
- Frameworks/libboost_regex-mt.dylib
- Frameworks/libboost_system-mt.dylib
- Frameworks/libboost_thread-mt.dylib
- Frameworks/libboost_url-mt.dylib
- Frameworks/libbrotlicommon.1.2.0.dylib
- Frameworks/libbrotlidec.1.2.0.dylib
- Frameworks/libbz2.1.0.8.dylib
- Frameworks/libdiscord_partner_sdk.dylib
- Frameworks/libexpat.1.11.3.dylib
- Frameworks/libfreetype.6.dylib
- Frameworks/libhunspell-1.7.0.dylib
- Frameworks/libiconv.2.dylib
- Frameworks/libicudata.78.3.dylib
- Frameworks/libicui18n.78.3.dylib
- Frameworks/libicuuc.78.3.dylib
- Frameworks/libjpeg.8.3.2.dylib
- Frameworks/libllwebrtc.dylib
- Frameworks/libminizip.1.dylib
- Frameworks/libncurses.6.dylib
- Frameworks/libndofdev.dylib
- Frameworks/libnghttp2.14.dylib
- Frameworks/libogg.0.dylib
- Frameworks/libopenal.1.25.1.dylib
- Frameworks/libopenjp2.2.5.4.dylib
- Frameworks/libpng16.16.dylib
- Frameworks/libvlc.5.dylib
- Frameworks/libvlccore.9.dylib
- Frameworks/libvorbis.0.dylib
- Frameworks/libvorbisenc.2.dylib
- Frameworks/libvorbisfile.3.dylib
- Frameworks/libxml2.16.dylib
- Frameworks/libz.1.3.2.dylib
- Resources/libndofdev.dylib
- Resources/SLPlugin.app/Contents/Frameworks/media_plugin_cef.dylib
- Resources/SLPlugin.app/Contents/Frameworks/media_plugin_libvlc.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_concat_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_imem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_mms_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_file_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_http_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_livehttp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_rist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_shout_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_srt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_udp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_realrtsp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_srt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadaptive_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsfsstorage_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsvorepository_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadjust_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadpcm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaes3_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libafile_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaiff_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libalphamask_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libamem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libanaglyph_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libantiflicker_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaom_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaraw_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libarchive_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaribsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libasf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libattachment_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libau_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudio_format_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_a_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_v_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudioscrobbler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiotoolboxmidi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libauhal_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavaudiocapture_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcapture_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcodec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libball_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libblend_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libblendbench_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluescreen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-awt-j2se-1.4.0.jar
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-j2se-1.4.0.jar
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbonjour_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_block_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_read_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcanvas_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaopengllayer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdda_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libchain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libchorus_flanger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libci_filters_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libclone_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcolorthres_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcompressor_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libconsole_logger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcroppadd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvdsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdav1d_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdcp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libddummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdecomp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdeinterlace_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_cdg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_chromecast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_stl_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemuxdump_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdiracsys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdirectory_demux_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdmxmus_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdolby_surround_decoder_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvbsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdnav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdread_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdynamicoverlay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libedgedetection_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libedummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libequalizer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liberase_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libes_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libexport_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libextract_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfaad_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_keystore_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_logger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfilesystem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfingerprinter_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflacsys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflaschen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfloat_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfolder_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreetype_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreeze_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libftp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libg711_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgaussianblur_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgestures_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libglconv_cvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgme_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgnutls_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgoom_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradfun_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradient_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrey_yuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libh26x_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhds_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libheadphone_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhotkeys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhqdn3d_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_10_p010_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_nv12_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_i420_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libidummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libimage_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libimem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinflate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinteger_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinvert_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkaraoke_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkeychain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibass_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibbluray_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblive555_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblpcm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblua_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmacosx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmad_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmagnify_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmarq_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmediadirs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmemory_keystore_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmirror_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmkv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmod_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmono_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmosaic_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotion_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotionblur_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotiondetect_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmp4_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpg123_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpgv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_asf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_avi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mp4_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mpjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ogg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_wav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libncurses_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnetsync_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnfs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnormvol_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnoseek_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsspeechsynthesizer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libogg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboggspots_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldmovie_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldrc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libopus_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libosx_notifications_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_a52_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_av1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_copy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dirac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_flac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_h264_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_hevc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mlp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4audio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4video_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_vc1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libparam_eq_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libplaylist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpng_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpodcast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libposterize_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpostproc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libprefetch_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpsychedelic_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpuzzle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpva_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawaud_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawdv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libreal_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librecord_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libremap_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libremoteosd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libripple_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librotate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librss_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librtp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librtpvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librv32_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsamplerate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsap_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsatip_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscale_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_pitch_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscene_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libschroedinger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscreen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte18_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte27_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsdp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsecuretransport_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsepia_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsftp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsharpen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libshm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsimple_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libskiptags_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsmf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatialaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatializer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspdif_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_resampler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspudec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstats_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstereo_widen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstl_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_autodel_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_bridge_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromaprint_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromecast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_cycle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_delay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_description_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_display_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_duplicate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_es_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_gather_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_mosaic_bridge_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_record_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_rtp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_setid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_smem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_standard_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_stats_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_transcode_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdelay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubstx3g_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsusf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubtitle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsvcdsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libswscale_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsyslog_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libt140_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtaglib_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtcp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtelx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtextst_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtheora_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtimecode_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtospdif_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtransform_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtrivial_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtta_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libttml_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtwolame_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libty_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libudp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libugly_resampler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libuleaddvaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libupnp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvc1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvcd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdr_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvhs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvideotoolbox_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvisual_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlc.5.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlccore.9.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvmem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvobsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvoc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvod_rtsp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvorbis_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvout_macosx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwall_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwave_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwebvtt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx26410b_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx264_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx265_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libxa_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libxml_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuvp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i420_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i422_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libzvbi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Alerts\).app/Contents/MacOS/DullahanHelper\ \(Alerts\)
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(GPU\).app/Contents/MacOS/DullahanHelper\ \(GPU\)
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Plugin\).app/Contents/MacOS/DullahanHelper\ \(Plugin\)
- WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- DullahanHelper.app
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- DullahanHelper\ \(Renderer\).app/Contents/MacOS/DullahanHelper\ \(Renderer\)
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --deep
- DullahanHelper\ \(Alerts\).app
- DullahanHelper\ \(GPU\).app
- DullahanHelper\ \(Plugin\).app
- WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- --deep
- DullahanHelper\ \(Renderer\).app
- WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- SLPlugin.app
- WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- -i net.${VIEWER_BINARY_NAME}.viewer
- ${VIEWER_CHANNEL}.app
- WORKING_DIRECTORY ${viewer_BINARY_DIR}
- )
diff --git a/indra/newview/FixPackage.cmake.in b/indra/newview/FixPackage.cmake.in
index e67026aabb..26fd3ccff7 100644
--- a/indra/newview/FixPackage.cmake.in
+++ b/indra/newview/FixPackage.cmake.in
@@ -158,9 +158,9 @@ execute_process(
COMMAND lipo libbz2.1.0.8.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
-output libbz2.1.0.8.dylib
- COMMAND lipo libexpat.1.11.3.dylib
+ COMMAND lipo libexpat.1.12.2.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
- -output libexpat.1.11.3.dylib
+ -output libexpat.1.12.2.dylib
COMMAND lipo libfreetype.6.dylib
-thin ${CMAKE_OSX_ARCHITECTURES}
-output libfreetype.6.dylib
@@ -233,439 +233,3 @@ execute_process(
WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Frameworks
ERROR_QUIET
)
-
-message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Running a native self-built viewer on it without correct codesigning would lead to a crash. Also, codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libEGL.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libGLESv2.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libcef_sandbox.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libvk_swiftshader.dylib
- Frameworks/Chromium\ Embedded\ Framework.framework
- Frameworks/libalut.0.dylib
- Frameworks/libapr-1.0.dylib
- Frameworks/libaprutil-1.0.dylib
- Frameworks/libboost_atomic-mt.dylib
- Frameworks/libboost_context-mt.dylib
- Frameworks/libboost_fiber-mt.dylib
- Frameworks/libboost_filesystem-mt.dylib
- Frameworks/libboost_program_options-mt.dylib
- Frameworks/libboost_regex-mt.dylib
- Frameworks/libboost_system-mt.dylib
- Frameworks/libboost_thread-mt.dylib
- Frameworks/libboost_url-mt.dylib
- Frameworks/libbrotlicommon.1.2.0.dylib
- Frameworks/libbrotlidec.1.2.0.dylib
- Frameworks/libbz2.1.0.8.dylib
- Frameworks/libdiscord_partner_sdk.dylib
- Frameworks/libexpat.1.11.3.dylib
- Frameworks/libfreetype.6.dylib
- Frameworks/libhunspell-1.7.0.dylib
- Frameworks/libiconv.2.dylib
- Frameworks/libicudata.78.3.dylib
- Frameworks/libicui18n.78.3.dylib
- Frameworks/libicuuc.78.3.dylib
- Frameworks/libjpeg.8.3.2.dylib
- Frameworks/libllwebrtc.dylib
- Frameworks/libminizip.1.dylib
- Frameworks/libncurses.6.dylib
- Frameworks/libndofdev.dylib
- Frameworks/libnghttp2.14.dylib
- Frameworks/libogg.0.dylib
- Frameworks/libopenal.1.25.1.dylib
- Frameworks/libopenjp2.2.5.4.dylib
- Frameworks/libpng16.16.dylib
- Frameworks/libvlc.5.dylib
- Frameworks/libvlccore.9.dylib
- Frameworks/libvorbis.0.dylib
- Frameworks/libvorbisenc.2.dylib
- Frameworks/libvorbisfile.3.dylib
- Frameworks/libxml2.16.dylib
- Frameworks/libz.1.3.2.dylib
- Resources/libndofdev.dylib
- Resources/SLPlugin.app/Contents/Frameworks/media_plugin_cef.dylib
- Resources/SLPlugin.app/Contents/Frameworks/media_plugin_libvlc.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_concat_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_imem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_mms_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_file_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_http_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_livehttp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_rist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_shout_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_srt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_udp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_realrtsp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_srt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadaptive_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsfsstorage_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsvorepository_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadjust_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadpcm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libadummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaes3_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libafile_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaiff_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libalphamask_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libamem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libanaglyph_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libantiflicker_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaom_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaraw_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libarchive_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaribsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libasf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libattachment_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libau_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudio_format_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_a_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_v_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudioscrobbler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiotoolboxmidi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libauhal_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavaudiocapture_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcapture_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcodec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libavi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libball_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libblend_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libblendbench_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluescreen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-awt-j2se-1.4.0.jar
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-j2se-1.4.0.jar
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libbonjour_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_block_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_read_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcanvas_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaopengllayer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdda_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libchain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libchorus_flanger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libci_filters_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libclone_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcolorthres_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcompressor_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libconsole_logger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcroppadd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvdsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdav1d_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdcp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libddummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdecomp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdeinterlace_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_cdg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_chromecast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_stl_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemuxdump_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdiracsys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdirectory_demux_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdmxmus_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdolby_surround_decoder_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvbsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdnav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdread_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libdynamicoverlay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libedgedetection_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libedummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libequalizer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liberase_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libes_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libexport_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libextract_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfaad_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_keystore_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_logger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfilesystem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfingerprinter_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflacsys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libflaschen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfloat_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfolder_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreetype_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreeze_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libftp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libg711_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgaussianblur_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgestures_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libglconv_cvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgme_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgnutls_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgoom_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradfun_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradient_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrey_yuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libh26x_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhds_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libheadphone_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhotkeys_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhqdn3d_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_10_p010_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_nv12_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_i420_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_mmx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_sse2_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libidummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libimage_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libimem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinflate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinteger_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libinvert_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkaraoke_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libkeychain_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibass_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibbluray_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblive555_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblpcm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liblua_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmacosx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmad_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmagnify_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmarq_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmediadirs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmemory_keystore_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmirror_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmkv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmod_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmono_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmosaic_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotion_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotionblur_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotiondetect_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmp4_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpg123_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpgv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_asf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_avi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mp4_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mpjpeg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ogg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_wav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libncurses_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnetsync_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnfs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnormvol_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnoseek_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsspeechsynthesizer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libnuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libogg_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboggspots_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldmovie_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldrc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libopus_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libosx_notifications_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_a52_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_av1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_copy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dirac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_flac_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_h264_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_hevc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mlp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4audio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4video_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_vc1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libparam_eq_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libplaylist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpng_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpodcast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libposterize_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpostproc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libprefetch_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libps_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpsychedelic_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpuzzle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libpva_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawaud_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawdv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libreal_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librecord_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libremap_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libremoteosd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libripple_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librist_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librotate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librss_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librtp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librtpvideo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/librv32_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsamplerate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsap_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsatip_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscale_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_pitch_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscene_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libschroedinger_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscreen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte18_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte27_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsdp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsecuretransport_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsepia_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsftp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsharpen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libshm_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsimple_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libskiptags_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsmf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatialaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatializer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspdif_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_resampler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libspudec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstats_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstereo_widen_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstl_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_autodel_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_bridge_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromaprint_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromecast_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_cycle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_delay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_description_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_display_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_dummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_duplicate_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_es_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_gather_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_mosaic_bridge_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_record_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_rtp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_setid_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_smem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_standard_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_stats_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_transcode_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdec_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdelay_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubstx3g_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsusf_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubtitle_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsvcdsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libswscale_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libsyslog_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libt140_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtaglib_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtcp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtelx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtextst_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtheora_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtimecode_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtospdif_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtransform_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtrivial_channel_mixer_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libts_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtta_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libttml_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libtwolame_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libty_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libudp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libugly_resampler_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libuleaddvaudio_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libupnp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvc1_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvcd_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdr_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdummy_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvhs_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvideotoolbox_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvisual_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlc.5.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlccore.9.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvmem_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvobsub_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvoc_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvod_rtsp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvorbis_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvout_macosx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libvpx_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwall_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwav_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwave_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libwebvtt_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx26410b_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx264_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libx265_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libxa_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libxml_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuv_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuvp_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i420_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i422_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/plugins/libzvbi_plugin.dylib
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper.app
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Alerts\).app/Contents/MacOS/DullahanHelper\ \(Alerts\)
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(GPU\).app/Contents/MacOS/DullahanHelper\ \(GPU\)
- Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Plugin\).app/Contents/MacOS/DullahanHelper\ \(Plugin\)
- WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- DullahanHelper\ \(Renderer\).app/Contents/MacOS/DullahanHelper\ \(Renderer\)
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --deep
- DullahanHelper\ \(Alerts\).app
- DullahanHelper\ \(GPU\).app
- DullahanHelper\ \(Plugin\).app
- WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- --deep
- DullahanHelper\ \(Renderer\).app
- WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- SLPlugin.app
- WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources
- )
-execute_process(
- COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
- --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
- -i net.${VIEWER_BINARY_NAME}.viewer
- ${CPACK_BUNDLE_NAME}.app
- WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}
- )
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 82f63519db..81deab1055 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -38,6 +38,8 @@
<string>public.app-category.games</string>
<key>NSHighResolutionCapable</key>
<true/>
+ <key>NSLocalNetworkUsageDescription</key>
+ <string>Second Life uses WebRTC for voice chat, which may require local network access while establishing the voice connection.</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
diff --git a/indra/newview/PKGBUILD.in b/indra/newview/PKGBUILD.in
index 3310c6c601..8b57e62f58 100644
--- a/indra/newview/PKGBUILD.in
+++ b/indra/newview/PKGBUILD.in
@@ -6,7 +6,7 @@ pkgdesc="${VIEWER_PACKAGE_COMMENT}"
arch=('${CMAKE_SYSTEM_PROCESSOR}')
url="https://${VIEWER_PACKAGE_DOMAIN_NAME}"
license=('LGPL-2.1')
-depends=(apr-util at-spi2-core boost-libs fltk glu hunspell libnghttp2 openjpeg2 sdl2 vlc libvorbis)
+depends=(freealut apr-util boost-libs fltk glu hunspell libnghttp2 openjpeg2 sdl2 vlc libvorbis ${ARCH_DEPS})
package() {
cd "$startdir"
diff --git a/indra/newview/SignBundle.cmake.in b/indra/newview/SignBundle.cmake.in
new file mode 100644
index 0000000000..eb6ea1a35d
--- /dev/null
+++ b/indra/newview/SignBundle.cmake.in
@@ -0,0 +1,430 @@
+message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Running a native self-built viewer on it without correct codesigning would lead to a crash. Also, codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libEGL.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libGLESv2.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libcef_sandbox.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libvk_swiftshader.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework
+ Frameworks/libalut.0.dylib
+ Frameworks/libapr-1.0.dylib
+ Frameworks/libaprutil-1.0.dylib
+ Frameworks/libboost_atomic-mt.dylib
+ Frameworks/libboost_context-mt.dylib
+ Frameworks/libboost_fiber-mt.dylib
+ Frameworks/libboost_filesystem-mt.dylib
+ Frameworks/libboost_program_options-mt.dylib
+ Frameworks/libboost_regex-mt.dylib
+ Frameworks/libboost_system-mt.dylib
+ Frameworks/libboost_thread-mt.dylib
+ Frameworks/libboost_url-mt.dylib
+ Frameworks/libbrotlicommon.1.2.0.dylib
+ Frameworks/libbrotlidec.1.2.0.dylib
+ Frameworks/libbz2.1.0.8.dylib
+ Frameworks/libdiscord_partner_sdk.dylib
+ Frameworks/libexpat.1.12.2.dylib
+ Frameworks/libfreetype.6.dylib
+ Frameworks/libhunspell-1.7.0.dylib
+ Frameworks/libiconv.2.dylib
+ Frameworks/libicudata.78.3.dylib
+ Frameworks/libicui18n.78.3.dylib
+ Frameworks/libicuuc.78.3.dylib
+ Frameworks/libjpeg.8.3.2.dylib
+ Frameworks/libllwebrtc.dylib
+ Frameworks/libminizip.1.dylib
+ Frameworks/libncurses.6.dylib
+ Frameworks/libndofdev.dylib
+ Frameworks/libnghttp2.14.dylib
+ Frameworks/libogg.0.dylib
+ Frameworks/libopenal.1.25.1.dylib
+ Frameworks/libopenjp2.2.5.4.dylib
+ Frameworks/libpng16.16.dylib
+ Frameworks/libvlc.5.dylib
+ Frameworks/libvlccore.9.dylib
+ Frameworks/libvorbis.0.dylib
+ Frameworks/libvorbisenc.2.dylib
+ Frameworks/libvorbisfile.3.dylib
+ Frameworks/libxml2.16.dylib
+ Frameworks/libz.1.3.2.dylib
+ Resources/libndofdev.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/media_plugin_cef.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/media_plugin_libvlc.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_concat_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_imem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_mms_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_file_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_http_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_livehttp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_rist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_shout_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_srt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_udp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_realrtsp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_srt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadaptive_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsfsstorage_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsvorepository_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadjust_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadpcm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaes3_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libafile_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaiff_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libalphamask_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libamem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libanaglyph_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libantiflicker_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaom_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaraw_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libarchive_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaribsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libasf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libattachment_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libau_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudio_format_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_a_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_v_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudioscrobbler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiotoolboxmidi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libauhal_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavaudiocapture_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcapture_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcodec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libball_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libblend_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libblendbench_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluescreen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-awt-j2se-1.4.0.jar
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-j2se-1.4.0.jar
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbonjour_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_block_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_read_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcanvas_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaopengllayer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdda_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libchain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libchorus_flanger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libci_filters_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libclone_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcolorthres_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcompressor_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libconsole_logger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcroppadd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvdsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdav1d_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdcp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libddummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdecomp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdeinterlace_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_cdg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_chromecast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_stl_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemuxdump_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdiracsys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdirectory_demux_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdmxmus_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdolby_surround_decoder_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvbsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdnav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdread_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdynamicoverlay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libedgedetection_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libedummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libequalizer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liberase_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libes_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libexport_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libextract_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfaad_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_keystore_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_logger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfilesystem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfingerprinter_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflacsys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflaschen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfloat_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfolder_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreetype_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreeze_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libftp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libg711_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgaussianblur_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgestures_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libglconv_cvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgme_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgnutls_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgoom_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradfun_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradient_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrey_yuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libh26x_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhds_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libheadphone_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhotkeys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhqdn3d_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_10_p010_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_nv12_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_i420_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libidummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libimage_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libimem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinflate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinteger_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinvert_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkaraoke_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkeychain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibass_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibbluray_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblive555_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblpcm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblua_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmacosx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmad_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmagnify_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmarq_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmediadirs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmemory_keystore_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmirror_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmkv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmod_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmono_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmosaic_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotion_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotionblur_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotiondetect_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmp4_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpg123_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpgv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_asf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_avi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mp4_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mpjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ogg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_wav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libncurses_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnetsync_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnfs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnormvol_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnoseek_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsspeechsynthesizer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libogg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboggspots_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldmovie_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldrc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libopus_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libosx_notifications_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_a52_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_av1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_copy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dirac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_flac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_h264_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_hevc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mlp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4audio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4video_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_vc1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libparam_eq_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libplaylist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpng_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpodcast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libposterize_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpostproc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libprefetch_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpsychedelic_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpuzzle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpva_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawaud_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawdv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libreal_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librecord_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libremap_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libremoteosd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libripple_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librotate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librss_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librtp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librtpvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librv32_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsamplerate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsap_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsatip_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscale_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_pitch_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscene_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libschroedinger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscreen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte18_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte27_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsdp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsecuretransport_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsepia_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsftp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsharpen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libshm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsimple_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libskiptags_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsmf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatialaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatializer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspdif_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_resampler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspudec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstats_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstereo_widen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstl_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_autodel_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_bridge_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromaprint_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromecast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_cycle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_delay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_description_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_display_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_duplicate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_es_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_gather_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_mosaic_bridge_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_record_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_rtp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_setid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_smem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_standard_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_stats_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_transcode_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdelay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubstx3g_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsusf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubtitle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsvcdsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libswscale_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsyslog_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libt140_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtaglib_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtcp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtelx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtextst_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtheora_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtimecode_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtospdif_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtransform_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtrivial_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtta_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libttml_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtwolame_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libty_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libudp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libugly_resampler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libuleaddvaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libupnp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvc1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvcd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdr_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvhs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvideotoolbox_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvisual_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlc.5.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlccore.9.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvmem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvobsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvoc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvod_rtsp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvorbis_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvout_macosx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwall_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwave_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwebvtt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx26410b_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx264_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx265_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libxa_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libxml_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuvp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i420_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i422_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libzvbi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Alerts\).app/Contents/MacOS/DullahanHelper\ \(Alerts\)
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(GPU\).app/Contents/MacOS/DullahanHelper\ \(GPU\)
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Plugin\).app/Contents/MacOS/DullahanHelper\ \(Plugin\)
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ DullahanHelper.app
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ DullahanHelper\ \(Renderer\).app/Contents/MacOS/DullahanHelper\ \(Renderer\)
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --deep
+ DullahanHelper\ \(Alerts\).app
+ DullahanHelper\ \(GPU\).app
+ DullahanHelper\ \(Plugin\).app
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ --deep
+ DullahanHelper\ \(Renderer\).app
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ SLPlugin.app
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ -i net.${VIEWER_BINARY_NAME}.viewer
+ ${VIEWER_CHANNEL}.app
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}
+ )
diff --git a/indra/newview/SignBundleMmxSse2.cmake.in b/indra/newview/SignBundleMmxSse2.cmake.in
new file mode 100644
index 0000000000..9d463337b0
--- /dev/null
+++ b/indra/newview/SignBundleMmxSse2.cmake.in
@@ -0,0 +1,11 @@
+message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_sse2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_sse2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_sse2_plugin.dylib
+ WORKING_DIRECTORY ${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents
+ )
diff --git a/indra/newview/SignPackage.cmake.in b/indra/newview/SignPackage.cmake.in
new file mode 100644
index 0000000000..9b5be4a7fd
--- /dev/null
+++ b/indra/newview/SignPackage.cmake.in
@@ -0,0 +1,430 @@
+message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Running a native self-built viewer on it without correct codesigning would lead to a crash. Also, codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libEGL.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libGLESv2.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libcef_sandbox.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/libvk_swiftshader.dylib
+ Frameworks/Chromium\ Embedded\ Framework.framework
+ Frameworks/libalut.0.dylib
+ Frameworks/libapr-1.0.dylib
+ Frameworks/libaprutil-1.0.dylib
+ Frameworks/libboost_atomic-mt.dylib
+ Frameworks/libboost_context-mt.dylib
+ Frameworks/libboost_fiber-mt.dylib
+ Frameworks/libboost_filesystem-mt.dylib
+ Frameworks/libboost_program_options-mt.dylib
+ Frameworks/libboost_regex-mt.dylib
+ Frameworks/libboost_system-mt.dylib
+ Frameworks/libboost_thread-mt.dylib
+ Frameworks/libboost_url-mt.dylib
+ Frameworks/libbrotlicommon.1.2.0.dylib
+ Frameworks/libbrotlidec.1.2.0.dylib
+ Frameworks/libbz2.1.0.8.dylib
+ Frameworks/libdiscord_partner_sdk.dylib
+ Frameworks/libexpat.1.12.2.dylib
+ Frameworks/libfreetype.6.dylib
+ Frameworks/libhunspell-1.7.0.dylib
+ Frameworks/libiconv.2.dylib
+ Frameworks/libicudata.78.3.dylib
+ Frameworks/libicui18n.78.3.dylib
+ Frameworks/libicuuc.78.3.dylib
+ Frameworks/libjpeg.8.3.2.dylib
+ Frameworks/libllwebrtc.dylib
+ Frameworks/libminizip.1.dylib
+ Frameworks/libncurses.6.dylib
+ Frameworks/libndofdev.dylib
+ Frameworks/libnghttp2.14.dylib
+ Frameworks/libogg.0.dylib
+ Frameworks/libopenal.1.25.1.dylib
+ Frameworks/libopenjp2.2.5.4.dylib
+ Frameworks/libpng16.16.dylib
+ Frameworks/libvlc.5.dylib
+ Frameworks/libvlccore.9.dylib
+ Frameworks/libvorbis.0.dylib
+ Frameworks/libvorbisenc.2.dylib
+ Frameworks/libvorbisfile.3.dylib
+ Frameworks/libxml2.16.dylib
+ Frameworks/libz.1.3.2.dylib
+ Resources/libndofdev.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/media_plugin_cef.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/media_plugin_libvlc.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_concat_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_imem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_mms_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_file_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_http_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_livehttp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_rist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_shout_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_srt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_output_udp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_realrtsp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaccess_srt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadaptive_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsfsstorage_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaddonsvorepository_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadjust_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadpcm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libadummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaes3_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libafile_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaiff_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libalphamask_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libamem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libanaglyph_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libantiflicker_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaom_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaraw_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libarchive_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaribsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libasf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libattachment_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libau_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudio_format_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_a_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiobargraph_v_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudioscrobbler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libaudiotoolboxmidi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libauhal_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavaudiocapture_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcapture_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavcodec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libavi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libball_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libblend_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libblendbench_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluescreen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-awt-j2se-1.4.0.jar
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbluray-j2se-1.4.0.jar
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libbonjour_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_block_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcache_read_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcanvas_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcaopengllayer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdda_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcdg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libchain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libchorus_flanger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libci_filters_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libclone_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcolorthres_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcompressor_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libconsole_logger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcroppadd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvdsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libcvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdav1d_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdcp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libddummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdecomp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdeinterlace_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_cdg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_chromecast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemux_stl_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdemuxdump_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdiracsys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdirectory_demux_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdmxmus_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdolby_surround_decoder_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvbsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdnav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdvdread_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libdynamicoverlay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libedgedetection_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libedummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libequalizer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liberase_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libes_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libexport_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libextract_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfaad_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_keystore_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfile_logger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfilesystem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfingerprinter_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflacsys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libflaschen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfloat_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfolder_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreetype_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libfreeze_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libftp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libg711_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgaussianblur_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgestures_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libglconv_cvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgme_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgnutls_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgoom_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradfun_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgradient_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libgrey_yuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libh26x_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhds_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libheadphone_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhotkeys_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhqdn3d_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libhttps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_10_p010_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_nv12_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_i420_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libidummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libimage_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libimem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinflate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinteger_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libinvert_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkaraoke_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libkeychain_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibass_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblibbluray_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblive555_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblogo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblpcm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liblua_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmacosx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmad_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmagnify_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmarq_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmediadirs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmemory_keystore_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmirror_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmkv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmod_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmono_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmosaic_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotion_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotionblur_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmotiondetect_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmp4_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpg123_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmpgv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_asf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_avi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mp4_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_mpjpeg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ogg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_ts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libmux_wav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libncurses_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnetsync_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnfs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnormvol_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnoseek_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsspeechsynthesizer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnsv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libnuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libogg_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboggspots_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldmovie_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/liboldrc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libopus_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libosx_notifications_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_a52_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_av1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_copy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dirac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_dts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_flac_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_h264_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_hevc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mlp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4audio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpeg4video_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_mpegvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpacketizer_vc1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libparam_eq_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libplaylist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpng_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpodcast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libposterize_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpostproc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libprefetch_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libps_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpsychedelic_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpuzzle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libpva_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawaud_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawdv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librawvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libreal_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librecord_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libremap_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libremoteosd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libripple_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librist_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librotate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librss_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librtp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librtpvideo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/librv32_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsamplerate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsap_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsatip_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscale_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_pitch_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscaletempo_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscene_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libschroedinger_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscreen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte18_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libscte27_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsdp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsecuretransport_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsepia_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsftp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsharpen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libshm_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsimple_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libskiptags_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsmf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatialaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspatializer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspdif_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspeex_resampler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libspudec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstats_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstereo_widen_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstl_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_autodel_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_bridge_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromaprint_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_chromecast_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_cycle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_delay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_description_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_display_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_dummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_duplicate_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_es_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_gather_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_mosaic_bridge_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_record_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_rtp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_setid_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_smem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_standard_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_stats_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libstream_out_transcode_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdec_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsdelay_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubstx3g_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubsusf_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsubtitle_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsvcdsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libswscale_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libsyslog_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libt140_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtaglib_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtcp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtelx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtextst_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtheora_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtimecode_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtospdif_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtransform_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtrivial_channel_mixer_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libts_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtta_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libttml_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libtwolame_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libty_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libudp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libugly_resampler_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libuleaddvaudio_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libupnp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvc1_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvcd_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdr_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvdummy_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvhs_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvideotoolbox_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvisual_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlc.5.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvlccore.9.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvmem_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvobsub_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvoc_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvod_rtsp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvorbis_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvout_macosx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libvpx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwall_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwav_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwave_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libwebvtt_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx26410b_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx264_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libx265_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libxa_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libxml_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuv_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuvp_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i420_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libyuy2_i422_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libzvbi_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Alerts\).app/Contents/MacOS/DullahanHelper\ \(Alerts\)
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(GPU\).app/Contents/MacOS/DullahanHelper\ \(GPU\)
+ Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper\ \(Plugin\).app/Contents/MacOS/DullahanHelper\ \(Plugin\)
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ DullahanHelper.app
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ DullahanHelper\ \(Renderer\).app/Contents/MacOS/DullahanHelper\ \(Renderer\)
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --deep
+ DullahanHelper\ \(Alerts\).app
+ DullahanHelper\ \(GPU\).app
+ DullahanHelper\ \(Plugin\).app
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ --deep
+ DullahanHelper\ \(Renderer\).app
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ SLPlugin.app
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources
+ )
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ --entitlements ${CMAKE_SOURCE_DIR}/newview/slplugin.entitlements
+ -i net.${VIEWER_BINARY_NAME}.viewer
+ ${CPACK_BUNDLE_NAME}.app
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}
+ )
diff --git a/indra/newview/SignPackageMmxSse2.cmake.in b/indra/newview/SignPackageMmxSse2.cmake.in
new file mode 100644
index 0000000000..9a1c22cf68
--- /dev/null
+++ b/indra/newview/SignPackageMmxSse2.cmake.in
@@ -0,0 +1,11 @@
+message("By default, the situation is assumed to be the strictest, an Apple Silicon Mac with the default security settings. Codesigning requires administrative access. If you believe you're not in such a situation, you can remove the sudos in this file.")
+execute_process(
+ COMMAND sudo codesign -f -s ${SIGNING_IDENTITY} --timestamp -o runtime --runtime-version ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_rgb_sse2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi420_yuy2_sse2_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_mmx_plugin.dylib
+ Resources/SLPlugin.app/Contents/Frameworks/plugins/libi422_yuy2_sse2_plugin.dylib
+ WORKING_DIRECTORY ${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents
+ )
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 124b7a2cd0..c4697fd566 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-26.1.1
+26.3.0
diff --git a/indra/newview/ViewerInstall.cmake b/indra/newview/ViewerInstall.cmake
index 56a3394943..440c72c561 100644
--- a/indra/newview/ViewerInstall.cmake
+++ b/indra/newview/ViewerInstall.cmake
@@ -75,13 +75,37 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/FixPackage.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake
)
- else (PACKAGE)
+ if (CMAKE_OSX_ARCHITECTURES MATCHES x86_64)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/SignPackageMmxSse2.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/SignBundleMmxSse2.cmake
+ )
+ endif ()
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/SignPackage.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/SignBundle.cmake
+ )
+ else ()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/FixBundle.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake
)
- endif (PACKAGE)
+ if (CMAKE_OSX_ARCHITECTURES MATCHES x86_64)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/SignBundleMmxSse2.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/SignBundleMmxSse2.cmake
+ )
+ endif ()
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/SignBundle.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/SignBundle.cmake
+ )
+ endif ()
install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake)
+ if (CMAKE_OSX_ARCHITECTURES MATCHES x86_64)
+ install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/SignBundleMmxSse2.cmake)
+ endif ()
+ install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/SignBundle.cmake)
elseif (WINDOWS)
@@ -130,18 +154,29 @@ elseif (WINDOWS)
set(BOOST_PLATFORM x${ADDRESS_SIZE})
endif ()
+ # Detect the actual Boost DLL suffix from vcpkg-installed binaries.
+ file(GLOB _boost_context_dlls "${prefix_result}/../bin/boost_context-*.dll")
+ if (_boost_context_dlls)
+ list(GET _boost_context_dlls 0 _boost_context_dll)
+ get_filename_component(_boost_context_dll_name "${_boost_context_dll}" NAME_WE)
+ string(REPLACE "boost_context" "" BOOST_DLL_SFX "${_boost_context_dll_name}")
+ else ()
+ set(BOOST_DLL_SFX -vc143-mt-${BOOST_PLATFORM}-1_91)
+ message(WARNING "Could not detect Boost DLL suffix via glob; using fallback '${BOOST_DLL_SFX}'.")
+ endif ()
+
install(
PROGRAMS
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${VIEWER_BINARY_NAME}.exe
${prefix_result}/../bin/OpenAL32.dll
${prefix_result}/../bin/alut.dll
- ${prefix_result}/../bin/boost_context-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_fiber-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_filesystem-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_json-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_program_options-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_thread-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_url-vc143-mt-${BOOST_PLATFORM}-1_91.dll
+ ${prefix_result}/../bin/boost_context${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_fiber${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_filesystem${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_json${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_program_options${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_thread${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_url${BOOST_DLL_SFX}.dll
${prefix_result}/../bin/brotlicommon.dll
${prefix_result}/../bin/brotlidec.dll
${prefix_result}/../bin/bz2.dll
@@ -176,8 +211,8 @@ elseif (WINDOWS)
install(
PROGRAMS
- ${prefix_result}/../bin/boost_context-vc143-mt-${BOOST_PLATFORM}-1_91.dll
- ${prefix_result}/../bin/boost_fiber-vc143-mt-${BOOST_PLATFORM}-1_91.dll
+ ${prefix_result}/../bin/boost_context${BOOST_DLL_SFX}.dll
+ ${prefix_result}/../bin/boost_fiber${BOOST_DLL_SFX}.dll
${prefix_result}/../bin/libapr-1.dll
${prefix_result}/../bin/libaprutil-1.dll
${prefix_result}/../bin/libexpat.dll
@@ -191,12 +226,14 @@ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${VIEWER_BINARY_NAME}
)
if (LINUX)
- if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
- set(_LIB lib/${ARCH}-linux-gnu)
+ if (${LINUX_DISTRO} MATCHES freedesktop)
+ set(_LIB lib)
+ elseif (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu))
+ set(_LIB lib/${ARCH}-linux-gnu/${VIEWER_BINARY_NAME})
elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR (${LINUX_DISTRO} MATCHES gentoo))
- set(_LIB lib${ADDRESS_SIZE})
+ set(_LIB lib${ADDRESS_SIZE}/${VIEWER_BINARY_NAME})
else ()
- set(_LIB lib)
+ set(_LIB lib/${VIEWER_BINARY_NAME})
endif ()
if (USE_DISCORD)
install(
@@ -204,13 +241,24 @@ if (LINUX)
DESTINATION ${_LIB}
)
endif ()
+ if (USE_OPENAL AND (${LINUX_DISTRO} MATCHES freedesktop))
+ install(
+ FILES
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libalut.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libalut.so.0
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libalut.so.0.0.0
+ DESTINATION ${_LIB}
+ )
+ endif ()
if (USE_FMODSTUDIO)
- install(FILES
- ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so
- ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so.13
- ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so.13.34
- DESTINATION ${_LIB})
- endif (USE_FMODSTUDIO)
+ install(
+ FILES
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so.13
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libfmod.so.13.35
+ DESTINATION ${_LIB}
+ )
+ endif ()
endif (LINUX)
install(DIRECTORY skins app_settings fonts
@@ -218,9 +266,43 @@ install(DIRECTORY skins app_settings fonts
PATTERN ".svn" EXCLUDE
)
+if (${LINUX_DISTRO} MATCHES freedesktop)
+ file(
+ COPY ${CMAKE_CURRENT_SOURCE_DIR}/icons/hicolor
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/48x48/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/48x48/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/64x64/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/64x64/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/96x96/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/96x96/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/128x128/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/128x128/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/256x256/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/256x256/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ file(RENAME
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/512x512/apps/${VIEWER_BINARY_NAME}.png
+ ${CMAKE_CURRENT_BINARY_DIR}/hicolor/512x512/apps/net.${VIEWER_BINARY_NAME}.Viewer.png
+ )
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hicolor
+ DESTINATION share/icons
+ )
+else ()
install(DIRECTORY icons/hicolor
DESTINATION share/icons
)
+endif ()
find_file(IS_ARTWORK_PRESENT NAMES have_artwork_bundle.marker
PATHS ${VIEWER_DIR}/newview/res)
@@ -257,8 +339,31 @@ install(FILES ${SCRIPTS_DIR}/messages/message_template.msg
DESTINATION share/${VIEWER_BINARY_NAME}/app_settings
)
+if (${LINUX_DISTRO} MATCHES freedesktop)
+ file(COPY_FILE
+ ${CMAKE_CURRENT_SOURCE_DIR}/linux_tools/${VIEWER_BINARY_NAME}.desktop
+ ${CMAKE_CURRENT_BINARY_DIR}/net.${VIEWER_BINARY_NAME}.Viewer.desktop
+ )
+ execute_process(
+ COMMAND sed -i "s/Icon=megapahit/Icon=net.megapahit.Viewer/" net.${VIEWER_BINARY_NAME}.Viewer.desktop
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/net.${VIEWER_BINARY_NAME}.Viewer.desktop
+ DESTINATION share/applications
+ )
+ string(TIMESTAMP TODAY_DATE "%Y-%m-%d" UTC)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/net.megapahit.Viewer.metainfo.xml.in
+ ${CMAKE_CURRENT_BINARY_DIR}/net.megapahit.Viewer.metainfo.xml
+ )
+ install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/net.megapahit.Viewer.metainfo.xml
+ DESTINATION share/metainfo
+ )
+else ()
install(FILES linux_tools/${VIEWER_BINARY_NAME}.desktop
DESTINATION share/applications
)
+endif ()
endif (DARWIN)
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 6a05466e06..9b80b40008 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -310,4 +310,15 @@
tooltip_ref="Command_ResyncAnimations_Tooltip"
execute_function="Tools.ResyncAnimations"
/>
+ <!-- Firestorm port: Quick Preferences toolbar button -->
+ <command name="quick_prefs"
+ available_in_toybox="true"
+ icon="Command_Preferences_Icon"
+ label_ref="Command_QuickPrefs_Label"
+ tooltip_ref="Command_QuickPrefs_Tooltip"
+ execute_function="Floater.ToggleOrBringToFront"
+ execute_parameters="quick_prefs"
+ is_running_function="Floater.IsOpen"
+ is_running_parameters="quick_prefs"
+ />
</commands>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 3648a40412..68efed0a67 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -511,6 +511,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RecentJumpThresholdSecs</key>
+ <map>
+ <key>Comment</key>
+ <string>Seconds after a jump input during which finish-anim is suppressed to avoid interrupting rapid successive jumps.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
<key>AvatarAxisDeadZone0</key>
<map>
<key>Comment</key>
@@ -1326,6 +1337,91 @@
<key>Value</key>
<real>1.047197551</real>
</map>
+ <!-- NaCl/Firestorm port: mouselook right-click zoom -->
+ <key>_NACL_MLFovValues</key>
+ <map>
+ <key>Comment</key>
+ <string>Mouselook FOV zoom state: VX=normal FOV, VY=zoomed FOV, VZ=1 if currently zoomed</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>1.047197551</real>
+ <real>1.047197551</real>
+ <real>0.0</real>
+ </array>
+ </map>
+ <key>FSScrollWheelExitsMouselook</key>
+ <map>
+ <key>Comment</key>
+ <string>If enabled, scrolling up while in mouselook (without right mouse held) exits mouselook</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <!-- End NaCl/Firestorm port -->
+ <!-- OTS over-the-shoulder aim settings -->
+ <key>OTSEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>When true, M key enters OTS shoulder cam instead of first-person mouselook</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>OTSCameraDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>OTS camera distance behind avatar (meters)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>3.0</real>
+ </map>
+ <key>OTSCameraSide</key>
+ <map>
+ <key>Comment</key>
+ <string>OTS camera side offset (negative = right of avatar)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>-0.5</real>
+ </map>
+ <key>OTSCameraHeight</key>
+ <map>
+ <key>Comment</key>
+ <string>OTS camera height above avatar root (meters)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+ <key>OTSFocusDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>OTS focus point distance in front of avatar (meters)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+ <!-- End OTS settings -->
<key>CameraOffset</key>
<map>
<key>Comment</key>
@@ -1363,8 +1459,8 @@
<key>Value</key>
<array>
<real>-3.0</real>
- <real>0.5</real>
- <real>0.2</real>
+ <real>0.0</real>
+ <real>0.75</real>
</array>
</map>
<key>CameraOffsetScale</key>
@@ -2667,6 +2763,39 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>PreventClickToSit</key>
+ <map>
+ <key>Comment</key>
+ <string>Prevent sitting on a chair on a click</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DisablePreJumpLand</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable pre-jump and jump animations</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>BlockTeleportOffers</key>
+ <map>
+ <key>Comment</key>
+ <string>Block any teleport offer automatically from coming</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DynamicCameraStrength</key>
<map>
<key>Comment</key>
@@ -3233,9 +3362,9 @@
<string>Vector3D</string>
<key>Value</key>
<array>
- <real>0.9</real>
- <real>0.5</real>
- <real>0.2</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
</array>
</map>
<key>AvatarSitRotation</key>
@@ -4634,6 +4763,39 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MapShowGridCoords</key>
+ <map>
+ <key>Comment</key>
+ <string>Shows/hides the grid coordinates of each region on the world map.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>KeepCameraOnLocalTeleport</key>
+ <map>
+ <key>Comment</key>
+ <string>Do not reset the camera position or mode when teleporting within the same region.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DisableTeleportScreens</key>
+ <map>
+ <key>Comment</key>
+ <string>Do not show the fullscreen teleport progress/black screen during teleports.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>MiniMapAutoCenter</key>
<map>
<key>Comment</key>
@@ -5138,7 +5300,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>MediaControlFadeTime</key>
<map>
@@ -5916,6 +6078,17 @@
<key>Value</key>
<integer>90</integer>
</map>
+ <key>ScriptToastButtonWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Default width of buttons in the Script dialog toast.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>127</integer>
+ </map>
<key>NotificationChannelRightMargin</key>
<map>
<key>Comment</key>
@@ -6147,6 +6320,39 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>OpenDebugStatVoice</key>
+ <map>
+ <key>Comment</key>
+ <string>Expand Voice (WebRTC) stats display</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>OpenDebugStatVoiceOutgoing</key>
+ <map>
+ <key>Comment</key>
+ <string>Expand Outgoing audio (Voice) stats display</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>OpenDebugStatVoiceIncoming</key>
+ <map>
+ <key>Comment</key>
+ <string>Expand Incoming audio (Voice) stats display</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>OutBandwidth</key>
<map>
<key>Comment</key>
@@ -8007,11 +8213,11 @@
<key>Comment</key>
<string>If available free physical memory is below this value textures get agresively scaled down</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>256</integer>
+ <integer>512</integer>
</map>
<key>RenderLowMemMinDiscardIncrement</key>
<map>
@@ -10777,6 +10983,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>GroupTitlesTagMode</key>
+ <map>
+ <key>Comment</key>
+ <string>Select Group Titles tag mode: 0 - no group tags, 1 - only my group tag, 2 - all group tags</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>2</integer>
+ </map>
<key>ShowAxes</key>
<map>
<key>Comment</key>
@@ -11239,6 +11456,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ShowBlockedConvHistory</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies whether blocked agents will be shown in Call Log</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ShowMatureEvents</key>
<map>
<key>Comment</key>
@@ -12426,17 +12654,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>UIFloaterTitleVPad</key>
- <map>
- <key>Comment</key>
- <string>Distance from top of floater to top of title string, pixels</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <real>7</real>
- </map>
<key>UIImgDefaultEyesUUID</key>
<map>
<key>Comment</key>
@@ -13603,141 +13820,8 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>VivoxAutoPostCrashDumps</key>
- <map>
- <key>Comment</key>
- <string>If true, SLVoice will automatically send crash dumps directly to Vivox.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>VivoxDebugLevel</key>
- <map>
- <key>Comment</key>
- <string>Logging level to use when launching the vivox daemon</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>0</string>
- </map>
- <key>VivoxLogDirectory</key>
- <map>
- <key>Comment</key>
- <string>Default log path is Application Support/SecondLife/logs specify alternate absolute path here.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string></string>
- </map>
- <key>VivoxShutdownTimeout</key>
- <map>
- <key>Comment</key>
- <string>shutdown timeout in miliseconds. The amount of time to wait for the service to shutdown gracefully after the last disconnect</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>5</string>
- </map>
- <key>VivoxDebugSIPURIHostName</key>
- <map>
- <key>Comment</key>
- <string>Hostname portion of vivox SIP URIs (empty string for the default).</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string></string>
- </map>
- <key>VivoxDebugVoiceAccountServerURI</key>
- <map>
- <key>Comment</key>
- <string>URI to the vivox account management server (empty string for the default).</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string></string>
- </map>
- <key>VivoxVoiceHost</key>
- <map>
- <key>Comment</key>
- <string>Client SLVoice host to connect to</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>127.0.0.1</string>
- </map>
- <key>VivoxVoicePort</key>
- <map>
- <key>Comment</key>
- <string>Client SLVoice port to connect to</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>44125</integer>
- </map>
-
- <key>VivoxVadAuto</key>
- <map>
- <key>Comment</key>
- <string>A flag indicating if the automatic VAD is enabled (1) or disabled (0). The individual settings are ignored if the auto-mode is enabled</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>VivoxVadHangover</key>
- <map>
- <key>Comment</key>
- <string>The time (in milliseconds) that it takes or the VAD to switch back to silence from speech mode after the last speech frame has been detected</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>2000</integer>
- </map>
- <key>VivoxVadNoiseFloor</key>
- <map>
- <key>Comment</key>
- <string>A dimensionless value between 0 and 20000 (default 576) that controls the maximum level at which the noise floor may be set at by the VAD's noise tracking</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>576</integer>
- </map>
- <key>VivoxVadSensitivity</key>
- <map>
- <key>Comment</key>
- <string>A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>VoiceCallsFriendsOnly</key>
- <!-- deprecated (see SL-12871) -->
+ <key>VoiceCallsFriendsOnly</key>
+ <!-- deprecated (see SL-12871) -->
<map>
<key>Comment</key>
<string>(Deprecated) Only accept voice calls from residents on your friends list</string>
@@ -13814,17 +13898,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>VoiceHost</key>
- <map>
- <key>Comment</key>
- <string>Client SLVoice host to connect to</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>127.0.0.1</string>
- </map>
<key>VoiceImageLevel0</key>
<map>
<key>Comment</key>
@@ -13913,17 +13986,6 @@
<key>Value</key>
<string>Default</string>
</map>
- <key>VoiceLogFile</key>
- <map>
- <key>Comment</key>
- <string>Log file to use when launching the voice daemon</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string></string>
- </map>
<key>VoiceOutputAudioDevice</key>
<map>
<key>Comment</key>
@@ -13946,17 +14008,6 @@
<key>Value</key>
<integer>10</integer>
</map>
- <key>VoicePort</key>
- <map>
- <key>Comment</key>
- <string>Client SLVoice port to connect to</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>44125</integer>
- </map>
<key>VoiceEchoCancellation</key>
<map>
<key>Comment</key>
@@ -17137,6 +17188,39 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>InventoryShowRecentTab</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide Recent tab in the Inventory floater</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>InventoryShowWornTab</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide Worn tab in the Inventory floater</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>InventoryShowFavoritesTab</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide Favorites tab in the Inventory floater</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>StatsReportMaxDuration</key>
<map>
<key>Comment</key>
@@ -17291,5 +17375,16 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>PurgeDiskCacheOnStartup</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not to LRU purge the disk cache during startup on main thread</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
index 8e12d09443..df58f68556 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
@@ -1171,12 +1171,12 @@ vec3 linear_to_srgb(vec3 cl);
// - Float zero is mapped to center of integers (so clear to integer zero is a nice default for atomic max usage).
// Burns 3 ops for conversion {shift,or,xor}.
//==============================================================================================================================
- AU1 AFisToU1(AU1 x){return x^(( AShrSU1(x,AU1_(31)))|AU1_(0x80000000));}
- AU1 AFisFromU1(AU1 x){return x^((~AShrSU1(x,AU1_(31)))|AU1_(0x80000000));}
+ AU1 AFisToU1(AU1 x){return x^(( AShrSU1(x,AU1_(31)))|AU1_(0x80000000u));}
+ AU1 AFisFromU1(AU1 x){return x^((~AShrSU1(x,AU1_(31)))|AU1_(0x80000000u));}
//------------------------------------------------------------------------------------------------------------------------------
// Just adjust high 16-bit value (useful when upper part of 32-bit word is a 16-bit float value).
- AU1 AFisToHiU1(AU1 x){return x^(( AShrSU1(x,AU1_(15)))|AU1_(0x80000000));}
- AU1 AFisFromHiU1(AU1 x){return x^((~AShrSU1(x,AU1_(15)))|AU1_(0x80000000));}
+ AU1 AFisToHiU1(AU1 x){return x^(( AShrSU1(x,AU1_(15)))|AU1_(0x80000000u));}
+ AU1 AFisFromHiU1(AU1 x){return x^((~AShrSU1(x,AU1_(15)))|AU1_(0x80000000u));}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//_____________________________________________________________/\_______________________________________________________________
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
index dd9e883fdf..abe61fe892 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -146,6 +146,9 @@ vec3 srgb_to_linear(vec3 c);
void main()
{
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
+
+ basecolor.a *= vertex_color.a;
+
if (basecolor.a < minimum_alpha)
{
discard;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 50b40e9c20..b08193a7dd 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -51,9 +51,7 @@ in vec3 vary_norm;
in vec4 vertex_color; //vertex color should be treated as sRGB
#endif
-#ifdef HAS_ALPHA_MASK
uniform float minimum_alpha;
-#endif
uniform mat4 proj_mat;
uniform mat4 inv_proj;
@@ -225,6 +223,13 @@ void main()
float final_alpha = diffuse_linear.a;
+#ifdef IS_AVATAR_SKIN
+ if(final_alpha < minimum_alpha)
+ {
+ discard;
+ }
+#endif
+
#ifdef USE_VERTEX_COLOR
final_alpha *= vertex_color.a;
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 396ece9dc1..6cbbb92f50 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -129,10 +129,10 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
+//RenderReflectionProbeCount 1 1
RenderReflectionProbeCount 1 4
RenderReflectionProbeDrawDistance 1 16.0
-
//
// Medium Low Graphics Settings
//
@@ -174,6 +174,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
+//RenderReflectionProbeCount 1 32
RenderReflectionProbeCount 1 16
RenderReflectionProbeDrawDistance 1 24.0
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp
index a2f9cd2852..d44aa9d72c 100644
--- a/indra/newview/gltf/asset.cpp
+++ b/indra/newview/gltf/asset.cpp
@@ -1027,6 +1027,12 @@ bool Image::prepImpl(Asset& asset, const LLUUID& id)
std::string dir = gDirUtilp->getDirName(asset.mFilename);
std::string img_file = dir + gDirUtilp->getDirDelimiter() + mUri;
+ if (!gDirUtilp->fileExists(img_file))
+ {
+ // URI might be escaped, unescape.
+ img_file = dir + gDirUtilp->getDirDelimiter() + LLURI::unescape(mUri);
+ }
+
LLUUID tracking_id = LLLocalBitmapMgr::getInstance()->addUnit(img_file);
if (tracking_id.notNull() && mLoadIntoTexturePipe)
{
diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h
index c231443a9e..53dee98cd1 100644
--- a/indra/newview/gltf/buffer_util.h
+++ b/indra/newview/gltf/buffer_util.h
@@ -141,6 +141,42 @@ namespace LL
}
template<>
+ inline void copyScalar<U32, LLVector4a>(U32* src, LLVector4a& dst)
+ {
+ dst.set((F32)*src, 0.f, 0.f, 0.f);
+ }
+
+ template<>
+ inline void copyScalar<U16, LLVector4a>(U16* src, LLVector4a& dst)
+ {
+ dst.set((F32)*src, 0.f, 0.f, 0.f);
+ }
+
+ template<>
+ inline void copyScalar<U8, LLVector4a>(U8* src, LLVector4a& dst)
+ {
+ dst.set((F32)*src, 0.f, 0.f, 0.f);
+ }
+
+ template<>
+ inline void copyScalar<U32, LLVector2>(U32* src, LLVector2& dst)
+ {
+ dst.set((F32)*src, 0.f);
+ }
+
+ template<>
+ inline void copyScalar<U16, LLVector2>(U16* src, LLVector2& dst)
+ {
+ dst.set((F32)*src, 0.f);
+ }
+
+ template<>
+ inline void copyScalar<U8, LLVector2>(U8* src, LLVector2& dst)
+ {
+ dst.set((F32)*src, 0.f);
+ }
+
+ template<>
inline void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst)
{
dst.set(src[0], src[1]);
@@ -221,6 +257,12 @@ namespace LL
}
template<>
+ inline void copyVec4<U32, LLVector4a>(U32* src, LLVector4a& dst)
+ {
+ dst.set((F32)src[0], (F32)src[1], (F32)src[2], (F32)src[3]);
+ }
+
+ template<>
inline void copyVec4<U16, LLVector4a>(U16* src, LLVector4a& dst)
{
dst.set(src[0], src[1], src[2], src[3]);
@@ -373,7 +415,7 @@ namespace LL
}
else
{
- LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL;
+ LL_ERRS("GLTF") << "Unsupported accessor type " << (S32)accessor.mType << LL_ENDL;
}
}
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 3a1d8079a9..5a94a2c6c6 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -440,7 +440,25 @@ void LLGLTFLoader::processNodeHierarchy(S32 node_idx, std::map<std::string, S32>
(LLModel::NO_ERRORS == pModel->getStatus()) &&
validate_model(pModel))
{
- mTransform.setIdentity();
+ // Build the scene transform.
+ // Non-skinned meshes: scene transform carries coord rotation + hierarchy,
+ // preserving the object's rotation/position/scale for upload.
+ // Skinned meshes: transform is already baked into vertices, so scene is identity.
+ if (node.mSkin >= 0)
+ {
+ mTransform.setIdentity();
+ }
+ else
+ {
+ glm::mat4 hierarchy_transform;
+ computeCombinedNodeTransform(mGLTFAsset, node_idx, hierarchy_transform);
+ glm::mat4 combined = coord_system_rotation * hierarchy_transform;
+ if (mApplyXYRotation)
+ {
+ combined = coord_system_rotationxy * combined;
+ }
+ mTransform = LLMatrix4(glm::value_ptr(combined));
+ }
transformation = mTransform;
// adjust the transformation to compensate for mesh normalization
@@ -684,7 +702,12 @@ std::string LLGLTFLoader::processTexture(std::string& full_path_out, S32 texture
// Process embedded textures
if (image.mBufferView >= 0)
{
- return extractTextureToTempFile(texture_index, texture_type);
+ std::string temp_path = extractTextureToTempFile(texture_index, texture_type);
+ if (!temp_path.empty())
+ {
+ full_path_out = temp_path;
+ }
+ return temp_path;
}
return "";
@@ -734,23 +757,47 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas
S32 skinIdx = nodeno.mSkin;
- // Compute final combined transform matrix (hierarchy + coordinate rotation)
+ // Compute the vertex transform for this mesh.
+ // Non-skinned meshes: vertices are left untransformed; the node's hierarchy transform
+ // (rotation, translation, scale) is stored in the scene transform instead, matching
+ // the DAE loader. This ensures the uploaded object's bounding box and transform
+ // properties are correct. See: https://github.com/secondlife/viewer/issues/5431
+ // Skinned meshes: coord rotation + hierarchy are baked into vertex positions because
+ // inverse bind matrices and skin weights are already computed in that space.
+ // TODO: consider aligning skinned meshes with the DAE loader (scene transform instead
+ // of vertex baking), which would require adjusting inverse bind matrices, bind shape
+ // matrix, and weight keying to match.
S32 node_index = static_cast<S32>(&nodeno - &mGLTFAsset.mNodes[0]);
glm::mat4 hierarchy_transform;
computeCombinedNodeTransform(mGLTFAsset, node_index, hierarchy_transform);
- // Combine transforms: coordinate rotation applied to hierarchy transform
- glm::mat4 final_transform = coord_system_rotation * hierarchy_transform;
- if (mApplyXYRotation)
+ glm::mat4 vertex_transform;
+ if (skinIdx >= 0)
{
- final_transform = coord_system_rotationxy * final_transform;
+ // Skinned mesh: bake coord rotation + hierarchy into vertices.
+ // Inverse bind matrices and skin weights depend on this transform being applied.
+ vertex_transform = coord_system_rotation * hierarchy_transform;
+ if (mApplyXYRotation)
+ {
+ vertex_transform = coord_system_rotationxy * vertex_transform;
+ }
+ }
+ else
+ {
+ // Non-skinned mesh: don't apply any transform to vertices.
+ // The hierarchy transform will be stored in the scene transform matrix.
+ vertex_transform = glm::mat4(1.0f); // identity
}
// Check if we have a negative scale (flipped coordinate system)
- bool hasNegativeScale = glm::determinant(final_transform) < 0.0f;
+ // coord_system_rotation and coord_system_rotationxy are pure rotations (det=1),
+ // so negative scale depends only on the hierarchy transform.
+ bool hasNegativeScale = glm::determinant(hierarchy_transform) < 0.0f;
+
+ bool hasVertexTransform = (vertex_transform != glm::mat4(1.0f));
// Pre-compute normal transform matrix (transpose of inverse of upper-left 3x3)
- const glm::mat3 normal_transform = glm::transpose(glm::inverse(glm::mat3(final_transform)));
+ const glm::mat3 normal_transform = glm::transpose(glm::inverse(glm::mat3(vertex_transform)));
// Mark unsuported joints with '-1' so that they won't get added into weights
// GLTF maps all joints onto all meshes. Gather use count per mesh to cut unused ones.
@@ -803,30 +850,49 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas
return false; // Skip this primitive
}
- // Apply the global scale and center offset to all vertices
+ // Apply vertex transform (if any) to all vertices.
+ // Skinned meshes: this bakes coord rotation + hierarchy into vertices.
+ // Non-skinned meshes: vertex_transform is identity (no baking).
for (U32 i = 0; i < prim.getVertexCount(); i++)
{
- // Use pre-computed final_transform
- glm::vec4 pos(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2], 1.0f);
- glm::vec4 transformed_pos = final_transform * pos;
-
GLTFVertex vert;
- vert.position = glm::vec3(transformed_pos);
- if (!prim.mNormals.empty())
+ if (hasVertexTransform)
{
- // Use pre-computed normal_transform
- glm::vec3 normal_vec(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]);
- vert.normal = glm::normalize(normal_transform * normal_vec);
+ glm::vec4 pos(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2], 1.0f);
+ glm::vec4 transformed_pos = vertex_transform * pos;
+ vert.position = glm::vec3(transformed_pos);
+
+ if (!prim.mNormals.empty())
+ {
+ glm::vec3 normal_vec(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]);
+ vert.normal = glm::normalize(normal_transform * normal_vec);
+ }
+ else
+ {
+ vert.normal = glm::normalize(normal_transform * glm::vec3(0.0f, 0.0f, 1.0f));
+ LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL;
+ }
}
else
{
- // Use default normal (pointing up in model space)
- vert.normal = glm::normalize(normal_transform * glm::vec3(0.0f, 0.0f, 1.0f));
- LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL;
+ // No transform: store raw GLTF positions and normals.
+ // The scene transform will carry coord rotation + hierarchy.
+ vert.position = glm::vec3(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2]);
+
+ if (!prim.mNormals.empty())
+ {
+ vert.normal = glm::vec3(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]);
+ }
+ else
+ {
+ vert.normal = glm::vec3(0.0f, 0.0f, 1.0f);
+ LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL;
+ }
}
- vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], -prim.mTexCoords0[i][1]);
+ // Flip texture V coordinate
+ vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], 1.f - prim.mTexCoords0[i][1]);
if (skinIdx >= 0)
{
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 07ed0d0824..cf12be91c3 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -865,9 +865,6 @@ Delete "$INSTDIR\trial\*.html"
Delete "$INSTDIR\newview.exe"
Delete "$INSTDIR\SecondLife.exe"
-# MAINT-3099 workaround - prevent these log files, if present, from causing a user alert
-Delete "$INSTDIR\VivoxVoiceService-*.log"
-
# Remove entire help directory
RMDir /r "$INSTDIR\help"
diff --git a/indra/newview/licenses-linux.txt b/indra/newview/licenses-linux.txt
index e83989b4a7..d443bd3385 100644
--- a/indra/newview/licenses-linux.txt
+++ b/indra/newview/licenses-linux.txt
@@ -196,50 +196,6 @@ Redistribution and use in source and binary forms, with or
Cass Everitt - cass@r3.nu
-================
-OpenJPEG License
-================
-
-/*
- * The copyright in this software is being made available under the 2-clauses
- * BSD License, included below. This software may be subject to other third
- * party and contributor rights, including patent rights, and no such rights
- * are granted under this license.
- *
- * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
- * Copyright (c) 2002-2014, Professor Benoit Macq
- * Copyright (c) 2003-2014, Antonin Descampe
- * Copyright (c) 2003-2009, Francois-Olivier Devaux
- * Copyright (c) 2005, Herve Drolon, FreeImage Team
- * Copyright (c) 2002-2003, Yannick Verschueren
- * Copyright (c) 2001-2003, David Janssens
- * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
- * Copyright (c) 2012, CS Systemes d'Information, France
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
===============
OpenSSL License
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index b1336f1bc4..39c81da447 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -575,51 +575,6 @@ supporting the PNG file format in commercial products. If you use this
source code in a product, acknowledgment is not required but would be
appreciated.
-*************************************************************
-*************************************************************
-
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 1999-2000 by authors.
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-*************************************************************
-*************************************************************
-
-Internet Software Consortium code
-
-/* This is from the BIND 4.9.4 release, modified to compile by itself */
-/* Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
=============
meshoptimizer
=============
diff --git a/indra/newview/linux_tools/megapahit.desktop b/indra/newview/linux_tools/megapahit.desktop
index 091df71e11..69c9fcda49 100755
--- a/indra/newview/linux_tools/megapahit.desktop
+++ b/indra/newview/linux_tools/megapahit.desktop
@@ -7,4 +7,3 @@ Terminal=false
Type=Application
Categories=Network;
StartupNotify=true
-X-Desktop-File-Install-Version=3.0"
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index aa620625ea..75a9ef58fc 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -430,6 +430,7 @@ LLAgent::LLAgent() :
mIsDoNotDisturb(false),
mControlFlags(0x00000000),
+ mLastJumpInputTime(0.0),
mAutoPilot(false),
mAutoPilotFlyOnStop(false),
@@ -784,6 +785,10 @@ void LLAgent::moveUp(S32 direction)
if (direction > 0)
{
+ if (!getFlying())
+ {
+ mLastJumpInputTime = LLTimer::getTotalSeconds();
+ }
setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP);
}
else if (direction < 0)
@@ -2118,6 +2123,13 @@ std::ostream& operator<<(std::ostream &s, const LLAgent &agent)
//-----------------------------------------------------------------------------
bool LLAgent::needsRenderAvatar()
{
+ // OTS mode: always render avatar — we are in third-person even though
+ // mouselook input is active.
+ if (gAgentCamera.cameraOTS())
+ {
+ return mShowAvatar && mOutfitChosen;
+ }
+
if (gAgentCamera.cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson)
{
return false;
@@ -2129,6 +2141,11 @@ bool LLAgent::needsRenderAvatar()
// true if we need to render your own avatar's head.
bool LLAgent::needsRenderHead()
{
+ // OTS mode: always render head — avatar is fully visible.
+ if (gAgentCamera.cameraOTS())
+ {
+ return mShowAvatar;
+ }
return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !gAgentCamera.cameraMouselook());
}
@@ -2242,7 +2259,8 @@ void LLAgent::endAnimationUpdateUI()
}
// clean up UI from mode we're leaving
- if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_MOUSELOOK )
+ if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_MOUSELOOK
+ || gAgentCamera.getLastCameraMode() == CAMERA_MODE_OTS)
{
gToolBarView->setToolBarsVisible(true);
// show mouse cursor
@@ -2364,7 +2382,8 @@ void LLAgent::endAnimationUpdateUI()
//---------------------------------------------------------------------
// Set up UI for mode we're entering
//---------------------------------------------------------------------
- if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK
+ || gAgentCamera.getCameraMode() == CAMERA_MODE_OTS)
{
// clean up UI
// first show anything hidden by UI toggle
@@ -2677,7 +2696,21 @@ void LLAgent::onAnimStop(const LLUUID& id)
}
else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND)
{
- setControlFlags(AGENT_CONTROL_FINISH_ANIM);
+ // FIRE-34049/FIRE-34273/https://github.com/secondlife/viewer/issues/4218
+ // Avoid forcing AGENT_CONTROL_FINISH_ANIM, which can short-circuit the next pre-jump
+ // during rapid successive jumps.
+ // TODO: a more robust fix would require knowing which specific animation finished,
+ // information that is not currently provided by the simulator.
+ const bool up_pos = (mControlFlags & AGENT_CONTROL_UP_POS) != 0;
+ const F64 now = LLTimer::getTotalSeconds();
+ const F64 elapsed = now - mLastJumpInputTime;
+ static LLCachedControl<F32> recent_jump_threshold_secs(gSavedSettings, "RecentJumpThresholdSecs");
+ const bool recent_jump = (mLastJumpInputTime > 0.0) && (elapsed < recent_jump_threshold_secs);
+
+ if (!up_pos && !recent_jump)
+ {
+ setControlFlags(AGENT_CONTROL_FINISH_ANIM);
+ }
}
}
@@ -4864,6 +4897,8 @@ const std::string& LLAgent::getTeleportStateName() const
void LLAgent::parseTeleportMessages(const std::string& xml_filename)
{
+ LL_PROFILE_ZONE_SCOPED;
+
LLXMLNodePtr root;
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index f5d928a1be..ddaa8dd68c 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -500,6 +500,7 @@ private:
S32 mControlsTakenCount[TOTAL_CONTROLS];
S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS];
U32 mControlFlags; // Replacement for the mFooKey's
+ F64 mLastJumpInputTime; // Time of last jump input (key-down) in seconds from LLTimer::getTotalSeconds()
//--------------------------------------------------------------------
// Animations
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index b6d31c0cae..6f9f8bfa2a 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -975,6 +975,10 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM);
}
}
+ else
+ {
+ new_distance = llmin(new_distance, getCameraMaxZoomDistance());
+ }
mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
}
@@ -1035,6 +1039,10 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters)
new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM);
}
}
+ else
+ {
+ new_distance = llmin(new_distance, getCameraMaxZoomDistance());
+ }
// Compute new camera offset
mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
@@ -1168,7 +1176,7 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
LLVector3 headLookAxis;
LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance());
- if (cameraMouselook())
+ if (cameraMouselook() || cameraOTS())
{
lookAtType = LOOKAT_TARGET_MOUSELOOK;
}
@@ -1401,7 +1409,7 @@ void LLAgentCamera::updateCamera()
gAgent.setShowAvatar(true);
}
- if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK))
+ if (isAgentAvatarValid() && mCameraMode != CAMERA_MODE_MOUSELOOK)
{
gAgentAvatarp->updateAttachmentVisibility(mCameraMode);
}
@@ -1489,7 +1497,8 @@ void LLAgentCamera::updateCamera()
}
gAgent.setLastPositionGlobal(global_pos);
- if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook())
+ // Exclude OTS — shoulder camera position must not be overridden by head-tracking.
+ if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook() && !cameraOTS())
{
LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() +
LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +
@@ -1590,6 +1599,19 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()
mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus());
return mFocusTargetGlobal;
}
+ else if (mCameraMode == CAMERA_MODE_OTS)
+ {
+ // Focus in front of avatar at aim height
+ static LLCachedControl<F32> ots_focus_dist(gSavedSettings, "OTSFocusDistance", 10.0f);
+ static LLCachedControl<F32> ots_height(gSavedSettings, "OTSCameraHeight", 0.5f);
+ static LLCachedControl<F32> ots_side(gSavedSettings, "OTSCameraSide", -0.5f);
+ LLVector3 focus_local((F32)ots_focus_dist, (F32)ots_side * 0.3f, (F32)ots_height * 0.5f);
+ LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion();
+ LLVector3 focus_world = focus_local * agent_rot;
+ LLVector3d avatar_pos = gAgent.getPosGlobalFromAgent(getAvatarRootPosition());
+ mFocusTargetGlobal = avatar_pos + LLVector3d(focus_world);
+ return mFocusTargetGlobal;
+ }
else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
{
LLVector3d at_axis(1.0, 0.0, 0.0);
@@ -1768,6 +1790,18 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(bool *hit_limit)
{
camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition());
}
+ else if (mCameraMode == CAMERA_MODE_OTS)
+ {
+ // Shoulder offset camera — avatar-local space: X=forward, Y=left, Z=up
+ static LLCachedControl<F32> ots_dist(gSavedSettings, "OTSCameraDistance", 3.0f);
+ static LLCachedControl<F32> ots_side(gSavedSettings, "OTSCameraSide", -0.5f);
+ static LLCachedControl<F32> ots_height(gSavedSettings, "OTSCameraHeight", 0.5f);
+ LLVector3 local_offset(-(F32)ots_dist, (F32)ots_side, (F32)ots_height);
+ LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion();
+ LLVector3 world_offset = local_offset * agent_rot;
+ LLVector3d avatar_pos = gAgent.getPosGlobalFromAgent(getAvatarRootPosition());
+ camera_position_global = avatar_pos + LLVector3d(world_offset);
+ }
else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
{
if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull())
@@ -2236,6 +2270,58 @@ void LLAgentCamera::changeCameraToDefault()
//-----------------------------------------------------------------------------
+// changeCameraToOTS()
+// Over-the-shoulder aim mode.
+// Calls changeCameraToMouselook() to inherit ALL of its input setup
+// (cursor hiding, mouse capture, control flags, focus management),
+// then immediately overrides mCameraMode to CAMERA_MODE_OTS so that
+// calcCameraPositionTargetGlobal places the camera at the shoulder offset
+// instead of the avatar's eye position.
+// Avatar rendering is handled explicitly in needsRenderAvatar() and needsRenderHead().
+//-----------------------------------------------------------------------------
+void LLAgentCamera::changeCameraToOTS()
+{
+ if (mCameraMode != CAMERA_MODE_OTS)
+ {
+ // Inherit everything from mouselook: cursor lock, mouse capture,
+ // AGENT_CONTROL_MOUSELOOK flag, keyboard focus clear, etc.
+ changeCameraToMouselook(false);
+
+ // Override mCameraMode to OTS so position/focus calculations
+ // use the shoulder offset instead of the eye position.
+ mCameraMode = CAMERA_MODE_OTS;
+
+ // changeCameraToMouselook hid attachments via updateAttachmentVisibility
+ // with CAMERA_MODE_MOUSELOOK. Restore full visibility for OTS mode.
+ if (isAgentAvatarValid())
+ {
+ gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+ }
+
+ // Start the camera animation LAST, after mCameraMode is OTS and after
+ // changeCameraToMouselook(false) has cleared mCameraAnimating via its
+ // animate=false branch. The rendered camera is still at the old
+ // (third-person) position this frame, so startCameraAnimation snapshots
+ // that as the start point and updateCamera lerps to the OTS shoulder
+ // target over ZoomTime seconds — matching the mouselook transition feel.
+ startCameraAnimation();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// changeCameraFromOTS()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::changeCameraFromOTS()
+{
+ if (mCameraMode == CAMERA_MODE_OTS)
+ {
+ // changeCameraToDefault handles clearing AGENT_CONTROL_MOUSELOOK,
+ // showing the cursor, and restoring the normal camera mode.
+ changeCameraToDefault();
+ }
+}
+
+//-----------------------------------------------------------------------------
// changeCameraToFollow()
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToFollow(bool animate)
@@ -2328,7 +2414,7 @@ void LLAgentCamera::changeCameraToThirdPerson(bool animate)
}
mCameraLag.clearVec();
- if (mCameraMode == CAMERA_MODE_MOUSELOOK)
+ if (mCameraMode == CAMERA_MODE_MOUSELOOK || mCameraMode == CAMERA_MODE_OTS)
{
mCurrentCameraDistance = MIN_CAMERA_DISTANCE;
mTargetCameraDistance = MIN_CAMERA_DISTANCE;
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index d277fd6158..ac1a36a6c2 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -43,7 +43,8 @@ enum ECameraMode
CAMERA_MODE_THIRD_PERSON,
CAMERA_MODE_MOUSELOOK,
CAMERA_MODE_CUSTOMIZE_AVATAR,
- CAMERA_MODE_FOLLOW
+ CAMERA_MODE_FOLLOW,
+ CAMERA_MODE_OTS // Over-the-shoulder: mouselook input + third-person camera
};
/** Camera Presets for CAMERA_MODE_THIRD_PERSON */
@@ -93,10 +94,14 @@ public:
void changeCameraToThirdPerson(bool animate = true);
void changeCameraToCustomizeAvatar(); // Trigger transition animation
void changeCameraToFollow(bool animate = true); // Ventrella
+ void changeCameraToOTS(); // Over-the-shoulder aim mode
+ void changeCameraFromOTS(); // Exit OTS back to third person
bool cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); }
- bool cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); }
+ // Also true for OTS — reuses mouselook input and UI behaviour; camera position handled separately.
+ bool cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK) || mCameraMode == CAMERA_MODE_OTS; }
bool cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); }
bool cameraFollow() const { return (mCameraMode == CAMERA_MODE_FOLLOW && mLastCameraMode == CAMERA_MODE_FOLLOW); }
+ bool cameraOTS() const { return mCameraMode == CAMERA_MODE_OTS; }
ECameraMode getCameraMode() const { return mCameraMode; }
ECameraMode getLastCameraMode() const { return mLastCameraMode; }
void updateCamera(); // Call once per frame to update camera location/orientation
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index 5ddb87558a..73368c1bcc 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -43,6 +43,7 @@
#include "llviewernetwork.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
+#include "llviewerjointattachment.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "llsdutil.h"
@@ -195,6 +196,12 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
&LLAgentListener::getNearbyObjectsList,
llsd::map("reply", LLSD()));
+ add("getAttachedObjectsList",
+ "Return attached objects list with information about each object\n"
+ "reply contains \"attachments\" result key",
+ &LLAgentListener::getAttachedObjectsList,
+ llsd::map("reply", LLSD()));
+
add("getAgentScreenPos",
"Return screen position of the [\"avatar_id\"] avatar or own avatar if not specified\n"
"reply contains \"x\", \"y\" coordinates and \"onscreen\" flag to indicate if it's actually in within the current window\n"
@@ -772,6 +779,41 @@ void LLAgentListener::getNearbyObjectsList(LLSD const& event_data)
}
}
+void LLAgentListener::getAttachedObjectsList(LLSD const& event_data)
+{
+ Response response(LLSD(), event_data);
+ response["attachments"] = LLSD::emptyArray();
+
+ if (!isAgentAvatarValid())
+ {
+ return;
+ }
+
+ for (const auto& [attachment_point_index, attachment_point] : gAgentAvatarp->mAttachmentPoints)
+ {
+ if (!attachment_point)
+ {
+ continue;
+ }
+
+ for (const auto& attachment_object_ptr : attachment_point->mAttachedObjects)
+ {
+ if (LLViewerObject* attachment_object = attachment_object_ptr.get())
+ {
+ response["attachments"].append(llsd::map(
+ "object_id", attachment_object->getID(),
+ "inventory_item_id", attachment_object->getAttachmentItemID(),
+ "name", attachment_object->getAttachmentItemName(),
+ "attachment_point", attachment_point->getName(),
+ "attachment_point_index", attachment_point_index,
+ "position", ll_sd_from_vector3(attachment_object->getPosition()),
+ "rotation", ll_sd_from_quaternion(attachment_object->getRotation()),
+ "is_temporary", attachment_object->isTempAttachment()));
+ }
+ }
+ }
+}
+
void LLAgentListener::getAgentScreenPos(LLSD const& event_data)
{
Response response(LLSD(), event_data);
diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h
index b5bea8c0bd..031fc75e46 100644
--- a/indra/newview/llagentlistener.h
+++ b/indra/newview/llagentlistener.h
@@ -68,6 +68,7 @@ private:
void getID(LLSD const& event_data);
void getNearbyAvatarsList(LLSD const& event_data);
void getNearbyObjectsList(LLSD const& event_data);
+ void getAttachedObjectsList(LLSD const& event_data);
void getAgentScreenPos(LLSD const& event_data);
LLViewerObject * findObjectClosestTo( const LLVector3 & position, bool sit_target = false ) const;
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 9c76f56ef3..f67f2688a1 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -1019,6 +1019,9 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
}
//-------------------------------------------------------------------------
+U32 AISUpdate::sBatchFrameCount = 0;
+LLTimer AISUpdate::sBatchTimer;
+
AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body)
: mType(type)
{
@@ -1036,8 +1039,16 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD&
mFetchDepth = request_body["depth"].asInteger();
}
- mTimer.setTimerExpirySec(AIS_EXPIRY_SECONDS);
- mTimer.start();
+ mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS);
+ mTaskTimer.start();
+
+ U32 current_frame = LLFrameTimer::getFrameCount();
+ if (sBatchFrameCount != current_frame)
+ {
+ sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS);
+ sBatchTimer.start();
+ sBatchFrameCount = current_frame;
+ }
parseUpdate(update);
}
@@ -1058,7 +1069,7 @@ void AISUpdate::clearParseResults()
void AISUpdate::checkTimeout()
{
- if (mTimer.hasExpired())
+ if (mTaskTimer.hasExpired() || sBatchTimer.hasExpired())
{
// If we are taking too long, don't starve other tasks,
// yield to mainloop.
@@ -1067,7 +1078,16 @@ void AISUpdate::checkTimeout()
// a chance, so wait for a frame tick instead.
llcoro::suspendUntilNextFrame();
LLCoros::checkStop();
- mTimer.setTimerExpirySec(AIS_EXPIRY_SECONDS);
+ mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS);
+
+ U32 current_frame = LLFrameTimer::getFrameCount();
+ if (sBatchFrameCount != current_frame)
+ {
+ // To give other tasks a chance batch timer
+ // has a longer delay.
+ sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS);
+ sBatchFrameCount = current_frame;
+ }
}
}
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index cfc286da2e..1dab0dd1f9 100644
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -130,9 +130,13 @@ private:
void clearParseResults();
void checkTimeout();
- // Fetch can return large packets of data, throttle it to not cause lags
- // Todo: make throttle work over all fetch requests isntead of per-request
- const F32 AIS_EXPIRY_SECONDS = 0.008f;
+ // Fetches can return large packets of data,
+ // throttle them individually to not get stuck
+ // on a single large task. And throttle sum total
+ // to not cause lags when multiple large fetches
+ // returned results.
+ const F32 AIS_TASK_EXPIRY_SECONDS = 0.008f;
+ const F32 AIS_BATCH_EXPIRY_SECONDS = 0.010f;
typedef std::map<LLUUID,size_t> uuid_int_map_t;
uuid_int_map_t mCatDescendentDeltas;
@@ -154,7 +158,9 @@ private:
uuid_list_t mCategoryIds;
bool mFetch;
S32 mFetchDepth;
- LLTimer mTimer;
+ LLTimer mTaskTimer;
+ static LLTimer sBatchTimer;
+ static U32 sBatchFrameCount;
AISAPI::COMMAND_TYPE mType;
};
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index f3265afebd..ece18fb5cc 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -144,6 +144,8 @@ LLAppCoreHttp::~LLAppCoreHttp()
void LLAppCoreHttp::init()
{
+ LL_PROFILE_ZONE_SCOPED;
+
LLCoreHttpUtil::setPropertyMethods(
std::bind(&LLControlGroup::getBOOL, std::ref(gSavedSettings), std::placeholders::_1),
std::bind(&LLControlGroup::declareBOOL, std::ref(gSavedSettings), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, LLControlVariable::PERSIST_NONDFT));
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 0b3d0355a2..d3aac5a43e 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -395,11 +395,13 @@ struct AttachmentInfo
- (void)sendEvent:(NSEvent *)event
{
+ startWatchdog("sendEvent"); // events are outside pumpMainLoop
[super sendEvent:event];
if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand))
{
[[self keyWindow] sendEvent:event];
}
+ stopWatchdog(); // leaving scope
}
@end
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 614d9fdeb1..9636db21c1 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -703,12 +703,12 @@ public:
void onFetchCompletion();
bool isFetchCompleted();
bool isTimedOut();
+ bool pollStopped();
void checkMissingWearables();
bool pollMissingWearables();
bool isMissingCompleted();
void recoverMissingWearable(LLWearableType::EType type);
- void clearCOFLinksForMissingWearables();
void onWearableAssetFetch(LLViewerWearable *wearable);
void onAllComplete();
@@ -717,7 +717,6 @@ public:
found_list_t& getFoundList();
void eraseTypeToLink(LLWearableType::EType type);
void eraseTypeToRecover(LLWearableType::EType type);
- void setObjItems(const LLInventoryModel::item_array_t& items);
void setGestItems(const LLInventoryModel::item_array_t& items);
bool isMostRecent();
void handleLateArrivals();
@@ -727,7 +726,6 @@ public:
private:
found_list_t mFoundList;
- LLInventoryModel::item_array_t mObjItems;
LLInventoryModel::item_array_t mGestItems;
typedef std::set<S32> type_set_t;
type_set_t mTypesToRecover;
@@ -804,11 +802,6 @@ void LLWearableHoldingPattern::eraseTypeToRecover(LLWearableType::EType type)
mTypesToRecover.erase(type);
}
-void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items)
-{
- mObjItems = items;
-}
-
void LLWearableHoldingPattern::setGestItems(const LLInventoryModel::item_array_t& items)
{
mGestItems = items;
@@ -914,55 +907,10 @@ void LLWearableHoldingPattern::onAllComplete()
if (isAgentAvatarValid())
{
- LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.size() << " attachments" << LL_ENDL;
- LLAgentWearables::llvo_vec_t objects_to_remove;
- LLAgentWearables::llvo_vec_t objects_to_retain;
- LLInventoryModel::item_array_t items_to_add;
-
- LLAgentWearables::findAttachmentsAddRemoveInfo(mObjItems,
- objects_to_remove,
- objects_to_retain,
- items_to_add);
-
- LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size()
- << " attachments" << LL_ENDL;
-
- // Here we remove the attachment pos overrides for *all*
- // attachments, even those that are not being removed. This is
- // needed to get joint positions all slammed down to their
- // pre-attachment states.
- gAgentAvatarp->clearAttachmentOverrides();
-
- if (objects_to_remove.size() || items_to_add.size())
- {
- LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size()
- << " and add " << items_to_add.size() << " items" << LL_ENDL;
- }
-
- // Take off the attachments that will no longer be in the outfit.
- LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove);
-
// Update wearables.
LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with "
<< mResolved << " wearable items " << LL_ENDL;
LLAppearanceMgr::instance().updateAgentWearables(this);
-
- // Restore attachment pos overrides for the attachments that
- // are remaining in the outfit.
- for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin();
- it != objects_to_retain.end();
- ++it)
- {
- LLViewerObject *objectp = *it;
- if (!objectp->isAnimatedObject())
- {
- gAgentAvatarp->addAttachmentOverridesForObject(objectp);
- }
- }
-
- // Add new attachments to match those requested.
- LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL;
- LLAgentWearables::userAttachMultipleAttachments(items_to_add);
}
if (isFetchCompleted() && isMissingCompleted())
@@ -1000,6 +948,10 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
{
// runway skip here?
LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
+
+ // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
+ doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollStopped, this));
+ return true;
}
bool completed = isFetchCompleted();
@@ -1070,6 +1022,9 @@ void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLView
{
// runway skip here?
LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
+
+ // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
+ return;
}
LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL;
@@ -1120,18 +1075,15 @@ bool LLWearableHoldingPattern::isMissingCompleted()
return mTypesToLink.size()==0 && mTypesToRecover.size()==0;
}
-void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
+bool LLWearableHoldingPattern::pollStopped()
{
- for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it)
+ // We have to keep on polling until we're sure that all callbacks have completed or they'll cause a crash
+ if (isFetchCompleted() && isMissingCompleted())
{
- LLFoundData &data = *it;
- if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
- {
- // Wearable link that was never resolved; remove links to it from COF
- LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
- LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID);
- }
+ delete this;
+ return true;
}
+ return false;
}
bool LLWearableHoldingPattern::pollMissingWearables()
@@ -1140,6 +1092,10 @@ bool LLWearableHoldingPattern::pollMissingWearables()
{
// runway skip here?
LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
+
+ // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
+ doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollStopped, this));
+ return true;
}
bool timed_out = isTimedOut();
@@ -1164,14 +1120,6 @@ bool LLWearableHoldingPattern::pollMissingWearables()
gAgentAvatarp->debugWearablesLoaded();
- // BAP - if we don't call clearCOFLinksForMissingWearables()
- // here, we won't have to add the link back in later if the
- // wearable arrives late. This is to avoid corruption of
- // wearable ordering info. Also has the effect of making
- // unworn item links visible in the COF under some
- // circumstances.
-
- //clearCOFLinksForMissingWearables();
onAllComplete();
}
return done;
@@ -1218,13 +1166,6 @@ void LLWearableHoldingPattern::handleLateArrivals()
replaced_types.insert(data.mWearableType);
- // BAP - if we didn't call
- // clearCOFLinksForMissingWearables() earlier, we
- // don't need to restore the link here. Fixes
- // wearable ordering problems.
-
- // LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false);
-
// BAP failing this means inventory or asset server
// are corrupted in a way we don't handle.
llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType));
@@ -2143,15 +2084,23 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn
// Keep the last N wearables of each type. For viewer 2.0, N is 1 for
// both body parts and clothing items.
void LLAppearanceMgr::filterWearableItems(
- LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total)
+ LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total, bool skip_bodyparts)
{
// Restrict by max total items first.
if ((max_total > 0) && (items.size() > max_total))
{
- LLInventoryModel::item_array_t items_to_keep;
- for (S32 i=0; i<max_total; i++)
+ LLInventoryModel::item_array_t items_to_keep; size_t non_body_kept = 0;
+ for (const auto& item : items)
{
- items_to_keep.push_back(items[i]);
+ if (skip_bodyparts && item.get() && item.get()->getType() == LLAssetType::AT_BODYPART)
+ {
+ items_to_keep.push_back(item);
+ }
+ else if (non_body_kept < max_total)
+ {
+ items_to_keep.push_back(item);
+ non_body_kept++;
+ }
}
items = items_to_keep;
}
@@ -2636,6 +2585,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
remove_non_link_items(wear_items);
remove_non_link_items(obj_items);
remove_non_link_items(gest_items);
+ // Since we're following folder links we might have picked up new duplicates, or exceeded MAX_CLOTHING_LAYERS
+ removeDuplicateItems(wear_items);
+ removeDuplicateItems(obj_items);
+ removeDuplicateItems(gest_items);
+ filterWearableItems(wear_items, 0, LLAgentWearables::MAX_CLOTHING_LAYERS, true);
dumpItemArray(wear_items,"asset_dump: wear_item");
dumpItemArray(obj_items,"asset_dump: obj_item");
@@ -2647,6 +2601,77 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
<< " descendent_count " << cof->getDescendentCount()
<< " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL;
}
+
+ // Update attachments to match those requested.
+ if (isAgentAvatarValid())
+ {
+ // Include attachments which should be in COF but don't have their link created yet
+ std::set<LLUUID> pendingAttachments;
+ LLAttachmentsMgr::instance().getPendingAttachments(pendingAttachments);
+ for (const LLUUID& idAttachItem : pendingAttachments)
+ {
+ if ( !gAgentAvatarp->isWearingAttachment(idAttachItem) || isLinkedInCOF(idAttachItem) )
+ {
+ LLAttachmentsMgr::instance().clearPendingAttachmentLink(idAttachItem);
+ continue;
+ }
+
+ if (LLViewerInventoryItem* pAttachItem = gInventory.getItem(idAttachItem))
+ {
+ obj_items.push_back(pAttachItem);
+ }
+ }
+
+ LL_DEBUGS("Avatar") << self_av_string() << "Updating " << obj_items.size() << " attachments" << LL_ENDL;
+ LLAgentWearables::llvo_vec_t objects_to_remove;
+ LLAgentWearables::llvo_vec_t objects_to_retain;
+ LLInventoryModel::item_array_t items_to_add;
+
+ LLAgentWearables::findAttachmentsAddRemoveInfo(obj_items,
+ objects_to_remove,
+ objects_to_retain,
+ items_to_add);
+
+ LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size()
+ << " attachments" << LL_ENDL;
+
+ // Here we remove the attachment pos overrides for *all*
+ // attachments, even those that are not being removed. This is
+ // needed to get joint positions all slammed down to their
+ // pre-attachment states.
+ gAgentAvatarp->clearAttachmentOverrides();
+
+ if (objects_to_remove.size() || items_to_add.size())
+ {
+ LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size()
+ << " and add " << items_to_add.size() << " items" << LL_ENDL;
+ }
+
+ // Take off the attachments that will no longer be in the outfit.
+ // (don't remove attachments until avatar is fully loaded - reduces random attaching/detaching/reattaching at log-on)
+ if (gAgentAvatarp->isFullyLoaded())
+ {
+ LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove);
+ }
+
+ // Restore attachment pos overrides for the attachments that
+ // are remaining in the outfit.
+ for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin();
+ it != objects_to_retain.end();
+ ++it)
+ {
+ LLViewerObject *objectp = *it;
+ if (!objectp->isAnimatedObject())
+ {
+ gAgentAvatarp->addAttachmentOverridesForObject(objectp);
+ }
+ }
+
+ // Add new attachments to match those requested.
+ LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL;
+ LLAgentWearables::userAttachMultipleAttachments(items_to_add);
+ }
+
if(!wear_items.size())
{
LLNotificationsUtil::add("CouldNotPutOnOutfit");
@@ -2661,7 +2686,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
LLTimer hp_block_timer;
LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
- holder->setObjItems(obj_items);
holder->setGestItems(gest_items);
// Note: can't do normal iteration, because if all the
@@ -4203,6 +4227,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nul
continue;
}
removeCOFItemLinks(linked_item_id, cb);
+ LLAttachmentsMgr::instance().clearPendingAttachmentLink(linked_item_id);
addDoomedTempAttachment(linked_item_id);
}
}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 131b6817ed..9d90be0004 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -151,6 +151,7 @@ public:
// Attachment link management
void unregisterAttachment(const LLUUID& item_id);
void registerAttachment(const LLUUID& item_id);
+ bool getAttachmentInvLinkEnable() const { return mAttachmentInvLinkEnabled; }
void setAttachmentInvLinkEnable(bool val);
// Add COF link to individual item.
@@ -249,7 +250,7 @@ private:
private:
- void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total);
+ void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total, bool skip_bodyparts = false);
void getDescendentsOfAssetType(const LLUUID& category,
LLInventoryModel::item_array_t& items,
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 1db62f2fab..f0df9537fc 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -136,10 +136,12 @@
#include "stringize.h"
#include "llcoros.h"
#include "llexception.h"
-#if !_M_ARM64 // !LL_LINUX
+#if defined(LL_CEF)
#include "cef/dullahan_version.h"
+#endif
+#if defined(LL_VLC)
#include "vlc/libvlc_version.h"
-#endif // LL_LINUX
+#endif
#if LL_DARWIN
#if LL_SDL
@@ -154,6 +156,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <boost/throw_exception.hpp>
+#include <chrono>
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in processMarkerFiles
@@ -361,9 +364,6 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
S32 gPendingMetricsUploads = 0;
-
-bool gDisconnected = false;
-
// Used to restore texture state after a mode switch
LLFrameTimer gRestoreGLTimer;
bool gRestoreGL = false;
@@ -398,6 +398,7 @@ const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
+const std::string WATCHDOG_MARKER_FILE_NAME("SecondLife.watchdog_marker");
static std::string gLaunchFileOnQuit;
//----------------------------------------------------------------------------
@@ -758,6 +759,8 @@ public:
bool LLAppViewer::init()
{
+ LL_PROFILE_ZONE_SCOPED;
+
setupErrorHandling(mSecondInstance);
//
@@ -959,6 +962,7 @@ bool LLAppViewer::init()
// Early out from user choice.
LL_WARNS("InitInfo") << "initHardwareTest() failed." << LL_ENDL;
// quit immediately
+ LL_PROFILER_FRAME_END;
return false;
}
LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
@@ -977,12 +981,14 @@ bool LLAppViewer::init()
OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK);
LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL;
// quit immediately
+ LL_PROFILER_FRAME_END;
return false;
}
LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
// Initialize event recorder
LLViewerEventRecorder::createInstance();
+ LLWatchdog::createInstance();
//
// Initialize the window
@@ -1012,6 +1018,7 @@ bool LLAppViewer::init()
// Already handled with a MBVideoDrvErr
LL_WARNS("InitInfo") << "gGLManager.mHasRequirements is false." << LL_ENDL;
// quit immediately
+ LL_PROFILER_FRAME_END;
return false;
}
@@ -1025,6 +1032,7 @@ bool LLAppViewer::init()
OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK);
LL_WARNS("InitInfo") << "SSE2 is not supported" << LL_ENDL;
// quit immediately
+ LL_PROFILER_FRAME_END;
return false;
}
#endif
@@ -1244,7 +1252,7 @@ bool LLAppViewer::init()
gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath());
}
#endif
-
+ LL_PROFILER_FRAME_END;
return true;
}
@@ -1309,7 +1317,11 @@ bool LLAppViewer::frame()
{
try
{
+ const auto start = std::chrono::steady_clock::now();
ret = doFrame();
+ const auto end = std::chrono::steady_clock::now();
+ const U64 doframe_time_us = (U64)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
+ LLTrace::sample(LLStatViewer::DOFRAME_TIME_US, doframe_time_us);
}
catch (const LLContinueError&)
{
@@ -2201,6 +2213,8 @@ bool LLAppViewer::cleanup()
// deleteSingleton() methods.
LLSingletonBase::deleteAll();
+ LLUICtrlFactory::deleteSingleton();
+
LLSplashScreen::hide();
LL_INFOS() << "Goodbye!" << LL_ENDL;
@@ -2224,6 +2238,8 @@ void LLAppViewer::initGeneralThread()
bool LLAppViewer::initThreads()
{
+ LL_PROFILE_ZONE_SCOPED;
+
static const bool enable_threads = true;
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
@@ -2503,7 +2519,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
}
- if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
+ // Be softer for files in the user's folders, user can't just reinstall those
+ bool error_when_no_comment = !set_defaults && location_key != "User";
+
+ if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent, error_when_no_comment))
{ // success!
LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;
}
@@ -3033,14 +3052,20 @@ bool LLAppViewer::initConfiguration()
if (mSecondInstance)
{
- // This is the second instance of SL. Mute voice,
- // but make sure the setting is *not* persisted.
- // Also see LLVivoxVoiceClient::voiceEnabled()
+ // This is the second concurrent instance of SL.
+ // Disable voice for this session only, user should
+ // be able to enable voice manually, after that it
+ // works the same way as on primary instance.
LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
- if (enable_voice)
+ if (enable_voice && enable_voice->getValue().asBoolean())
{
+ LL_DEBUGS("AppInit") << "Disabling voice for this session only" << LL_ENDL;
+ // Will be saved as mValues[2] which does not get written to the file.
+ // This feels like a hack, but otherwise way too many controls have to
+ // be tracked manually instead of using xmls' control_name.
const bool DO_NOT_PERSIST = false;
- enable_voice->setValue(LLSD(false), DO_NOT_PERSIST);
+ LLSD::Boolean new_value = false;
+ enable_voice->setValue(new_value, DO_NOT_PERSIST);
}
}
@@ -3068,6 +3093,8 @@ bool LLAppViewer::initConfiguration()
// keeps growing, necessitating a method all its own.
void LLAppViewer::initStrings()
{
+ LL_PROFILE_ZONE_SCOPED;
+
std::string strings_file = "strings.xml";
std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
@@ -3157,6 +3184,7 @@ void LLAppViewer::sendOutOfDiskSpaceNotification()
bool LLAppViewer::initWindow()
{
+ LL_PROFILE_ZONE_SCOPED;
LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
// store setting in a global for easy access and modification
@@ -3210,20 +3238,60 @@ bool LLAppViewer::initWindow()
<< " (setting = " << watchdog_enabled_setting << ")"
<< LL_ENDL;
- if (use_watchdog)
+ // Watchdog reports to statistics via marker files, that is
+ // pointless without ability to write (!mSecondInstance) those files.
+ // If use_watchdog is set, watchdog also reports to bugspat.
+ if (use_watchdog || !mSecondInstance)
{
- LLWatchdog::getInstance()->init([]()
- {
- LLAppViewer* app = LLAppViewer::instance();
- if (app->logoutRequestSent())
+ LLWatchdog::getInstance()->init(
+ [](bool final_marker)
{
- app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
- }
- else
+ LLAppViewer* app = LLAppViewer::instance();
+ // Without watchdog everything will be counted as
+ // either 'unknown' (no crash marker) or based of present crash marker
+ if (final_marker)
+ {
+ // watchdog is going to crash viewer, so crate a 'crash' marker
+ if (app->logoutRequestSent())
+ {
+ app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
+ }
+ else
+ {
+ app->createErrorMarker(LAST_EXEC_FROZE);
+ }
+ }
+ else
+ {
+ // not going to crash, just create a 'watchdog' marker
+ app->createWatchdogMarker();
+ }
+ },
+ []()
{
- app->createErrorMarker(LAST_EXEC_FROZE);
- }
- });
+ LLAppViewer* app = LLAppViewer::instance();
+ // in case process recovered from freeze, remove watchdog marker.
+ app->removeWatchdogMarker();
+ },
+ [](std::string &desc)
+ {
+#if LL_WINDOWS && LL_BUGSPLAT
+ LLAppViewer* app = LLAppViewer::instance();
+ app->writeDebugInfo();
+ return app->reportCustomToBugsplat(desc);
+#else
+ return false;
+#endif
+ },
+ []()
+ {
+ LLAppViewer* app = LLAppViewer::instance();
+ app->sendLogoutRequest();
+ // Might be better to ask user if user wants to terminate the app or wait.
+ OSMessageBox(LLTrans::getString("MBFreezeDetected"), LLTrans::getString("MBFatalError"), OSMB_OK);
+ },
+ use_watchdog);
+
}
LLNotificationsUI::LLNotificationManager::getInstance();
@@ -3351,7 +3419,7 @@ LLSD LLAppViewer::getViewerInfo() const
url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (!LLStringUtil::endsWith(url, "/"))
url += "/";
- url += LLURI::escape(versionInfo.getVersion()) + ".html";
+ url += "#" + LLURI::escape(versionInfo.getVersion()); // + ".html";
}
info["VIEWER_RELEASE_NOTES_URL"] = url;
@@ -3464,7 +3532,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
}
-#if !_M_ARM64 // !LL_LINUX
+#if defined(LL_CEF)
std::ostringstream cef_ver_codec;
cef_ver_codec << "Dullahan: ";
cef_ver_codec << DULLAHAN_VERSION_MAJOR;
@@ -3494,7 +3562,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["LIBCEF_VERSION"] = "Undefined";
#endif
-#if !_M_ARM64 // !LL_LINUX
+#if defined(LL_VLC)
std::ostringstream vlc_ver_codec;
vlc_ver_codec << LIBVLC_VERSION_MAJOR;
vlc_ver_codec << ".";
@@ -3997,13 +4065,8 @@ void LLAppViewer::processMarkerFiles()
{
// the file existed, is ours, and matched our version, so we can report on what it says
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed or froze" << LL_ENDL;
-#if LL_WINDOWS && LL_BUGSPLAT
- // bugsplat will set correct state in bugsplatSendLog
- // Might be more accurate to rename this one into 'unknown'
+ // App terminated unexpectedly or froze, we don't know the cause yet.
gLastExecEvent = LAST_EXEC_UNKNOWN;
-#else
- gLastExecEvent = LAST_EXEC_OTHER_CRASH;
-#endif // LL_WINDOWS
}
else
@@ -4056,23 +4119,29 @@ void LLAppViewer::processMarkerFiles()
}
LLAPRFile::remove(logout_marker_file);
}
- // and last refine based on whether or not a marker created during a non-llerr crash is found
+ // Refine based on whether or not a marker created during
+ // a crash is found or if wathdog caught a freeze.
+ // Bugsplat will set correct state in bugsplatSendLog.
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
+ std::string watchdog_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, WATCHDOG_MARKER_FILE_NAME);
if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
{
S32 marker_code = getMarkerErrorCode(error_marker_file);
if (marker_code >= 0)
{
- if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
- {
- gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
- LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
- }
- else if (marker_code > 0 && marker_code < (S32)LAST_EXEC_COUNT)
+ if (marker_code > 0 && marker_code < (S32)LAST_EXEC_COUNT)
{
+ // If we have a code, it takes precendence
gLastExecEvent = (eLastExecEvent)marker_code;
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
}
+ // if we have the marker, even without a code, it's a crash.
+ else if (gLastExecEvent == LAST_EXEC_LOGOUT_UNKNOWN
+ || gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "Error marker '" << error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
+ }
else
{
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
@@ -4084,6 +4153,33 @@ void LLAppViewer::processMarkerFiles()
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(error_marker_file);
+ if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
+ {
+ // If viewer crashed after a freeze was detected,
+ // crash still takes precendence. Just clear watchdog.
+ removeWatchdogMarker();
+ }
+ }
+ else
+ {
+ // so only check watchdog marker if there is no error marker.
+ if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
+ {
+ if (LAST_EXEC_UNKNOWN == gLastExecEvent
+ || LAST_EXEC_LOGOUT_UNKNOWN == gLastExecEvent)
+ {
+ // watchdog marker gets created if we detect a freeze,
+ // so if viwer did not stop gracefully, and we know it wasn't a crash,
+ // we have no other info, check watchdog.
+ if (markerIsSameVersion(watchdog_marker_file))
+ {
+ gLastExecEvent = LAST_EXEC_UNKNOWN == gLastExecEvent ? LAST_EXEC_FROZE : LAST_EXEC_LOGOUT_FROZE;
+ LL_INFOS("MarkerFile") << "Watchdog marker '" << watchdog_marker_file << "' found, setting LastExecEvent to FROZE"
+ << LL_ENDL;
+ }
+ }
+ removeWatchdogMarker();
+ }
}
#if LL_DARWIN
@@ -4128,6 +4224,7 @@ void LLAppViewer::removeMarkerFiles()
{
LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
}
+ removeWatchdogMarker();
}
else
{
@@ -4389,6 +4486,7 @@ U32 LLAppViewer::getObjectCacheVersion()
bool LLAppViewer::initCache()
{
+ LL_PROFILE_ZONE_SCOPED;
mPurgeCache = false;
bool read_only = mSecondInstance;
LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
@@ -4482,19 +4580,22 @@ bool LLAppViewer::initCache()
if (mPurgeCache)
{
- LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
- purgeCache();
+ LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
+ purgeCache();
// clear the new C++ file system based cache
LLDiskCache::getInstance()->clearCache();
- }
- else
+ }
+ else if (gSavedSettings.getBOOL("PurgeDiskCacheOnStartup"))
{
// purge excessive files from the new file system based cache
LLDiskCache::getInstance()->purge();
}
+
+ // Start disk cache purge thread to
+ // purge excessive files from the file system based cache
+ LLAppViewer::getPurgeDiskCacheThread()->start();
}
- LLAppViewer::getPurgeDiskCacheThread()->start();
LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
@@ -4537,15 +4638,69 @@ void LLAppViewer::loadKeyBindings()
// As per GHI #4498, remove old, stale CEF cache folders from previous sessions
void LLAppViewer::purgeCefStaleCaches()
{
+ LL_PROFILE_ZONE_SCOPED;
// TODO: we really shouldn't use a hard coded name for the cache folder here...
const std::string browser_parent_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache");
- if (LLFile::isdir(browser_parent_cache))
+ if (!LLFile::isdir(browser_parent_cache))
+ {
+ return;
+ }
+ // We are using a fixed name to not leave stale folders
+ // around in case something goes wrong on startup.
+ const std::string holder_cache_name = browser_parent_cache + "_rename";
+
+ // Try to rename the entire directory first
+ if (LLFile::rename(browser_parent_cache, holder_cache_name) == 0)
+ {
+ LL_DEBUGS("AppInit") << "Successfully renamed CEF cache folder for deletion" << LL_ENDL;
+ }
+ else
+ {
+ // Rename failed (likely another instance has files open in the cache)
+ // Create holder folder and move individual subfolders instead
+ LL_DEBUGS("AppInit") << "Could not rename CEF cache folder (may be in use), moving individual folders" << LL_ENDL;
+
+ if (!LLFile::isdir(holder_cache_name) && LLFile::mkdir(holder_cache_name) != 0)
+ {
+ LL_WARNS() << "Failed to create holder folder: " << holder_cache_name << LL_ENDL;
+ // Attept normal cleanup
+ gDirUtilp->deleteDirAndContents(browser_parent_cache);
+ return;
+ }
+
+ // Iterate through subdirectories in the cache folder
+ LLDirIterator dir_iter(browser_parent_cache, "*");
+ std::string subfolder_name;
+ while (dir_iter.next(subfolder_name))
+ {
+ if (subfolder_name == "." || subfolder_name == "..")
+ {
+ continue;
+ }
+
+ std::string source_path = browser_parent_cache + gDirUtilp->getDirDelimiter() + subfolder_name;
+ std::string dest_path = holder_cache_name + gDirUtilp->getDirDelimiter() + subfolder_name;
+
+ // If folder is in use, move will fail, don't delete it.
+ LLFile::rename(source_path, dest_path);
+ }
+ }
+
+ // Post deletion task to the General work queue to avoid blocking the main thread
+ if (auto queue = LL::WorkQueue::getInstance("General"))
+ {
+ // Alternatively throw it at LLPurgeDiskCacheThread to clean
+ // it during periodic purges.
+ queue->post([holder_cache_name]()
+ {
+ LL_PROFILE_ZONE_NAMED("cef_cache_cleanup");
+ gDirUtilp->deleteDirAndContents(holder_cache_name);
+ });
+ }
+ else
{
- // This is a sledgehammer approach - nukes the cef_cache dir entirely
- // which is then recreated the first time a CEF instance creates an
- // individual cache folder. If we ever decide to retain some folders
- // e.g. Search UI cache - then we will need a more granular approach.
- gDirUtilp->deleteDirAndContents(browser_parent_cache);
+ LL_WARNS() << "Failed to get General work queue, deleting CEF cache synchronously" << LL_ENDL;
+ gDirUtilp->deleteDirAndContents(holder_cache_name);
}
}
@@ -4564,7 +4719,19 @@ void LLAppViewer::purgeCacheImmediate()
{
LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL;
LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false);
- LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true);
+ if (LLVOCache::instanceExists())
+ {
+ LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true);
+ }
+ else if (!mSecondInstance)
+ {
+ // LLVOCache requires parameters to be initialized, if it's not there, try manually
+ std::string mask = "*";
+ std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "objectcache");
+ LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL;
+ gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
+ LLFile::rmdir(cache_dir);
+ }
}
std::string LLAppViewer::getSecondLifeTitle() const
@@ -4732,6 +4899,8 @@ std::string get_name_cache_filename(const std::string &base_file, const std::str
void LLAppViewer::loadNameCache()
{
+ LL_PROFILE_ZONE_SCOPED;
+
// display names cache
std::string filename = get_name_cache_filename("avatar_name_cache", "xml");
LL_INFOS("AvNameCache") << filename << LL_ENDL;
@@ -5496,6 +5665,30 @@ bool LLAppViewer::errorMarkerExists() const
return LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB);
}
+void LLAppViewer::createWatchdogMarker() const
+{
+ if (!mSecondInstance)
+ {
+ std::string error_marker = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, WATCHDOG_MARKER_FILE_NAME);
+
+ LLAPRFile file;
+ file.open(error_marker, LL_APR_WB);
+ if (file.getFileHandle())
+ {
+ recordMarkerVersion(file);
+ file.close();
+ }
+ }
+}
+void LLAppViewer::removeWatchdogMarker() const
+{
+ if (!mSecondInstance)
+ {
+ std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, WATCHDOG_MARKER_FILE_NAME);
+ LLFile::remove(error_marker_file);
+ }
+}
+
void LLAppViewer::outOfMemorySoftQuit()
{
if (!mQuitRequested)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index cbe8be7741..d76e5015e9 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -254,6 +254,9 @@ public:
void createErrorMarker(eLastExecEvent error_code) const;
bool errorMarkerExists() const;
+ void createWatchdogMarker() const;
+ void removeWatchdogMarker() const;
+
// Attempt a 'soft' quit with disconnect and saving of settings/cache.
// Intended to be thread safe.
// Good chance of viewer crashing either way, but better than alternatives.
@@ -421,8 +424,6 @@ extern S32 gPendingMetricsUploads;
extern F32 gSimLastTime;
extern F32 gSimFrames;
-extern bool gDisconnected;
-
extern LLFrameTimer gRestoreGLTimer;
extern bool gRestoreGL;
extern bool gUseWireframe;
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 5bbaed750c..728a8ef81e 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -131,16 +131,12 @@ int main( int argc, char **argv )
// install unexpected exception handler
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
-#ifdef __aarch64__
- setenv("LD_PRELOAD", APP_PLUGIN_DIR"/libcef.so", 1);
-#else
# if LL_LINUX
setenv("LD_PRELOAD", "libpthread.so.0 libGL.so.1", 1);
# else
setenv("LD_PRELOAD", "libpthread.so libGL.so.1", 1);
# endif
setenv("__GL_THREADED_OPTIMIZATIONS", "1", 0);
-#endif
bool ok = viewer_app_ptr->init();
if(!ok)
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index b074c40c17..2bd9c8661a 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -135,6 +135,16 @@ void cleanupViewer()
gViewerAppPtr = NULL;
}
+void startWatchdog(std::string_view state)
+{
+ gViewerAppPtr->resumeMainloopTimeout(state);
+}
+
+void stopWatchdog()
+{
+ gViewerAppPtr->pauseMainloopTimeout();
+}
+
void clearDumpLogsDir()
{
if (!LLAppViewer::instance()->isSecondInstance())
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 8c9da7ef28..afff5f2cf2 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -86,6 +86,7 @@
#include "BugSplat.h"
#include "boost/json.hpp" // Boost.Json
#include "llagent.h" // for agent location
+#include "llmemory.h"
#include "llstartup.h"
#include "llviewerregion.h"
#include "llvoavatarself.h" // for agent name
@@ -123,6 +124,7 @@ namespace
// MiniDmpSender pointer. As things stand, though, we must define an
// actual function and store the pointer statically.
static MiniDmpSender *sBugSplatSender = nullptr;
+ static std::string sBugsplatDescriptionField;
bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2)
{
@@ -159,8 +161,21 @@ namespace
WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "settings_per_account.xml")));
}
- // LL_ERRS message, when there is one
- sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage()));
+ if (!sBugsplatDescriptionField.empty())
+ {
+ // Can be set by watchdog or other code that detects a problem
+ // and wants to add some context to the crash report.
+ // Will be visible in the BugSplat web UI.
+ sBugSplatSender->setDefaultUserDescription(WCSTR(sBugsplatDescriptionField));
+ // This type of crash is not necessarily a crash, or final.
+ // Prepare for the next one.
+ sBugsplatDescriptionField.clear();
+ }
+ else
+ {
+ // LL_ERRS message, when there is one
+ sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage()));
+ }
sBugSplatSender->setAttribute(WCSTR(L"OS"), WCSTR(LLOSInfo::instance().getOSStringSimple())); // In case we ever stop using email for this
sBugSplatSender->setAttribute(WCSTR(L"AppState"), WCSTR(LLStartUp::getStartupStateString()));
@@ -171,6 +186,16 @@ namespace
sBugSplatSender->setAttribute(WCSTR(L"VRAM"), WCSTR(STRINGIZE(gGLManager.mVRAM)));
sBugSplatSender->setAttribute(WCSTR(L"RAM"), WCSTR(STRINGIZE(gSysMemory.getPhysicalMemoryKB().value())));
+ const U32 avail_kb = LLMemory::getAvailableMemKB().value();
+ if (avail_kb != U32_MAX) // filter out initial values, if one is not set, all are not set
+ {
+ // Memory usage at crash time (can be 1s obsolete)
+ sBugSplatSender->setAttribute(WCSTR(L"MemAllocatedKB"), WCSTR(std::to_string(LLMemory::getAllocatedMemKB().value())));
+ sBugSplatSender->setAttribute(WCSTR(L"MemAvailableKB"), WCSTR(std::to_string(LLMemory::getAvailableMemKB().value())));
+ sBugSplatSender->setAttribute(WCSTR(L"MemMaxPhysicalKB"), WCSTR(std::to_string(LLMemory::getMaxMemKB().value())));
+ sBugSplatSender->setAttribute(WCSTR(L"MemAvailCommitMB"), WCSTR(std::to_string(LLMemory::getAvailableCommitMemMB().value())));
+ }
+
if (gAgent.getRegion())
{
// region location, when we have it
@@ -183,6 +208,7 @@ namespace
}
LLAppViewer* app = LLAppViewer::instance();
+
if (!app->isSecondInstance() && !app->errorMarkerExists())
{
// If marker doesn't exist, create a marker with 'other' or 'logout' code for next launch
@@ -441,22 +467,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
// commands and exit the process before we do anything else.
if (!velopack_initialize())
{
+ // Obsolete? Always return true
// Velopack handled the invocation (install/uninstall hook)
-
- // Drop install related settings
- gDirUtilp->initAppDirs("SecondLife");
-
- std::string user_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml");
- LLControlGroup settings("global");
- if (settings.loadFromFile(user_settings_path))
- {
- // If user reinstalls or updates, we want to recheck for nsis leftovers.
- if (settings.controlExists("PreviousInstallChecked"))
- {
- settings.setBOOL("PreviousInstallChecked", false);
- }
- settings.saveToFile(user_settings_path, true);
- }
return 0;
}
#endif
@@ -878,6 +890,38 @@ bool LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
return false;
}
+#if defined(LL_BUGSPLAT)
+static int reportCustomToBugsplatFilter(EXCEPTION_POINTERS* pExcepInfo)
+{
+ if (sBugSplatSender)
+ {
+ sBugSplatSender->createReport(pExcepInfo);
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+bool LLAppViewerWin32::reportCustomToBugsplat(const std::string &description)
+{
+#if defined(LL_BUGSPLAT)
+ if (sBugSplatSender)
+ {
+ sBugsplatDescriptionField = description;
+
+ __try
+ {
+ // Generate a custom exception code
+ RaiseException(0xE0000001, 0, 0, NULL);
+ }
+ __except (reportCustomToBugsplatFilter(GetExceptionInformation()))
+ {
+ }
+ return true;
+ }
+#endif // LL_BUGSPLAT
+ return false;
+}
+
bool LLAppViewerWin32::initWindow()
{
// This is a workaround/hotfix for a change in Windows 11 24H2 (and possibly later)
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index 0741758a0c..53177f7f95 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -44,6 +44,7 @@ public:
bool cleanup() override;
bool reportCrashToBugsplat(void* pExcepInfo) override;
+ bool reportCustomToBugsplat(const std::string& description) override;
protected:
bool initWindow() override; // Override to initialize the viewer's window.
diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp
index 73ac895d0d..51df71e4f5 100644
--- a/indra/newview/llattachmentsmgr.cpp
+++ b/indra/newview/llattachmentsmgr.cpp
@@ -42,10 +42,19 @@ const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F;
const F32 MIN_RETRY_REQUEST_TIME = 5.0F;
const F32 MAX_BAD_COF_TIME = 30.0F;
+class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy
+{
+public:
+ void fire(const LLUUID& item_id) override
+ {
+ LLAttachmentsMgr::instance().onRegisterAttachmentComplete(item_id);
+ LLRequestServerAppearanceUpdateOnDestroy::fire(item_id);
+ }
+};
+
LLAttachmentsMgr::LLAttachmentsMgr():
mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME),
- mDetachRequests("detach",MIN_RETRY_REQUEST_TIME),
- mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME)
+ mDetachRequests("detach",MIN_RETRY_REQUEST_TIME)
{
}
@@ -80,6 +89,9 @@ void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id,
void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id)
{
+ if (item_id.isNull())
+ return;
+
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT attachment was requested "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
@@ -113,8 +125,6 @@ void LLAttachmentsMgr::onIdle()
expireOldDetachRequests();
- checkInvalidCOFLinks();
-
spamStatusInfo();
}
@@ -222,6 +232,11 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
{
if (mRecentlyArrivedAttachments.size())
{
+ if (!LLAppearanceMgr::instance().getAttachmentInvLinkEnable())
+ {
+ return;
+ }
+
// One or more attachments have arrived but have not yet been
// processed for COF links
if (mAttachmentRequests.empty())
@@ -268,17 +283,49 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
}
if (ids_to_link.size())
{
- LLPointer<LLInventoryCallback> cb = new LLRequestServerAppearanceUpdateOnDestroy();
- for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin();
- uuid_it != ids_to_link.end(); ++uuid_it)
+ LLPointer<LLInventoryCallback> cb = new LLRegisterAttachmentCallback();
+ for (const LLUUID& id_item: ids_to_link)
{
- LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb);
+ if (std::find(mPendingAttachLinks.begin(), mPendingAttachLinks.end(), id_item) == mPendingAttachLinks.end())
+ {
+ LLAppearanceMgr::instance().addCOFItemLink(id_item, cb);
+ mPendingAttachLinks.insert(id_item);
+ }
}
}
mRecentlyArrivedAttachments.clear();
}
}
+bool LLAttachmentsMgr::getPendingAttachments(std::set<LLUUID>& ids) const
+{
+ ids.clear();
+
+ // Returns the combined set of attachments that are pending link creation and those that currently have an ongoing link creation process.
+ set_union(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end(), mPendingAttachLinks.begin(), mPendingAttachLinks.end(), std::inserter(ids, ids.begin()));
+
+ return !ids.empty();
+}
+
+void LLAttachmentsMgr::clearPendingAttachmentLink(const LLUUID& idItem)
+{
+ mPendingAttachLinks.erase(idItem);
+}
+
+void LLAttachmentsMgr::onRegisterAttachmentComplete(const LLUUID& id_item_link)
+{
+ if (const LLUUID& id_item = gInventory.getLinkedItemID(id_item_link); id_item != id_item_link)
+ {
+ clearPendingAttachmentLink(id_item);
+
+ // It may have been detached already in which case we should remove the COF link
+ if ( isAgentAvatarValid() && !gAgentAvatarp->isWearingAttachment(id_item) )
+ {
+ LLAppearanceMgr::instance().removeCOFItemLinks(id_item);
+ }
+ }
+}
+
LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout):
mOpName(op_name),
mTimeout(timeout)
@@ -407,6 +454,8 @@ void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id)
void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
{
+ clearPendingAttachmentLink(inv_item_id);
+
LLTimer timer;
LLInventoryItem *item = gInventory.getItem(inv_item_id);
if (mDetachRequests.getTime(inv_item_id, timer))
@@ -428,10 +477,6 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
{
LL_DEBUGS("Avatar") << "ATT detach on shutdown for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
}
-
- LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking "
- << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;
- mQuestionableCOFLinks.addTime(inv_item_id);
}
bool LLAttachmentsMgr::isAttachmentStateComplete() const
@@ -440,81 +485,8 @@ bool LLAttachmentsMgr::isAttachmentStateComplete() const
&& mAttachmentRequests.empty()
&& mDetachRequests.empty()
&& mRecentlyArrivedAttachments.empty()
- && mQuestionableCOFLinks.empty();
-}
-
-// Check for attachments that are (a) linked in COF and (b) not
-// attached to the avatar. This is a rotten function to have to
-// include, because it runs the risk of either repeatedly spamming out
-// COF link removals if they're failing for some reason, or getting
-// into a tug of war with some other sequence of events that's in the
-// process of adding the attachment in question. However, it's needed
-// because we have no definitive source of authority for what things
-// are actually supposed to be attached. Scripts, run on the server
-// side, can remove an attachment without our expecting it. If this
-// happens to an attachment that's just been added, then the COF link
-// creation may still be in flight, and we will have to delete the
-// link after it shows up.
-//
-// Note that we only flag items for possible link removal if they have
-// been previously detached. This means that an attachment failure
-// will leave the link in the COF, where it will hopefully resolve
-// correctly on relog.
-//
-// See related: MAINT-5070, MAINT-4409
-//
-void LLAttachmentsMgr::checkInvalidCOFLinks()
-{
- if (!gInventory.isInventoryUsable() || mQuestionableCOFLinks.empty())
- {
- return;
- }
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
- cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
- for (S32 i=0; i<item_array.size(); i++)
- {
- const LLViewerInventoryItem* inv_item = item_array.at(i).get();
- const LLUUID& item_id = inv_item->getLinkedUUID();
- if (inv_item->getType() == LLAssetType::AT_OBJECT)
- {
- LLTimer timer;
- bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer);
- bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id);
- if (is_wearing_attachment && is_flagged_questionable)
- {
- LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "
- << (is_wearing_attachment ? "attached " : "")
- <<"removing flag after "
- << timer.getElapsedTimeF32() << " item "
- << inv_item->getName() << " id " << item_id << LL_ENDL;
- mQuestionableCOFLinks.removeTime(item_id);
- }
- }
- }
-
- for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin();
- it != mQuestionableCOFLinks.end(); )
- {
- LLItemRequestTimes::iterator curr_it = it;
- ++it;
- const LLUUID& item_id = curr_it->first;
- LLViewerInventoryItem *inv_item = gInventory.getItem(item_id);
- if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME)
- {
- if (LLAppearanceMgr::instance().isLinkedInCOF(item_id))
- {
- LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after "
- << curr_it->second.getElapsedTimeF32() << " seconds for "
- << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
- LLAppearanceMgr::instance().removeCOFItemLinks(item_id);
- }
- mQuestionableCOFLinks.erase(curr_it);
- continue;
- }
- }
-}
+ && mPendingAttachLinks.empty();
+ }
void LLAttachmentsMgr::spamStatusInfo()
{
diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h
index de36253339..0f10da1377 100644
--- a/indra/newview/llattachmentsmgr.h
+++ b/indra/newview/llattachmentsmgr.h
@@ -85,10 +85,15 @@ public:
void onDetachRequested(const LLUUID& inv_item_id);
void onDetachCompleted(const LLUUID& inv_item_id);
+ void clearPendingAttachmentLink(const LLUUID& idItem);
+ bool getPendingAttachments(std::set<LLUUID>& ids) const;
bool isAttachmentStateComplete() const;
// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0
void refreshAttachments();
+protected:
+ void onRegisterAttachmentComplete(const LLUUID& id_item_link);
+ friend class LLRegisterAttachmentCallback;
private:
@@ -112,7 +117,6 @@ private:
void linkRecentlyArrivedAttachments();
void expireOldAttachmentRequests();
void expireOldDetachRequests();
- void checkInvalidCOFLinks();
void spamStatusInfo();
// Attachments that we are planning to rez but haven't requested from the server yet.
@@ -127,9 +131,8 @@ private:
// Attachments that have arrived but have not been linked in the COF yet.
std::set<LLUUID> mRecentlyArrivedAttachments;
LLTimer mCOFLinkBatchTimer;
-
- // Attachments that are linked in the COF but may be invalid.
- LLItemRequestTimes mQuestionableCOFLinks;
+ // Attachments that have pending COF link creation
+ std::set<LLUUID> mPendingAttachLinks;
};
#endif
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 6f6b89ea81..c6b17fcb4e 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -29,13 +29,12 @@
#include "llavataractions.h"
-#include "boost/lambda/lambda.hpp" // for lambda::constant
-
#include "llavatarnamecache.h" // IDEVO
#include "llsd.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "roles_constants.h" // for GP_MEMBER_INVITE
+#include "llregionflags.h" // for ESTATE_ACCESS_BANNED_AGENT_ADD
#include "llagent.h"
#include "llappviewer.h" // for gLastVersionChannel
@@ -627,6 +626,34 @@ void LLAvatarActions::ejectAvatar(const LLUUID& id, bool ban_enabled)
}
// static
+void LLAvatarActions::estateKickAvatar(const LLUUID& id)
+{
+ LLAvatarName av_name;
+ LLSD payload;
+ payload["avatar_id"] = id;
+ LLSD args;
+ if (LLAvatarNameCache::get(id, &av_name))
+ {
+ args["EVIL_USER"] = av_name.getCompleteName();
+ }
+ LLNotificationsUtil::add("EstateKickUser", args, payload, handleEstateKickAvatar);
+}
+
+// static
+void LLAvatarActions::estateBanAvatar(const LLUUID& id)
+{
+ LLAvatarName av_name;
+ LLSD payload;
+ payload["avatar_id"] = id;
+ LLSD args;
+ if (LLAvatarNameCache::get(id, &av_name))
+ {
+ args["AVATAR_NAME"] = av_name.getCompleteName();
+ }
+ LLNotificationsUtil::add("EstateBanUser", args, payload, handleEstateBanAvatar);
+}
+
+// static
void LLAvatarActions::freeze(const LLUUID& id)
{
LLSD payload;
@@ -1427,6 +1454,62 @@ bool LLAvatarActions::handleEjectAvatar(const LLSD& notification, const LLSD& re
return false;
}
+bool LLAvatarActions::handleEstateKickAvatar(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("EstateOwnerMessage");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
+ msg->nextBlock("MethodData");
+ msg->addString("Method", "kickestate");
+ msg->addUUID("Invoice", LLUUID::generateNewID());
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", avatar_id.asString());
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+
+bool LLAvatarActions::handleEstateBanAvatar(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("EstateOwnerMessage");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
+ msg->nextBlock("MethodData");
+ msg->addString("Method", "estateaccessdelta");
+ msg->addUUID("Invoice", LLUUID::generateNewID());
+
+ std::string buf;
+ gAgent.getID().toString(buf);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buf);
+
+ buf = llformat("%u", (U32)ESTATE_ACCESS_BANNED_AGENT_ADD);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buf);
+
+ avatar_id.toString(buf);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buf);
+
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+
bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 1f5a42ed22..bc4eb6fa60 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -192,6 +192,10 @@ public:
static void freezeAvatar(const LLUUID& id);
static void ejectAvatar(const LLUUID& id, bool ban_enabled = false);
+
+ static void estateKickAvatar(const LLUUID& id);
+
+ static void estateBanAvatar(const LLUUID& id);
/**
* Kick avatar off grid
*/
@@ -263,6 +267,8 @@ private:
static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
static bool handleFreezeAvatar(const LLSD& notification, const LLSD& response);
static bool handleEjectAvatar(const LLSD& notification, const LLSD& response);
+ static bool handleEstateKickAvatar(const LLSD& notification, const LLSD& response);
+ static bool handleEstateBanAvatar(const LLSD& notification, const LLSD& response);
static bool handleKick(const LLSD& notification, const LLSD& response);
static bool handleFreeze(const LLSD& notification, const LLSD& response);
static bool handleUnfreeze(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index f6bc59c748..409952c496 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -47,7 +47,7 @@ S32 LLAvatarListItem::sLeftPadding = 0;
S32 LLAvatarListItem::sNameRightPadding = 0;
S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT];
-static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(typeid(LLAvatarListItem::Params), "avatar_list_item");
LLAvatarListItem::Params::Params()
: default_style("default_style"),
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 9d9948731f..aa24c69831 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -527,12 +527,28 @@ void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg,
AvatarGroupsReply is automatically sent by the server in response to the
AvatarPropertiesRequest in addition to the AvatarPropertiesReply message.
*/
- LLUUID agent_id;
- LLUUID avatar_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id);
+ LLAvatarGroups avatar_groups;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_groups.agent_id);
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_groups.avatar_id);
+
+ LL_DEBUGS("AvatarProperties") << "Received AvatarGroupsReply for "
+ << avatar_groups.avatar_id << LL_ENDL;
+
+ S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
+ for (S32 i = 0; i < group_count; ++i)
+ {
+ LLAvatarGroups::LLGroupData gd;
+ msg->getU64Fast( _PREHASH_GroupData, _PREHASH_GroupPowers, gd.group_powers, i);
+ msg->getBOOLFast( _PREHASH_GroupData, _PREHASH_AcceptNotices, gd.accept_notices, i);
+ msg->getStringFast( _PREHASH_GroupData, _PREHASH_GroupTitle, gd.group_title, i);
+ msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, gd.group_id, i);
+ msg->getStringFast( _PREHASH_GroupData, _PREHASH_GroupName, gd.group_name, i);
+ msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, gd.group_insignia_id, i);
+ avatar_groups.group_list.push_back(gd);
+ }
- LL_DEBUGS("AvatarProperties") << "Received AvatarGroupsReply for " << avatar_id << LL_ENDL;
+ LLAvatarPropertiesProcessor* self = getInstance();
+ self->notifyObservers(avatar_groups.avatar_id, &avatar_groups, APT_GROUPS);
}
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id, void* data, EAvatarProcessorType type)
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 1592629fca..bfafe780ff 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -55,7 +55,8 @@ enum EAvatarProcessorType
APT_PICK_INFO,
APT_TEXTURES,
APT_CLASSIFIEDS,
- APT_CLASSIFIED_INFO
+ APT_CLASSIFIED_INFO,
+ APT_GROUPS // Group membership list with per-group role titles
};
// legacy data is supposed to match AvatarPropertiesReply,
@@ -117,6 +118,28 @@ struct LLAvatarData::LLGroupData
LLUUID group_insignia_id;
};
+/** Sent by the server automatically alongside AvatarPropertiesReply (UDP).
+ * Contains every group the avatar belongs to, including their selected
+ * role title in each group. The active group is the one whose group_title
+ * matches the avatar's current "Title" NameValue. */
+struct LLAvatarGroups
+{
+ LLUUID agent_id;
+ LLUUID avatar_id;
+
+ struct LLGroupData
+ {
+ U64 group_powers { 0 };
+ bool accept_notices{ false };
+ std::string group_title; // role title the avatar has selected in this group
+ LLUUID group_id;
+ std::string group_name;
+ LLUUID group_insignia_id;
+ };
+ typedef std::list<LLGroupData> group_list_t;
+ group_list_t group_list;
+};
+
struct LLPickData
{
LLUUID agent_id;
diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp
index 89516a8a84..05c882e3f1 100644
--- a/indra/newview/llblocklist.cpp
+++ b/indra/newview/llblocklist.cpp
@@ -48,6 +48,7 @@ LLBlockList::LLBlockList(const Params& p)
LLMuteList::getInstance()->addObserver(this);
mMuteListSize = static_cast<U32>(LLMuteList::getInstance()->getMutes().size());
+ updateNoItemsCommentText();
// Set up context menu.
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -101,8 +102,35 @@ BlockListActionType LLBlockList::getCurrentMuteListActionType()
return type;
}
+void LLBlockList::updateNoItemsCommentText()
+{
+ const LLMuteList* mute_list = LLMuteList::getInstance();
+ if (!mute_list->isLoaded() && !mute_list->isFailed())
+ {
+ setNoItemsCommentText(mLoadingItemsMsg);
+ }
+ else if (mute_list->isFailed())
+ {
+ setNoItemsCommentText(mFailedItemsMsg);
+ }
+ else
+ {
+ updateNoItemsMessage(mNameFilter);
+ }
+}
+
+void LLBlockList::onChange()
+{
+ // Something changed, not sure what so force a refresh.
+ mShouldAddAll = true;
+ mActionType = NONE;
+ updateNoItemsCommentText();
+ setDirty();
+}
+
void LLBlockList::onChangeDetailed(const LLMute &mute)
{
+ updateNoItemsCommentText();
mActionType = getCurrentMuteListActionType();
mCurItemId = mute.mID;
@@ -197,6 +225,7 @@ void LLBlockList::addNewItem(const LLMute* mute)
void LLBlockList::refresh()
{
+ updateNoItemsCommentText();
bool have_filter = !mNameFilter.empty();
// save selection to restore it after list rebuilt
@@ -208,6 +237,8 @@ void LLBlockList::refresh()
clear();
createList();
mShouldAddAll = false;
+ // Full rebuild supersedes any queued incremental action. This ensures list consistency.
+ mActionType = NONE;
}
else
{
@@ -246,7 +277,9 @@ void LLBlockList::refresh()
{
LLBlockedListItem * curItem = dynamic_cast<LLBlockedListItem *> (*it);
if(curItem)
- {
+ {
+ // Refresh item text styling each pass so filtering keeps highlight in sync.
+ curItem->highlightName(mNameFilter);
hideListItem(curItem, findInsensitive(curItem->getName(), mNameFilter));
}
}
diff --git a/indra/newview/llblocklist.h b/indra/newview/llblocklist.h
index 64e8246f43..9266584256 100644
--- a/indra/newview/llblocklist.h
+++ b/indra/newview/llblocklist.h
@@ -58,7 +58,7 @@ public:
LLToggleableMenu* getContextMenu() const { return mContextMenu.get(); }
LLBlockedListItem* getBlockedItem() const;
- virtual void onChange() { }
+ virtual void onChange();
virtual void onChangeDetailed(const LLMute& );
virtual void draw();
@@ -68,6 +68,8 @@ public:
void refresh();
U32 getMuteListSize() { return mMuteListSize; }
+ void setLoadingItemsMsg(const std::string& msg) { mLoadingItemsMsg = msg; updateNoItemsCommentText(); }
+ void setFailedItemsMsg(const std::string& msg) { mFailedItemsMsg = msg; updateNoItemsCommentText(); }
private:
@@ -83,6 +85,7 @@ private:
bool isMenuItemVisible(const LLSD& userdata);
void toggleMute(U32 flags);
void createList();
+ void updateNoItemsCommentText();
BlockListActionType getCurrentMuteListActionType();
@@ -100,6 +103,8 @@ private:
LLMute::EType mCurItemType;
U32 mCurItemFlags;
std::string mPrevNameFilter;
+ std::string mLoadingItemsMsg;
+ std::string mFailedItemsMsg;
};
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 76e308a966..2c9d74ed97 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -680,6 +680,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
LLNotifications::instance().add("RevokedModifyRights",args, payload);
}
}
+ // update modify permissions flags for affected objects
+ LLViewerObject::markObjectsForUpdate(agent_id);
(mBuddyInfo[agent_id])->setRightsFrom(new_rights);
}
}
diff --git a/indra/newview/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h
index 484bd2ef04..acc752588d 100644
--- a/indra/newview/llcapabilityprovider.h
+++ b/indra/newview/llcapabilityprovider.h
@@ -37,12 +37,12 @@
class LLCapabilityProvider
{
public:
- virtual ~LLCapabilityProvider() {}
+ virtual ~LLCapabilityProvider() = default;
/**
* Get a capability URL, given a capability name. Returns empty string if
* no such capability is defined on this provider.
*/
- virtual std::string getCapability(const std::string& name) const = 0;
+ virtual std::string getCapability(std::string_view name) const = 0;
/**
* Get host to which to send that capability request.
*/
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 454991ab83..27e5263967 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -140,6 +140,7 @@ void LLChannelManager::onLoginCompleted()
}
else
{
+ mStartUpToastInited = true;
gViewerWindow->getRootView()->addChild(mStartUpChannel);
// init channel's position and size
diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h
index 4db7f32b10..75b3060e66 100644
--- a/indra/newview/llchannelmanager.h
+++ b/indra/newview/llchannelmanager.h
@@ -104,12 +104,15 @@ public:
*/
static LLNotificationsUI::LLScreenChannel* getNotificationScreenChannel();
+ bool getStartUpToastInited() const { return mStartUpToastInited; }
+
std::vector<ChannelElem>& getChannelList() { return mChannelList;}
private:
LLScreenChannel* createChannel(LLScreenChannelBase::Params& p);
LLScreenChannel* mStartUpChannel;
+ bool mStartUpToastInited{false};
std::vector<ChannelElem> mChannelList;
};
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 47803edc73..6bd15d4b61 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -647,7 +647,7 @@ void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by
for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)
{
- if (clothing_by_type[type].empty())
+ if (!clothing_by_type[type].empty())
continue;
LLWearableType::EType w_type = static_cast<LLWearableType::EType>(type);
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 97d2345778..ce236dec66 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -200,13 +200,14 @@ void LLColorSwatchCtrl::draw()
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
mBorder->setKeyboardFocusHighlight(hasFocus());
- // Draw border
- LLRect border( 0, getRect().getHeight(), getRect().getWidth(), mLabelHeight );
- gl_rect_2d( border, mBorderColor.get(), false );
- LLRect interior = border;
+ LLRect gl_border(0, getRect().getHeight(), getRect().getWidth(), mLabelHeight);
+ LLColor4 gl_border_color = mBorderColor.get();
+ LLRect interior = gl_border;
interior.stretch( -1 );
+ bool show_border_ctrl = true;
+
// Check state
if ( mValid )
{
@@ -239,7 +240,9 @@ void LLColorSwatchCtrl::draw()
{
if (mFallbackImage.notNull())
{
- mFallbackImage->draw(interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), LLColor4::white % alpha);
+ mFallbackImage->draw(interior.mLeft - 1, interior.mBottom - 1, mFallbackImage->getWidth(), mFallbackImage->getHeight(), LLColor4::white % alpha);
+ gl_border_color = LLUIColorTable::instance().getColor("ColorSwatchBorderColorGray").get();
+ show_border_ctrl = false;
}
else
{
@@ -250,6 +253,11 @@ void LLColorSwatchCtrl::draw()
}
}
+ mBorder->setVisible(show_border_ctrl);
+
+ // Draw border
+ gl_rect_2d(gl_border, gl_border_color, false);
+
LLUICtrl::draw();
}
diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp
index 65863f0a5e..e9c6df3ed8 100644
--- a/indra/newview/llconversationloglist.cpp
+++ b/indra/newview/llconversationloglist.cpp
@@ -45,6 +45,7 @@ LLConversationLogList::LLConversationLogList(const Params& p)
mIsDirty(true)
{
LLConversationLog::instance().addObserver(this);
+ LLMuteList::instance().addObserver(this);
// Set up context menu.
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -65,6 +66,15 @@ LLConversationLogList::LLConversationLogList(const Params& p)
}
mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst");
+ LLControlVariable* cntrl_ptr = gSavedSettings.getControl("ShowBlockedConvHistory");
+ if (cntrl_ptr)
+ {
+ mShowBlockedSignal = cntrl_ptr->getCommitSignal()->connect(
+ [this](LLControlVariable* control, const LLSD& value, const LLSD& previous)
+ {
+ setDirty(true);
+ });
+ }
}
LLConversationLogList::~LLConversationLogList()
@@ -74,6 +84,7 @@ LLConversationLogList::~LLConversationLogList()
mContextMenu.get()->die();
}
+ LLMuteList::getInstance()->removeObserver(this);
LLConversationLog::instance().removeObserver(this);
}
@@ -178,6 +189,44 @@ void LLConversationLogList::changed(const LLUUID& session_id, U32 mask)
}
}
+// inherited from LLMuteListObserver
+void LLConversationLogList::onChange()
+{
+}
+
+// inherited from LLMuteListObserver
+void LLConversationLogList::onChangeDetailed(const LLMute& mute)
+{
+ if (isDirty())
+ {
+ // Going to refresh either way.
+ return;
+ }
+
+ static LLCachedControl<bool> show_blocked(gSavedSettings, "ShowBlockedConvHistory", false);
+ if (!show_blocked())
+ {
+ // Check if any conversation in the log has this participant
+ const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations();
+
+ // Note sure if actually need this update. List can be rather large
+ // and rebuilding it on every event can be expensive.
+ // But 'mute' events are also rare, so maybe not a problem.
+ // There also might be a way to react only to relevant changes,
+ // instead of reacting to everything, like ignoring voice only mutes,
+ // which are not relevant for this log by themselves.
+ for (const LLConversation& conversation : conversations)
+ {
+ if (conversation.getParticipantID() == mute.mID)
+ {
+ setDirty(true);
+ break;
+ }
+ }
+ }
+ // else don't need to hide anything
+}
+
void LLConversationLogList::addNewItem(const LLConversation* conversation)
{
LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation);
@@ -207,6 +256,9 @@ void LLConversationLogList::rebuildList()
const std::vector<LLConversation>& conversations = log_instance.getConversations();
std::vector<LLConversation>::const_iterator iter = conversations.begin();
+ LLMuteList* mutes = LLMuteList::getInstance();
+
+ static LLCachedControl<bool> show_blocked(gSavedSettings, "ShowBlockedConvHistory", false);
for (; iter != conversations.end(); ++iter)
{
@@ -214,6 +266,11 @@ void LLConversationLogList::rebuildList()
if (not_found)
continue;
+ if (!show_blocked() && mutes->isMuted(iter->getParticipantID()))
+ {
+ continue;
+ }
+
addNewItem(&*iter);
}
@@ -517,8 +574,8 @@ bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListI
LLStringUtil::toUpper(name1);
LLStringUtil::toUpper(name2);
- bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst");
- if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2)))
+ static LLCachedControl<bool> sort_friends_first(gSavedSettings, "SortFriendsFirst", true);
+ if (sort_friends_first() && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2)))
{
return LLAvatarActions::isFriend(id1);
}
@@ -533,8 +590,8 @@ bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListI
const LLUUID& id1 = conversation1->getConversation()->getParticipantID();
const LLUUID& id2 = conversation2->getConversation()->getParticipantID();
- bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst");
- if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2)))
+ static LLCachedControl<bool> sort_friends_first(gSavedSettings, "SortFriendsFirst", true);
+ if (sort_friends_first() && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2)))
{
return LLAvatarActions::isFriend(id1);
}
diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h
index 6372f6c9a3..39f129c9f1 100644
--- a/indra/newview/llconversationloglist.h
+++ b/indra/newview/llconversationloglist.h
@@ -39,7 +39,7 @@ class LLConversationLogListItem;
* it's always in actual state.
*/
-class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver
+class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver, public LLMuteListObserver
{
LOG_CLASS(LLConversationLogList);
public:
@@ -76,6 +76,12 @@ public:
virtual void changed();
virtual void changed(const LLUUID& session_id, U32 mask);
+ /**
+ * Changes from LLMuteListObserver
+ */
+ virtual void onChange();
+ virtual void onChangeDetailed(const LLMute& mute);
+
private:
void setDirty(bool dirty = true) { mIsDirty = dirty; }
@@ -104,6 +110,8 @@ private:
bool mIsDirty;
bool mIsFriendsOnTop;
std::string mNameFilter;
+
+ boost::signals2::scoped_connection mShowBlockedSignal;
};
/**
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 99d770b6e2..117bfbf64c 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -59,11 +59,18 @@ public:
virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
+ bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
conversation->showVoiceIndicator(conversation
&& status != STATUS_JOINING
&& status != STATUS_LEFT_CHANNEL
- && LLVoiceClient::getInstance()->voiceEnabled()
- && LLVoiceClient::getInstance()->isVoiceWorking());
+ && voice_enabled);
+
+ static bool s_voice_enabled(false);
+ if (s_voice_enabled != voice_enabled)
+ {
+ s_voice_enabled = voice_enabled;
+ conversation->updateConversationIndicators();
+ }
}
private:
@@ -210,6 +217,12 @@ bool LLConversationViewSession::postBuild()
LLFolderViewItem::postBuild();
mItemPanel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance());
+
+ if (!mItemPanel)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Failed to construct mItemPanel from panel_conversation_list_item.xml" << LL_ENDL;
+ }
addChild(mItemPanel);
mCallIconLayoutPanel = mItemPanel->getChild<LLPanel>("call_icon_panel");
@@ -509,11 +522,25 @@ void LLConversationViewSession::refresh()
// Update all speaking indicators
LLSpeakingIndicatorManager::updateSpeakingIndicators();
+ updateConversationIndicators();
+
+ requestArrange();
+ if (vmi)
+ {
+ // Do the regular upstream refresh
+ LLFolderViewFolder::refresh();
+ }
+}
+
+void LLConversationViewSession::updateConversationIndicators()
+{
+ bool is_active_channel = isInActiveVoiceChannel();
+
// we should show indicator for specified voice session only if this is current channel. EXT-5562.
if (mSpeakingIndicator)
{
- mSpeakingIndicator->setIsActiveChannel(mIsInActiveVoiceChannel);
- mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel);
+ mSpeakingIndicator->setIsActiveChannel(is_active_channel);
+ mSpeakingIndicator->setShowParticipantsSpeaking(is_active_channel);
}
LLConversationViewParticipant* participant = NULL;
@@ -523,16 +550,9 @@ void LLConversationViewSession::refresh()
participant = dynamic_cast<LLConversationViewParticipant*>(*iter);
if (participant)
{
- participant->allowSpeakingIndicator(mIsInActiveVoiceChannel);
+ participant->allowSpeakingIndicator(is_active_channel);
}
}
-
- requestArrange();
- if (vmi)
- {
- // Do the regular upstream refresh
- LLFolderViewFolder::refresh();
- }
}
void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id)
@@ -543,7 +563,7 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi
{
bool old_value = mIsInActiveVoiceChannel;
mIsInActiveVoiceChannel = vmi->getUUID() == session_id;
- mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel && !LLVoiceChannel::isSuspended());
+ mCallIconLayoutPanel->setVisible(isInActiveVoiceChannel() && !LLVoiceChannel::isSuspended());
if (old_value != mIsInActiveVoiceChannel)
{
refresh();
@@ -567,6 +587,13 @@ bool LLConversationViewSession::highlightFriendTitle(LLConversationItem* vmi)
return false;
}
+bool LLConversationViewSession::isInActiveVoiceChannel()
+{
+ return mIsInActiveVoiceChannel &&
+ LLVoiceClient::getInstance()->voiceEnabled() &&
+ LLVoiceClient::getInstance()->isVoiceWorking();
+}
+
//
// Implementation of conversations list participant (avatar) widgets
//
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index a6d240ed84..5844041127 100644
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -94,7 +94,8 @@ public:
void setHighlightState(bool hihglight_state);
LLFloater* getSessionFloater();
- bool isInActiveVoiceChannel() { return mIsInActiveVoiceChannel; }
+ bool isInActiveVoiceChannel();
+ void updateConversationIndicators();
bool highlightFriendTitle(LLConversationItem* vmi);
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index 53da9826ed..246a9d28e4 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -38,7 +38,6 @@
#include "llappviewer.h"
#include "llsceneview.h"
#include "llviewertexture.h"
-#include "llfloaterreg.h"
#include "llscenemonitor.h"
//
// Globals
@@ -53,7 +52,6 @@ static LLDefaultChildRegistry::Register<LLDebugView> r("debug_view");
LLDebugView::LLDebugView(const LLDebugView::Params& p)
: LLView(p),
- mFastTimerView(NULL),
mDebugConsolep(NULL),
mFloaterSnapRegion(NULL)
{}
@@ -89,8 +87,6 @@ void LLDebugView::init()
r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
(S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
- mFastTimerView = dynamic_cast<LLFastTimerView*>(LLFloaterReg::getInstance("block_timers"));
-
gSceneView = new LLSceneView(r);
gSceneView->setFollowsTop();
gSceneView->setFollowsLeft();
@@ -105,7 +101,7 @@ void LLDebugView::init()
addChild(gSceneMonitorView);
gSceneMonitorView->setRect(rect);
- r.set(150, rect.getHeight() - 60, 820, 110);
+ r.set(150, rect.getHeight() - 60, 835, 110);
LLTextureView::Params tvp;
tvp.name("gTextureView");
tvp.rect(r);
diff --git a/indra/newview/lldebugview.h b/indra/newview/lldebugview.h
index 8fa2acc3c9..ca274d6f91 100644
--- a/indra/newview/lldebugview.h
+++ b/indra/newview/lldebugview.h
@@ -59,7 +59,6 @@ public:
void setStatsVisible(bool visible);
- LLFastTimerView* mFastTimerView;
LLConsole* mDebugConsolep;
LLView* mFloaterSnapRegion;
};
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 322ee90541..da9378ad12 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -723,9 +723,13 @@ F32 LLDrawable::updateXform(bool undamped)
mXform.setRotation(target_rot);
mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
mXform.updateMatrix();
- if (isRoot() && mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
+ if (isRoot() && mVObjp->isAnimatedObject())
{
- mVObjp->getControlAvatar()->matchVolumeTransform();
+ LLControlAvatar* cav = mVObjp->getControlAvatar();
+ if (cav)
+ {
+ cav->matchVolumeTransform();
+ }
}
if (mSpatialBridge)
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index bc45734e66..9d1b11880b 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -267,7 +267,7 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)
gGL.setColorMask(true, false);
- if (!rigged)
+ if (!rigged && getType() == LLDrawPoolAlpha::POOL_ALPHA_POST_WATER)
{ //render "highlight alpha" on final non-rigged pass
// NOTE -- hacky call here protected by !rigged instead of alongside "forwardRender"
// so renderDebugAlpha is executed while gls_pipeline_alpha and depth GL state
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 7a974fe857..3cb5ad6f28 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -205,22 +205,22 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
if (tex_a && (!tex_b || (tex_a == tex_b)))
{
- shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
tex_a->setFilteringOption(filter_mode);
+ shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
blend_factor = 0; // only one tex provided, no blending
}
else if (tex_b && !tex_a)
{
- shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_b);
tex_b->setFilteringOption(filter_mode);
+ shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_b);
blend_factor = 0; // only one tex provided, no blending
}
else if (tex_b != tex_a)
{
- shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
tex_a->setFilteringOption(filter_mode);
- shader->bindTexture(LLViewerShaderMgr::BUMP_MAP2, tex_b);
tex_b->setFilteringOption(filter_mode);
+ shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
+ shader->bindTexture(LLViewerShaderMgr::BUMP_MAP2, tex_b);
}
shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask);
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index f1b46f0533..9eddec55c5 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -73,9 +73,9 @@ namespace Details
// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
// This means we attempt to recover relatively quickly but back off giving more time to recover
// until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
- constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout.
- constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout.
- constexpr S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules.
+ constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS = 1.f;
+ constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 3.f;
+ constexpr S32 MAX_EVENT_POLL_ERRORS = 15; // ~5 minutes, by the above rules.
constexpr F64 MIN_SECONDS_PASSED = 10.0; // Minimum time we expect the server to hold the request.
int LLEventPollImpl::sNextCounter = 1;
@@ -238,23 +238,26 @@ namespace Details
}
else if (!status.isHttpStatus())
{
- /// Some LLCore or LIBCurl error was returned. This is unlikely to be recoverable
- LL_WARNS("LLEventPollImpl") << "<" << counter << "> Critical error from poll request returned from libraries. Canceling coroutine." << LL_ENDL;
- break;
+ // Some LLCore or LIBCurl error was returned.
+ LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error from poll request returned from libraries. " << status.toTerseString() << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+ << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;
}
- LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
- << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;
- if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS)
+ if (errorCount < MAX_EVENT_POLL_ERRORS)
{ // An unanticipated error has been received from our poll
// request. Calculate a timeout and wait for it to expire(sleep)
- // before trying again. The sleep time is increased by 5 seconds
+ // before trying again. The sleep time is increased by 3 seconds
// for each consecutive error.
- ++errorCount;
F32 waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS
+ errorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC;
+ ++errorCount;
+
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Retrying in " << waitToRetry <<
" seconds, error count is now " << errorCount << LL_ENDL;
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 5c46eb9d80..41ae47b645 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -52,7 +52,7 @@ public:
return copy;
}
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
{
// more label always spans width of text box
if (num_chars == 0)
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index d2b862eb58..20cc89b7bd 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1071,6 +1071,91 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
return true;
}
+F32 dot_product(const LLVector3& a, const LLVector3& b)
+{
+ return a.mV[VX] * b.mV[VX] + a.mV[VY] * b.mV[VY] + a.mV[VZ] * b.mV[VZ];
+}
+
+bool LLFace::calcAlignedPlanarGLTF(
+ const LLFace* align_to,
+ LLVector2* res_st_offset,
+ LLVector2* res_st_scale,
+ F32* res_st_rot,
+ S32 gltf_info_index) const
+{
+ if (!align_to)
+ {
+ return false;
+ }
+
+ const LLTextureEntry* orig_tep = align_to->getTextureEntry();
+ const LLTextureEntry* tep = getTextureEntry();
+ if (!orig_tep || !tep)
+ {
+ return false;
+ }
+
+ // Only support planar mapping for now
+ if (orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR ||
+ tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)
+ {
+ return false;
+ }
+
+ LLGLTFMaterial* orig_mat = orig_tep->getGLTFRenderMaterial();
+ LLGLTFMaterial* this_mat = tep->getGLTFRenderMaterial();
+ if (!orig_mat || !this_mat)
+ {
+ return false;
+ }
+
+ // Get the original GLTF transform for the specified channel
+ const auto& orig_tt = orig_mat->mTextureTransform[gltf_info_index];
+
+ // Convert GLTF transform to legacy TE transform
+ F32 map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot;
+ LLGLTFMaterial::convertPBRTransformToTexture(
+ orig_tt.mScale,
+ orig_tt.mOffset,
+ orig_tt.mRotation,
+ map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot);
+
+ // Calculate aligments
+ LLVector3 orig_pos, this_pos;
+ LLQuaternion orig_face_rot, this_face_rot;
+ F32 orig_proj_scale, this_proj_scale;
+ align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale);
+ getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale);
+
+ // The rotation of "this face's" texture:
+ LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot;
+ LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot;
+ F32 x_ang, y_ang, z_ang;
+ this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang);
+
+ // Offset and scale of "this face's" texture:
+ LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot;
+ LLVector3 st_scale(map_scaleS, map_scaleT, 1.f);
+ st_scale *= orig_proj_scale;
+ centers_dist.scaleVec(st_scale);
+ LLVector2 orig_st_offset(map_offsS, map_offsT);
+
+ LLVector2 tex_res_st_offset = orig_st_offset + (LLVector2)centers_dist;
+ tex_res_st_offset.mV[VX] -= (S32)tex_res_st_offset.mV[VX];
+ tex_res_st_offset.mV[VY] -= (S32)tex_res_st_offset.mV[VY];
+
+ st_scale /= this_proj_scale;
+
+ // Convert aligned legacy TE transform back to GLTF transform
+ LLGLTFMaterial::convertTextureTransformToPBR(
+ st_scale.mV[0], st_scale.mV[1],
+ tex_res_st_offset.mV[0], tex_res_st_offset.mV[1],
+ z_ang,
+ *res_st_scale, *res_st_offset, *res_st_rot);
+
+ return true;
+}
+
void LLFace::updateRebuildFlags()
{
if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
@@ -1405,11 +1490,11 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
// They are used only to display a face selection marker
// (white square with a rounded cross at the center)
const auto& tt = gltf_mat->mTextureTransform[gltf_info_index];
- r = -tt.mRotation * 2;
- ms = tt.mScale[VX];
- mt = tt.mScale[VY];
- os += tt.mOffset[VX] + (ms - 1) / 2;
- ot -= tt.mOffset[VY] + (mt - 1) / 2;
+ LLGLTFMaterial::convertPBRTransformToTexture(
+ tt.mScale,
+ tt.mOffset,
+ tt.mRotation,
+ ms, mt, os, ot, r);
}
else
{
@@ -2382,7 +2467,11 @@ F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius
//the above calculation is too expensive
//the below is a good estimation: bounding box of the bounding sphere:
- F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
+ F32 alpha = 1.f;
+ if (!is_approx_zero(radius)) // radius can be something like -1e-10
+ {
+ alpha = 0.5f * (radius + screen_radius - d) / radius;
+ }
alpha = llclamp(alpha, 0.f, 1.f) ;
return alpha * alpha ;
}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index df31e9ea90..6e9d23c3a2 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -103,6 +103,8 @@ public:
LLVector3 getPositionAgent() const;
LLVector2 surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal);
void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const;
+ bool calcAlignedPlanarGLTF(const LLFace* align_to, LLVector2* res_st_offset,
+ LLVector2* res_st_scale, F32* res_st_rot, S32 gltf_info_index = 0) const;
bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset,
LLVector2* st_scale, F32* st_rot, LLRender::eTexIndex map = LLRender::DIFFUSE_MAP) const;
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 98b3ca820b..b3408f7861 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1375,6 +1375,11 @@ bool LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
}
void copy_slurl_to_clipboard_cb(std::string& slurl)
{
+ if (slurl.empty())
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ return;
+ }
LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, static_cast<S32>(slurl.size()));
LLSD args;
diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm
index 6921cd6101..99e93bafbf 100644
--- a/indra/newview/llfilepicker_mac.mm
+++ b/indra/newview/llfilepicker_mac.mm
@@ -241,8 +241,13 @@ void doSaveDialogModeless(const std::string* file,
NSURL* url = [NSURL fileURLWithPath:fileName];
[panel setNameFieldStringValue: fileName];
- [panel setDirectoryURL: url];
+ NSURL *last_url = [[NSUserDefaults standardUserDefaults] URLForKey:@"NSNavLastRootDirectory"];
+ if(!last_url)
+ {
+ NSURL *downloads_url = [[NSFileManager defaultManager] URLsForDirectory:NSDownloadsDirectory inDomains:NSUserDomainMask].firstObject;
+ [panel setDirectoryURL:downloads_url];
+ }
[panel beginWithCompletionHandler:^(NSModalResponse result)
{
diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index 95e7b9af41..ed07d49ac1 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -403,7 +403,7 @@ void LLFloater360Capture::suspendForAFrame()
U32 curr_frame_count = LLFrameTimer::getFrameCount();
while (LLFrameTimer::getFrameCount() <= curr_frame_count + frame_count_delta)
{
- llcoro::suspend();
+ llcoro::suspendUntilNextFrame();
}
}
diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp
deleted file mode 100644
index ba682494bb..0000000000
--- a/indra/newview/llfloaterbigpreview.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
-* @file llfloaterbigpreview.cpp
-* @brief Display of extended (big) preview for snapshots and SL Share
-* @author merov@lindenlab.com
-*
-* $LicenseInfo:firstyear=2013&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2013, 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 "llfloaterbigpreview.h"
-#include "llsnapshotlivepreview.h"
-
-///////////////////////
-//LLFloaterBigPreview//
-///////////////////////
-
-LLFloaterBigPreview::LLFloaterBigPreview(const LLSD& key) : LLFloater(key),
- mPreviewPlaceholder(NULL),
- mFloaterOwner(NULL)
-{
-}
-
-LLFloaterBigPreview::~LLFloaterBigPreview()
-{
- if (mPreviewHandle.get())
- {
- mPreviewHandle.get()->die();
- }
-}
-
-void LLFloaterBigPreview::onCancel()
-{
- closeFloater();
-}
-
-void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp)
-{
- if (isFloaterOwner(floaterp))
- {
- closeFloater();
- }
-}
-
-bool LLFloaterBigPreview::postBuild()
-{
- mPreviewPlaceholder = getChild<LLUICtrl>("big_preview_placeholder");
- return LLFloater::postBuild();
-}
-
-void LLFloaterBigPreview::draw()
-{
- LLFloater::draw();
-
- LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
-
- // Display the preview if one is available
- if (previewp && previewp->getBigThumbnailImage())
- {
- // Get the preview rect
- const LLRect& preview_rect = mPreviewPlaceholder->getRect();
-
- // Get the preview texture size
- S32 thumbnail_w = previewp->getBigThumbnailWidth();
- S32 thumbnail_h = previewp->getBigThumbnailHeight();
-
- // Compute the scaling ratio and the size of the final texture in the rect: we want to prevent anisotropic scaling (distorted in x and y)
- F32 ratio = llmax((F32)(thumbnail_w)/(F32)(preview_rect.getWidth()), (F32)(thumbnail_h)/(F32)(preview_rect.getHeight()));
- thumbnail_w = (S32)((F32)(thumbnail_w)/ratio);
- thumbnail_h = (S32)((F32)(thumbnail_h)/ratio);
-
- // Compute the preview offset within the preview rect: we want to center that preview in the available rect
- const S32 local_offset_x = (preview_rect.getWidth() - thumbnail_w) / 2 ;
- const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ;
-
- // Compute preview offset within the floater rect
- S32 offset_x = preview_rect.mLeft + local_offset_x;
- S32 offset_y = preview_rect.mBottom + local_offset_y;
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- // Apply floater transparency to the texture unless the floater is focused.
- F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
- LLColor4 color = LLColor4::white;
-
- // Draw the preview texture
- gl_draw_scaled_image(offset_x, offset_y,
- thumbnail_w, thumbnail_h,
- previewp->getBigThumbnailImage(), color % alpha);
- }
-}
-
diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h
deleted file mode 100644
index 1d5804acf5..0000000000
--- a/indra/newview/llfloaterbigpreview.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
-* @file llfloaterbigpreview.h
-* @brief Display of extended (big) preview for snapshots
-* @author merov@lindenlab.com
-*
-* $LicenseInfo:firstyear=2013&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2013, 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_LLFLOATERBIGPREVIEW_H
-#define LL_LLFLOATERBIGPREVIEW_H
-
-#include "llfloater.h"
-
-class LLFloaterBigPreview : public LLFloater
-{
-public:
- LLFloaterBigPreview(const LLSD& key);
- ~LLFloaterBigPreview();
-
- bool postBuild();
- void draw();
- void onCancel();
-
- void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); }
- void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; }
- bool isFloaterOwner(LLFloater* floaterp) const { return (mFloaterOwner == floaterp); }
- void closeOnFloaterOwnerClosing(LLFloater* floaterp);
-
-private:
- LLHandle<LLView> mPreviewHandle;
- LLUICtrl* mPreviewPlaceholder;
- LLFloater* mFloaterOwner;
-};
-
-#endif // LL_LLFLOATERBIGPREVIEW_H
-
diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp
index fb31361fd9..914d2135ba 100644
--- a/indra/newview/llfloaterchangeitemthumbnail.cpp
+++ b/indra/newview/llfloaterchangeitemthumbnail.cpp
@@ -236,11 +236,13 @@ bool LLFloaterChangeItemThumbnail::handleDragAndDrop(
if (cargo_type == DAD_TEXTURE)
{
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
- if (item->getAssetUUID().notNull())
+ const LLUUID& asset_id = item->getAssetUUID();
+ if (asset_id.notNull())
{
if (drop)
{
- assignAndValidateAsset(item->getAssetUUID());
+ LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::getFetchedTexture(asset_id);
+ assignAndValidateTexture(asset_id, texturep);
}
*accept = ACCEPT_YES_SINGLE;
@@ -708,6 +710,81 @@ void LLFloaterChangeItemThumbnail::assignAndValidateAsset(const LLUUID &asset_id
}
}
}
+
+void LLFloaterChangeItemThumbnail::assignAndValidateTexture(const LLUUID& asset_id, LLPointer<LLViewerFetchedTexture> texturep)
+{
+ if (!texturep)
+ {
+ LL_WARNS() << "Image " << asset_id << " doesn't exist" << LL_ENDL;
+ return;
+ }
+
+ if (texturep->isMissingAsset())
+ {
+ LL_WARNS() << "Image " << asset_id << " is missing" << LL_ENDL;
+ return;
+ }
+
+ if (texturep->getFullWidth() != texturep->getFullHeight())
+ {
+ LLNotificationsUtil::add("ThumbnailDimentionsLimit");
+ return;
+ }
+
+ if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
+ && texturep->getFullWidth() > 0)
+ {
+ LLNotificationsUtil::add("ThumbnailDimentionsLimit");
+ return;
+ }
+
+ if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
+ || texturep->getFullWidth() == 0)
+ {
+ if (texturep->isFullyLoaded()
+ && (texturep->getRawImageLevel() == 0)
+ && (texturep->isRawImageValid()))
+ {
+ LLUUID task_id = mTaskId;
+ uuid_set_t inventory_ids = mItemList;
+ LLHandle<LLFloater> handle = getHandle();
+ LLFloaterSimpleSnapshot::completion_t callback =
+ [inventory_ids, task_id, handle](const LLUUID& asset_id)
+ {
+ onUploadComplete(asset_id, task_id, inventory_ids, handle);
+ };
+ LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
+ *mItemList.begin(),
+ mTaskId,
+ callback);
+ }
+ else
+ {
+ ImageLoadedData* data = new ImageLoadedData();
+ data->mTaskId = mTaskId;
+ data->mItemIds = mItemList;
+ data->mThumbnailId = asset_id;
+ data->mFloaterHandle = getHandle();
+ data->mSilent = false;
+ data->mTexturep = texturep;
+
+ texturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ texturep->setMinDiscardLevel(0);
+ texturep->setLoadedCallback(onFullImageLoaded,
+ 0, // Need best quality
+ true,
+ false,
+ (void*)data,
+ NULL,
+ false);
+ texturep->forceToSaveRawImage(0);
+ }
+ return;
+ }
+
+ setThumbnailId(asset_id);
+}
+
bool LLFloaterChangeItemThumbnail::validateAsset(const LLUUID &asset_id)
{
if (asset_id.isNull())
@@ -922,76 +999,8 @@ void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
}
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::findFetchedTexture(asset_id, TEX_LIST_STANDARD);
- if (!texturep)
- {
- LL_WARNS() << "Image " << asset_id << " doesn't exist" << LL_ENDL;
- return;
- }
-
- if (texturep->isMissingAsset())
- {
- LL_WARNS() << "Image " << asset_id << " is missing" << LL_ENDL;
- return;
- }
-
- if (texturep->getFullWidth() != texturep->getFullHeight())
- {
- LLNotificationsUtil::add("ThumbnailDimentionsLimit");
- return;
- }
-
- if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
- && texturep->getFullWidth() > 0)
- {
- LLNotificationsUtil::add("ThumbnailDimentionsLimit");
- return;
- }
-
- if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
- || texturep->getFullWidth() == 0)
- {
- if (texturep->isFullyLoaded()
- && (texturep->getRawImageLevel() == 0)
- && (texturep->isRawImageValid()))
- {
- LLUUID task_id = mTaskId;
- uuid_set_t inventory_ids = mItemList;
- LLHandle<LLFloater> handle = getHandle();
- LLFloaterSimpleSnapshot::completion_t callback =
- [inventory_ids, task_id, handle](const LLUUID& asset_id)
- {
- onUploadComplete(asset_id, task_id, inventory_ids, handle);
- };
- LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
- *mItemList.begin(),
- mTaskId,
- callback);
- }
- else
- {
- ImageLoadedData* data = new ImageLoadedData();
- data->mTaskId = mTaskId;
- data->mItemIds = mItemList;
- data->mThumbnailId = asset_id;
- data->mFloaterHandle = getHandle();
- data->mSilent = false;
- data->mTexturep = texturep;
-
- texturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
- texturep->setMinDiscardLevel(0);
- texturep->setLoadedCallback(onFullImageLoaded,
- 0, // Need best quality
- true,
- false,
- (void*)data,
- NULL,
- false);
- texturep->forceToSaveRawImage(0);
- }
- return;
- }
- setThumbnailId(asset_id);
+ assignAndValidateTexture(asset_id, texturep);
}
}
diff --git a/indra/newview/llfloaterchangeitemthumbnail.h b/indra/newview/llfloaterchangeitemthumbnail.h
index 46f63801fe..980b46b298 100644
--- a/indra/newview/llfloaterchangeitemthumbnail.h
+++ b/indra/newview/llfloaterchangeitemthumbnail.h
@@ -82,7 +82,11 @@ private:
static void onRemove(void*);
static void onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle);
+ // As needed, attempts to load image then validates and assigns, does no converting.
void assignAndValidateAsset(const LLUUID &asset_id, bool silent = false);
+ // As needed, attempts to load and convert(upload) image then validates and assigns.
+ void assignAndValidateTexture(const LLUUID& asset_id, LLPointer<LLViewerFetchedTexture> texturep);
+
static void onImageDataLoaded(bool success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index cd45093856..56e086502a 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -233,7 +233,15 @@ bool LLFloaterColorPicker::postBuild()
childSetCommitCallback("sspin", onTextCommit, (void*)this );
childSetCommitCallback("lspin", onTextCommit, (void*)this );
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1));
+ mPipetteConnection = LLToolPipette::getInstance()->setToolSelectCallback(
+ [this](LLPointer<LLViewerObject> object, S32 te_index)
+ {
+ const LLTextureEntry* entry = object->getTE(te_index);
+ if (entry)
+ {
+ onColorSelect(entry->getColor());
+ }
+ });
return true;
}
@@ -460,10 +468,10 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
}
}
-void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
+// From pipette
+void LLFloaterColorPicker::onColorSelect( const LLColor4 &color )
{
- // Pipete
- selectCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
+ selectCurRgb(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]);
}
void LLFloaterColorPicker::onMouseCaptureLost()
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 5c27fffd08..af199d92a3 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -122,7 +122,7 @@ class LLFloaterColorPicker
void onClickPipette ( );
static void onTextCommit ( LLUICtrl* ctrl, void* data );
static void onImmediateCheck ( LLUICtrl* ctrl, void* data );
- void onColorSelect( const class LLTextureEntry& te );
+ void onColorSelect(const LLColor4& color); // from pipette
private:
// mutators for color values, can raise event to preview changes at object
void selectCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn );
@@ -197,6 +197,7 @@ class LLFloaterColorPicker
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
+ boost::signals2::scoped_connection mPipetteConnection;
};
#endif // LL_LLFLOATERCOLORPICKER_H
diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp
index 97399c9cf7..40e2d2bf1e 100644
--- a/indra/newview/llfloaterconversationlog.cpp
+++ b/indra/newview/llfloaterconversationlog.cpp
@@ -100,6 +100,10 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata)
{
mConversationLogList->toggleSortFriendsOnTop();
}
+ else if ("show_blocked" == command_name)
+ {
+ gSavedSettings.setBOOL("ShowBlockedConvHistory", !gSavedSettings.getBOOL("ShowBlockedConvHistory"));
+ }
else if ("view_nearby_chat_history" == command_name)
{
LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);
@@ -129,6 +133,10 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata)
{
return gSavedSettings.getBOOL("SortFriendsFirst");
}
+ else if ("show_blocked" == command_name)
+ {
+ return gSavedSettings.getBOOL("ShowBlockedConvHistory");
+ }
return false;
}
diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp
index a42c94f049..bc1f3045bb 100644
--- a/indra/newview/llfloatereditenvironmentbase.cpp
+++ b/indra/newview/llfloatereditenvironmentbase.cpp
@@ -262,7 +262,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons
}
else if (mInventoryItem)
{
- const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
LLUUID parent_id = mInventoryItem->getParentUUID();
if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
{
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index 999a473a49..79d74093a2 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -385,8 +385,11 @@ void LLFloaterExperiences::retrieveExperienceListCoro(std::string url,
if (!status)
{
+ LL_WARNS("Experience") << "Failed to retrieve list. Error: " << status.toTerseString()
+ << ". Type: " << errorNotify << " Message: " << status.getMessage() << LL_ENDL;
+
LLSD subs;
- subs["ERROR_MESSAGE"] = status.getType();
+ subs["ERROR_MESSAGE"] = llformat(" %d\n %s", (S32)status.getType(), status.getMessage().c_str());
LLNotificationsUtil::add(errorNotify, subs);
return;
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 143781a225..f8f34ca12e 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -57,6 +57,8 @@
#include "llsdserialize.h"
#include "llviewermenu.h" // is_agent_mappable
#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llnearbyvoicemoderation.h"
const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80;
@@ -90,6 +92,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mAutoResize = false;
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
+ LLNearbyVoiceModeration::getInstance();
}
LLFloaterIMContainer::~LLFloaterIMContainer()
@@ -152,6 +155,11 @@ void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const
{
// The general strategy when a session id is modified is to delete all related objects and create them anew.
+ // The conversation floater can be active while participant widgets are selected.
+ // Preserve that state separately so the new conversation widget can be selected
+ // after the server replaces an outgoing ad-hoc session id.
+ const bool was_active = old_session_id == getSelectedSession();
+
// Note however that the LLFloaterIMSession has its session id updated through a call to sessionInitReplyReceived()
// and do not need to be deleted and recreated (trying this creates loads of problems). We do need however to suppress
// its related mSessions record as it's indexed with the wrong id.
@@ -164,6 +172,11 @@ void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const
// Create a new conversation with the new id
addConversationListItem(new_session_id, change_focus);
LLFloaterIMSessionTab::addToHost(new_session_id);
+
+ if (was_active)
+ {
+ selectConversationPair(new_session_id, true, false, true);
+ }
}
@@ -530,6 +543,33 @@ void LLFloaterIMContainer::idleUpdate()
mGeneralTitleInUse = !needs_override;
setTitle(needs_override ? conversation_floaterp->getTitle() : mGeneralTitle);
}
+ const LLConversationItem* nearby_session = getSessionModel(LLUUID());
+ if (nearby_session)
+ {
+ LLSpeakerMgr* speaker_mgr = (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance());
+
+ LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = nearby_session->getChildrenBegin();
+ LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = nearby_session->getChildrenEnd();
+ while (current_participant_model != end_participant_model)
+ {
+ LLConversationItemParticipant* participant_model =
+ dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
+ if (participant_model)
+ {
+ bool show_moderator_options = LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator();
+ LLUUID participant_id = participant_model->getUUID();
+ if (participant_id != gAgentID)
+ {
+ // Don't show moderator options if participant is not connected to the same spatial channel
+ LLSpeaker* speakerp = speaker_mgr->findSpeaker(participant_id).get();
+ show_moderator_options &= speakerp && speakerp->isInVoiceChannel();
+ }
+ participant_model->setModeratorOptionsVisible(show_moderator_options);
+ }
+
+ current_participant_model++;
+ }
+ }
}
mParticipantRefreshTimer.setTimerExpirySec(1.0f);
@@ -1693,6 +1733,10 @@ bool LLFloaterIMContainer::visibleContextMenuItem(const LLSD& userdata)
{
return isMuted(conversation_item->getUUID());
}
+ else if ("can_allow_text_chat" == item)
+ {
+ return !isNearbyChatSpeakerSelected();
+ }
return true;
}
@@ -1700,7 +1744,7 @@ bool LLFloaterIMContainer::visibleContextMenuItem(const LLSD& userdata)
void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
{
setVisibleAndFrontmost(false);
- selectConversationPair(session_id, true);
+ selectConversationPair(session_id, true, true, true);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
if (session_floater)
@@ -1746,13 +1790,13 @@ void LLFloaterIMContainer::selectNextConversationByID(const LLUUID& uuid)
}
// Synchronous select the conversation item and the conversation floater
-bool LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater/*=true*/)
+bool LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater/*=true*/, bool force_select_widget/*=false*/)
{
bool handled = true;
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
/* widget processing */
- if (select_widget && mConversationsRoot->getSelectedCount() <= 1)
+ if (select_widget && (force_select_widget || mConversationsRoot->getSelectedCount() <= 1))
{
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id);
if (widget && widget->getParentFolder())
@@ -1956,7 +2000,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
mConversationEventQueue.erase(uuid);
// Don't let the focus fall IW, select and refocus on the first conversation in the list
- if (change_focus && isInVisibleChain())
+ if (change_focus && is_widget_selected && isInVisibleChain())
{
setFocus(true);
if (new_selection)
@@ -2022,9 +2066,27 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
{
- // only group moderators can perform actions related to this "enable callback"
- if (!isGroupModerator())
+ if (LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator() && isNearbyChatSpeakerSelected())
{
+ // Determine here which actions are allowed
+ if ("can_moderate_voice" == userdata)
+ {
+ return true;
+ }
+ else if (("can_mute" == userdata))
+ {
+ return !is_self;
+ }
+ else if ("can_unmute" == userdata)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ else if (!isGroupModerator())
+ {
+ // only group moderators can perform actions related to this "enable callback"
return false;
}
@@ -2157,7 +2219,35 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID)
{
- if (!gAgent.getRegion()) return;
+ if (!gAgent.getRegion())
+ {
+ return;
+ }
+
+ if (isNearbyChatSpeakerSelected())
+ {
+ if ("selected" == command)
+ {
+ // Request a mute/unmute using a capability request via the simulator
+ LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, !isMuted(userID));
+ }
+ else
+ if ("mute_all" == command)
+ {
+ // Send the mute_all request to the server
+ const bool mute_state = true;
+ LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
+ }
+ else
+ if ("unmute_all" == command)
+ {
+ // Send the unmute_all request to the server
+ const bool mute_state = false;
+ LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state);
+ }
+
+ return;
+ }
if (command.compare("selected"))
{
@@ -2275,6 +2365,31 @@ LLSpeaker * LLFloaterIMContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr *
return speaker_managerp->findSpeaker(participant_itemp->getUUID());
}
+bool LLFloaterIMContainer::isNearbyChatSpeakerSelected()
+{
+ LLFolderViewItem *selectedItem = mConversationsRoot->getCurSelectedItem();
+ if (!selectedItem)
+ {
+ LL_WARNS() << "Current selected item is null" << LL_ENDL;
+ return NULL;
+ }
+
+ conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin();
+ conversations_widgets_map::const_iterator end = mConversationsWidgets.end();
+ const LLUUID * conversation_uuidp = NULL;
+ while(iter != end)
+ {
+ if (iter->second == selectedItem || iter->second == selectedItem->getParentFolder())
+ {
+ conversation_uuidp = &iter->first;
+ break;
+ }
+ ++iter;
+ }
+ // Nearby chat ID is LLUUID::null
+ return conversation_uuidp->isNull();
+}
+
void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid)
{
LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant());
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 30eed8be36..4cb243aa64 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -74,7 +74,7 @@ public:
void showConversation(const LLUUID& session_id);
void selectConversation(const LLUUID& session_id);
void selectNextConversationByID(const LLUUID& session_id);
- bool selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true);
+ bool selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true, bool force_select_widget = false);
void clearAllFlashStates();
bool selectAdjacentConversation(bool focus_selected);
bool selectNextorPreviousConversation(bool select_next, bool focus_selected = true);
@@ -178,6 +178,7 @@ private:
void banSelectedMember(const LLUUID& participant_uuid);
void openNearbyChat();
bool isParticipantListExpanded();
+ bool isNearbyChatSpeakerSelected();
void idleUpdate(); // for convenience (self) from static idle
void idleProcessEvents();
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index f0d696361a..6143d5b89e 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -69,6 +69,7 @@
#include "lltranslate.h"
#include "llautoreplace.h"
#include "lluiusage.h"
+#include "rlvactions.h"
S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
@@ -91,6 +92,8 @@ static LLChatTypeTrigger sChatTypeTriggers[] = {
{ "/shout" , CHAT_TYPE_SHOUT}
};
+static std::unordered_set<S32> sRedirChatChannels;
+
bool cb_do_nothing()
{
return false;
@@ -475,7 +478,7 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()
auto length = raw_text.length();
- if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
+ if( (length > 0) && (raw_text[0] != '/') && !(RlvActions::isRlvEnabled() && !sRedirChatChannels.empty()) ) // forward slash is used for escape (eg. emote) sequences
{
gAgent.startTyping();
}
@@ -699,6 +702,14 @@ void LLFloaterIMNearbyChat::displaySpeakingIndicator()
}
}
+void LLFloaterIMNearbyChat::addOrRemoveRedirChatChannel(S32 channel, bool add)
+{
+ if (add)
+ sRedirChatChannels.insert(channel);
+ else
+ sRedirChatChannels.erase(channel);
+}
+
void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, bool animate)
{
sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate);
@@ -718,6 +729,15 @@ void LLFloaterIMNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType
utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
}
+ auto prefix = utf8_out_text.substr(0, 4);
+ if (RlvActions::isRlvEnabled() && channel == 0 && !sRedirChatChannels.empty() && prefix != "/me " && prefix != "/me'")
+ {
+ std::for_each(sRedirChatChannels.begin(), sRedirChatChannels.end(), [utf8_out_text,type](S32 channel){
+ send_chat_from_viewer(utf8_out_text, type, channel);
+ });
+ return;
+ }
+
// Don't animate for chats people can't hear (chat to scripts)
if (animate && (channel == 0))
{
diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h
index abcaa13442..e2382690da 100644
--- a/indra/newview/llfloaterimnearbychat.h
+++ b/indra/newview/llfloaterimnearbychat.h
@@ -77,6 +77,7 @@ public:
static void startChat(const char* line);
static void stopChat();
+ static void addOrRemoveRedirChatChannel(S32 channel, bool add);
static void sendChatFromViewer(const std::string &utf8text, EChatType type, bool animate);
static void sendChatFromViewer(const LLWString &wtext, EChatType type, bool animate);
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index 84a9fad708..73bce6f2fd 100644
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -142,7 +142,7 @@ void LLFloaterIMSession::onClickCloseBtn(bool app_qutting)
{
if (app_qutting)
{
- LLFloaterIMSessionTab::onClickCloseBtn();
+ LLFloaterIMSessionTab::onClickCloseBtn(app_qutting);
return;
}
@@ -1056,7 +1056,7 @@ void LLFloaterIMSession::processAgentListUpdates(const LLSD& body)
if (moderator_muted_text)
label = LLTrans::getString("IM_muted_text_label");
else
- label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID);
+ label = LLIMModel::instance().getName(mSessionID);
mInputEditor->setLabel(label);
if (moderator_muted_text)
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 48360f30d4..3445b0a7cf 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -48,6 +48,7 @@
#include "llfloaterimnearbychat.h"
#include "llgroupiconctrl.h"
#include "lllayoutstack.h"
+#include "llnotificationsutil.h"
#include "llpanelemojicomplete.h"
#include "lltoolbarview.h"
@@ -936,7 +937,7 @@ void LLFloaterIMSessionTab::hideOrShowTitle()
void LLFloaterIMSessionTab::updateSessionName(const std::string& name)
{
- mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name);
+ mInputEditor->setLabel(name);
}
void LLFloaterIMSessionTab::updateChatIcon(const LLUUID& id)
@@ -1419,3 +1420,20 @@ bool LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
}
return handled;
}
+
+void LLFloaterIMSessionTab::onClickCloseBtn(bool app_quitting)
+{
+ bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false);
+ if (is_ad_hoc && !app_quitting)
+ {
+ LLNotificationsUtil::add("ConfirmLeaveAdhoc", LLSD(), LLSD(), [this](const LLSD& notification, const LLSD& response)
+ {
+ if (0 == LLNotificationsUtil::getSelectedOption(notification, response))
+ closeFloater();
+ });
+ }
+ else
+ {
+ closeFloater();
+ }
+}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 6d04d622e1..b27ac1b8f9 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -85,6 +85,8 @@ public:
void closeFloater(bool app_quitting = false) override;
void deleteAllChildren() override;
+ virtual void onClickCloseBtn(bool app_quitting = false) override;
+
// Handle the left hand participant list widgets
void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
void removeConversationViewParticipant(const LLUUID& participant_id);
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index c0fe7ad896..163edf0426 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -100,6 +100,7 @@ void LLFloaterInspect::onOpen(const LLSD& key)
LLSelectMgr::getInstance()->setForceSelection(forcesel); // restore previouis value
mObjectSelection = LLSelectMgr::getInstance()->getSelection();
refresh();
+ mDirty = false;
}
void LLFloaterInspect::onClickCreatorProfile()
{
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index c961070787..33e054aab9 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -225,6 +225,21 @@ void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> fl
<< " - description update = " << (needs_description_update ? "true" : "false") << LL_NEWLINE
<< " - outfit_folder_id = " << outfit_folder_id.asString() << LL_ENDL;
+ std::string old_description;
+ if (needs_wearable_ordering_update)
+ {
+ LLViewerInventoryItem* old_item = gInventory.getItem(old_item_id);
+ LLViewerInventoryItem* target_item = gInventory.getItem(target_item_id);
+ if (old_item && target_item &&
+ old_item->getType() == LLAssetType::AT_CLOTHING &&
+ target_item->getType() == LLAssetType::AT_CLOTHING &&
+ old_item->getWearableType() == target_item->getWearableType())
+ {
+ // Preserve the original description, which contains ordering info
+ old_description = old_item->getActualDescription();
+ }
+ }
+
// If we are replacing an object, bodypart or gesture link within an outfit folder,
// we need to change the actual description of the link itself. LLAppearanceMgr *should*
// have created COF links that will be used to save the outfit with an empty description.
@@ -246,7 +261,14 @@ void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> fl
{
LLPointer<LLViewerInventoryItem> item = *it;
- if ((item->getType() == LLAssetType::AT_BODYPART ||
+ if (item->getType() == LLAssetType::AT_CLOTHING && !old_description.empty())
+ {
+ // Use the old description to set ordering info
+ LLSD updates;
+ updates["desc"] = old_description;
+ update_inventory_item(item->getUUID(), updates, LLPointer<LLInventoryCallback>(NULL));
+ }
+ else if ((item->getType() == LLAssetType::AT_BODYPART ||
item->getType() == LLAssetType::AT_OBJECT ||
item->getType() == LLAssetType::AT_GESTURE)
&& !item->getActualDescription().empty())
@@ -347,12 +369,9 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items)
bool is_outfit_folder = gInventory.isObjectDescendentOf(source_item->getParentUUID(), outfit_folder_id);
// If either the new or old item in the COF is a wearable, we need to update wearable ordering after the link has been replaced
bool needs_wearable_ordering_update = (is_outfit_folder && source_item->getType() == LLAssetType::AT_CLOTHING) || target_item->getType() == LLAssetType::AT_CLOTHING;
- // Other items in the COF need a description update (description of the actual link item must be empty)
- bool needs_description_update = is_outfit_folder && target_item->getType() != LLAssetType::AT_CLOTHING;
LL_DEBUGS() << "is_outfit_folder = " << (is_outfit_folder ? "true" : "false") << LL_NEWLINE
- << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE
- << "needs_description_update = " << (needs_description_update ? "true" : "false") << LL_ENDL;
+ << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_ENDL;
LLInventoryObject::const_object_list_t obj_array;
obj_array.push_back(LLConstPointer<LLInventoryObject>(target_item));
@@ -361,7 +380,7 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items)
source_item->getUUID(),
target_item->getUUID(),
needs_wearable_ordering_update,
- needs_description_update,
+ is_outfit_folder,
(is_outfit_folder ? source_item->getParentUUID() : LLUUID::null) ));
link_inventory_array(source_item->getParentUUID(), obj_array, cb);
}
diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp
index 7316d7617d..a80546595c 100644
--- a/indra/newview/llfloatermarketplace.cpp
+++ b/indra/newview/llfloatermarketplace.cpp
@@ -39,6 +39,27 @@ LLFloaterMarketplace::~LLFloaterMarketplace()
{
}
+void LLFloaterMarketplace::onOpen(const LLSD& key)
+{
+ Params params(key);
+
+ if (!params.validateBlock())
+ {
+ closeFloater();
+ return;
+ }
+
+ if (params.url().empty())
+ {
+ openMarketplace();
+ }
+ else
+ {
+ openMarketplaceURL(params.url);
+ set_current_url(params.url); // Fix looping back to previous url when using the viewer navigation bar
+ }
+}
+
// just to override LLFloaterWebContent
void LLFloaterMarketplace::onClose(bool app_quitting)
{
@@ -68,3 +89,34 @@ void LLFloaterMarketplace::openMarketplace()
mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
}
}
+
+void LLFloaterMarketplace::openMarketplaceURL(const std::string& url)
+{
+ if (mCurrentURL != url)
+ {
+ mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+ }
+}
+
+// static
+bool LLFloaterMarketplace::isMarketplaceURL(const std::string& url)
+{
+ auto trimURL = [](std::string_view url) -> std::string_view
+ {
+ if (url.starts_with("https://"))
+ url.remove_prefix(8);
+ else if (url.starts_with("http://"))
+ url.remove_prefix(7);
+
+ while (!url.empty() && url.back() == '/')
+ url.remove_suffix(1);
+
+ return url;
+ };
+
+ static LLCachedControl<std::string> marketplace_url(gSavedSettings, "MarketplaceURL", "https://marketplace.secondlife.com/");
+ std::string_view marketplace_url_trimmed = trimURL(marketplace_url());
+ std::string_view url_trimmed = trimURL(url);
+
+ return !marketplace_url_trimmed.empty() && url_trimmed.starts_with(marketplace_url_trimmed);
+}
diff --git a/indra/newview/llfloatermarketplace.h b/indra/newview/llfloatermarketplace.h
index 9524c94eee..17979dae90 100644
--- a/indra/newview/llfloatermarketplace.h
+++ b/indra/newview/llfloatermarketplace.h
@@ -36,11 +36,14 @@ class LLFloaterMarketplace:
public:
void openMarketplace();
+ void openMarketplaceURL(const std::string& url);
+ bool static isMarketplaceURL(const std::string& url);
private:
LLFloaterMarketplace(const LLSD& key);
~LLFloaterMarketplace();
bool postBuild() override;
+ void onOpen(const LLSD& key) override;
void onClose(bool app_quitting) override;
};
diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp
index f20fea01c5..dfd023e424 100644
--- a/indra/newview/llfloatermarketplacelistings.cpp
+++ b/indra/newview/llfloatermarketplacelistings.cpp
@@ -29,6 +29,7 @@
#include "llfloatermarketplacelistings.h"
+#include "llcallbacklist.h"
#include "llfloaterreg.h"
#include "llfiltereditor.h"
#include "llfolderview.h"
@@ -231,7 +232,7 @@ void LLPanelMarketplaceListings::onTabChange()
void LLPanelMarketplaceListings::onAddButtonClicked()
{
- LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
llassert(marketplacelistings_id.notNull());
LLFolderType::EType preferred_type = LLFolderType::lookup("category");
LLHandle<LLPanel> handle = getHandle();
@@ -351,7 +352,15 @@ public:
if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS)
{
- mMarketplaceListingsFloater->initializeMarketPlace();
+ LLHandle<LLFloater> handle = mMarketplaceListingsFloater->getHandle();
+ doOnIdleOneTime([handle]()
+ {
+ LLFloaterMarketplaceListings* floater = (LLFloaterMarketplaceListings*)handle.get();
+ if (floater)
+ {
+ floater->initializeMarketPlace();
+ }
+ });
}
}
}
@@ -415,7 +424,7 @@ bool LLFloaterMarketplaceListings::postBuild()
// Fetch aggressively so we can interact with listings as soon as possible
if (!fetchContents())
{
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
LLInventoryModelBackgroundFetch::instance().start(marketplacelistings_id, true);
}
@@ -513,8 +522,6 @@ void LLFloaterMarketplaceListings::setRootFolder()
return;
}
- mRootFolderCreating = false;
-
// No longer need to observe new category creation
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
{
@@ -524,6 +531,8 @@ void LLFloaterMarketplaceListings::setRootFolder()
}
llassert(!mCategoryAddedObserver);
+ mRootFolderCreating = false;
+
if (marketplacelistings_id == mRootFolderId)
{
LL_WARNS("SLM") << "Inventory warning: Marketplace listings folder already set" << LL_ENDL;
@@ -566,7 +575,8 @@ void LLFloaterMarketplaceListings::setPanels()
void LLFloaterMarketplaceListings::initializeMarketPlace()
{
- LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this));
+ if (!mRootFolderCreating)
+ LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this));
}
S32 LLFloaterMarketplaceListings::getFolderCount()
@@ -909,7 +919,7 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key)
LLUUID cat_id(key.asUUID());
if (cat_id.isNull())
{
- cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ cat_id = gInventory.getMarketplaceListingsUUID();
}
// Validates the folder
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
index fa491a4b27..bd8530abd7 100644
--- a/indra/newview/llfloaterobjectweights.cpp
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -208,7 +208,7 @@ void LLFloaterObjectWeights::draw()
toggleRenderLoadingIndicators(false);
}
mTrianglesShown->setText(llformat("%d", total_tris));
- mPixelArea->setText(llformat("%d", pixel_area));
+ mPixelArea->setText(llformat("%ld", (S64)pixel_area)); // value capped at 10M
}
LLFloater::draw();
}
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index d5e45c09e3..e497fb0914 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -502,7 +502,7 @@ void LLFloaterPay::onGive(give_money_ptr info)
amount = atoi(text_field->getValue().asString().c_str());
}
- if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount)
+ if (amount > PAY_AMOUNT_NOTIFICATION)
{
LLUUID payee_id = LLUUID::null;
bool is_group = false;
diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp
deleted file mode 100644
index 616c13cdc7..0000000000
--- a/indra/newview/llfloaterpostprocess.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/**
- * @file llfloaterpostprocess.cpp
- * @brief LLFloaterPostProcess class definition
- *
- * $LicenseInfo:firstyear=2007&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 "llfloaterpostprocess.h"
-
-#include "llsliderctrl.h"
-#include "llcheckboxctrl.h"
-#include "llnotificationsutil.h"
-#include "lluictrlfactory.h"
-#include "llviewerdisplay.h"
-#include "llpostprocess.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llviewerwindow.h"
-
-
-LLFloaterPostProcess::LLFloaterPostProcess(const LLSD& key)
- : LLFloater(key)
-{
-}
-
-LLFloaterPostProcess::~LLFloaterPostProcess()
-{
-
-
-}
-bool LLFloaterPostProcess::postBuild()
-{
- /// Color Filter Callbacks
- childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter");
- //childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, &(gPostProcess->tweaks.gamma()));
- childSetCommitCallback("ColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness");
- childSetCommitCallback("ColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation");
- childSetCommitCallback("ColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast");
-
- childSetCommitCallback("ColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base");
- childSetCommitCallback("ColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base");
- childSetCommitCallback("ColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base");
- childSetCommitCallback("ColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base");
-
- /// Night Vision Callbacks
- childSetCommitCallback("NightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision");
- childSetCommitCallback("NightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier");
- childSetCommitCallback("NightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size");
- childSetCommitCallback("NightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength");
-
- /// Bloom Callbacks
- childSetCommitCallback("BloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom");
- childSetCommitCallback("BloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low");
- childSetCommitCallback("BloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width");
- childSetCommitCallback("BloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength");
-
- // Effect loading and saving.
- LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo");
- getChild<LLComboBox>("PPLoadEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onLoadEffect, this, comboBox));
- comboBox->setCommitCallback(boost::bind(&LLFloaterPostProcess::onChangeEffectName, this, _1));
-
- LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor");
- getChild<LLComboBox>("PPSaveEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onSaveEffect, this, editBox));
-
- syncMenu();
- return true;
-}
-
-// Bool Toggle
-void LLFloaterPostProcess::onBoolToggle(LLUICtrl* ctrl, void* userData)
-{
- char const * boolVariableName = (char const *)userData;
-
- // check the bool
- LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
- gPostProcess->tweaks[boolVariableName] = cbCtrl->getValue();
-}
-
-// Float Moved
-void LLFloaterPostProcess::onFloatControlMoved(LLUICtrl* ctrl, void* userData)
-{
- char const * floatVariableName = (char const *)userData;
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- gPostProcess->tweaks[floatVariableName] = sldrCtrl->getValue();
-}
-
-// Color Moved
-void LLFloaterPostProcess::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
-{
- char const * floatVariableName = (char const *)userData;
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- gPostProcess->tweaks[floatVariableName][0] = sldrCtrl->getValue();
-}
-
-// Color Moved
-void LLFloaterPostProcess::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
-{
- char const * floatVariableName = (char const *)userData;
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- gPostProcess->tweaks[floatVariableName][1] = sldrCtrl->getValue();
-}
-
-// Color Moved
-void LLFloaterPostProcess::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
-{
- char const * floatVariableName = (char const *)userData;
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- gPostProcess->tweaks[floatVariableName][2] = sldrCtrl->getValue();
-}
-
-// Color Moved
-void LLFloaterPostProcess::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
-{
- char const * floatVariableName = (char const *)userData;
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- gPostProcess->tweaks[floatVariableName][3] = sldrCtrl->getValue();
-}
-
-void LLFloaterPostProcess::onLoadEffect(LLComboBox* comboBox)
-{
- LLSD::String effectName(comboBox->getSelectedValue().asString());
-
- gPostProcess->setSelectedEffect(effectName);
-
- syncMenu();
-}
-
-void LLFloaterPostProcess::onSaveEffect(LLLineEditor* editBox)
-{
- std::string effectName(editBox->getValue().asString());
-
- if (gPostProcess->mAllEffects.has(effectName))
- {
- LLSD payload;
- payload["effect_name"] = effectName;
- LLNotificationsUtil::add("PPSaveEffectAlert", LLSD(), payload, boost::bind(&LLFloaterPostProcess::saveAlertCallback, this, _1, _2));
- }
- else
- {
- gPostProcess->saveEffect(effectName);
- syncMenu();
- }
-}
-
-void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl)
-{
- // get the combo box and name
- LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor");
-
- // set the parameter's new name
- editBox->setValue(ctrl->getValue());
-}
-
-bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- // if they choose save, do it. Otherwise, don't do anything
- if (option == 0)
- {
- gPostProcess->saveEffect(notification["payload"]["effect_name"].asString());
-
- syncMenu();
- }
- return false;
-}
-
-void LLFloaterPostProcess::syncMenu()
-{
- // add the combo boxe contents
- LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo");
-
- comboBox->removeall();
-
- LLSD::map_const_iterator currEffect;
- for(currEffect = gPostProcess->mAllEffects.beginMap();
- currEffect != gPostProcess->mAllEffects.endMap();
- ++currEffect)
- {
- comboBox->add(currEffect->first);
- }
-
- // set the current effect as selected.
- comboBox->selectByValue(gPostProcess->getSelectedEffect());
-
- /// Sync Color Filter Menu
- getChild<LLUICtrl>("ColorFilterToggle")->setValue(gPostProcess->tweaks.useColorFilter());
- //getChild<LLUICtrl>("ColorFilterGamma")->setValue(gPostProcess->tweaks.gamma());
- getChild<LLUICtrl>("ColorFilterBrightness")->setValue(gPostProcess->tweaks.brightness());
- getChild<LLUICtrl>("ColorFilterSaturation")->setValue(gPostProcess->tweaks.saturation());
- getChild<LLUICtrl>("ColorFilterContrast")->setValue(gPostProcess->tweaks.contrast());
- getChild<LLUICtrl>("ColorFilterBaseR")->setValue(gPostProcess->tweaks.contrastBaseR());
- getChild<LLUICtrl>("ColorFilterBaseG")->setValue(gPostProcess->tweaks.contrastBaseG());
- getChild<LLUICtrl>("ColorFilterBaseB")->setValue(gPostProcess->tweaks.contrastBaseB());
- getChild<LLUICtrl>("ColorFilterBaseI")->setValue(gPostProcess->tweaks.contrastBaseIntensity());
-
- /// Sync Night Vision Menu
- getChild<LLUICtrl>("NightVisionToggle")->setValue(gPostProcess->tweaks.useNightVisionShader());
- getChild<LLUICtrl>("NightVisionBrightMult")->setValue(gPostProcess->tweaks.brightMult());
- getChild<LLUICtrl>("NightVisionNoiseSize")->setValue(gPostProcess->tweaks.noiseSize());
- getChild<LLUICtrl>("NightVisionNoiseStrength")->setValue(gPostProcess->tweaks.noiseStrength());
-
- /// Sync Bloom Menu
- getChild<LLUICtrl>("BloomToggle")->setValue(LLSD(gPostProcess->tweaks.useBloomShader()));
- getChild<LLUICtrl>("BloomExtract")->setValue(gPostProcess->tweaks.extractLow());
- getChild<LLUICtrl>("BloomSize")->setValue(gPostProcess->tweaks.bloomWidth());
- getChild<LLUICtrl>("BloomStrength")->setValue(gPostProcess->tweaks.bloomStrength());
-}
diff --git a/indra/newview/llfloaterpostprocess.h b/indra/newview/llfloaterpostprocess.h
deleted file mode 100644
index 50b48d8410..0000000000
--- a/indra/newview/llfloaterpostprocess.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * @file llfloaterpostprocess.h
- * @brief LLFloaterPostProcess class definition
- *
- * $LicenseInfo:firstyear=2007&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_LLFLOATERPOSTPROCESS_H
-#define LL_LLFLOATERPOSTPROCESS_H
-
-#include "llfloater.h"
-
-class LLButton;
-class LLComboBox;
-class LLLineEditor;
-class LLSliderCtrl;
-class LLTabContainer;
-class LLPanelPermissions;
-class LLPanelObject;
-class LLPanelVolume;
-class LLPanelContents;
-class LLPanelFace;
-
-/**
- * Menu for adjusting the post process settings of the world
- */
-class LLFloaterPostProcess : public LLFloater
-{
-public:
-
- LLFloaterPostProcess(const LLSD& key);
- virtual ~LLFloaterPostProcess();
- bool postBuild();
-
- /// post process callbacks
- static void onBoolToggle(LLUICtrl* ctrl, void* userData);
- static void onFloatControlMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlGMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlBMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlIMoved(LLUICtrl* ctrl, void* userData);
- void onLoadEffect(LLComboBox* comboBox);
- void onSaveEffect(LLLineEditor* editBox);
- void onChangeEffectName(LLUICtrl* ctrl);
-
- /// prompts a user when overwriting an effect
- bool saveAlertCallback(const LLSD& notification, const LLSD& response);
-
- /// sync up sliders
- void syncMenu();
-};
-
-#endif
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index eb1b758332..cb708050fd 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -474,7 +474,8 @@ bool LLFloaterPreference::postBuild()
getChild<LLUICtrl>("log_path_string")->setEnabled(false); // make it read-only but selectable
- getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
+ mLanguageCombobox = getChild<LLComboBox>("language_combobox");
+ mLanguageCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
mTimeFormatCombobox = getChild<LLComboBox>("time_format_combobox");
mTimeFormatCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onTimeFormatChange, this));
@@ -516,18 +517,18 @@ bool LLFloaterPreference::postBuild()
std::map<std::string, std::string>::iterator iter = labels.find(system_lang);
if (iter != labels.end())
{
- getChild<LLComboBox>("language_combobox")->add(iter->second, LLSD("default"), ADD_TOP, true);
+ mLanguageCombobox->add(iter->second, LLSD("default"), ADD_TOP, true);
}
else
{
LL_WARNS() << "Language \"" << system_lang << "\" is not in default_languages.xml" << LL_ENDL;
- getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
+ mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true);
}
}
else
{
LL_WARNS() << "Failed to load labels from " << user_filename << ". Using default." << LL_ENDL;
- getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
+ mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true);
}
#ifndef LL_DISCORD
@@ -619,8 +620,6 @@ void LLFloaterPreference::apply()
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
- LLViewerMedia::getInstance()->setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue());
-
if (hasChild("web_proxy_enabled", true) &&hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true))
{
bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue();
@@ -774,9 +773,9 @@ void LLFloaterPreference::onOpen(const LLSD& key)
// Load (double-)click to walk/teleport settings.
updateClickActionViews();
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
// Lixux doesn't support automatic mode
- LLComboBox* combo = getChild<LLComboBox>("double_click_action_combo");
+ LLComboBox* combo = getChild<LLComboBox>("mouse_warp_combo");
S32 mode = gSavedSettings.getS32("MouseWarpMode");
if (mode == 0)
{
@@ -1340,6 +1339,12 @@ void LLFloaterPreference::refresh()
updateClickActionViews();
mTimeFormatCombobox->selectByValue(gSavedSettings.getBOOL("Use24HourClock") ? "1" : "0");
+
+ std::string current_language = gSavedSettings.getString("Language");
+ if (current_language != "default" && !current_language.empty())
+ {
+ mLanguageCombobox->selectByValue(LLSD(current_language));
+ }
}
void LLFloaterPreference::onCommitWindowedMode()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 8d3f1ed6b0..33ba28d0dc 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -237,6 +237,7 @@ private:
LLButton* mEnablePopupBtn = nullptr;
LLButton* mDisablePopupBtn = nullptr;
LLComboBox* mTimeFormatCombobox = nullptr;
+ LLComboBox* mLanguageCombobox = nullptr;
std::unique_ptr< ll::prefs::SearchData > mSearchData;
bool mSearchDataDirty;
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 2be5953ecd..45f2abf011 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -538,6 +538,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid));
panel->setCtrlsEnabled(allow_modify);
+ panel->getChild<LLLineEditor>("estate_id")->setValue((S32)region_info.mEstateID);
+
+ if (region)
+ {
+ panel->getChild<LLLineEditor>("grid_position_x")->setValue((S32)(region->getOriginGlobal()[VX] / 256));
+ panel->getChild<LLLineEditor>("grid_position_y")->setValue((S32)(region->getOriginGlobal()[VY] / 256));
+ }
+ else
+ {
+ panel->getChild<LLLineEditor>("grid_position_x")->setDefaultText();
+ panel->getChild<LLLineEditor>("grid_position_y")->setDefaultText();
+ }
// DEBUG PANEL
panel = tab->getChild<LLPanel>("Debug");
@@ -902,6 +914,9 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
getChildView("apply_btn")->setEnabled(false);
getChildView("access_text")->setEnabled(allow_modify);
// getChildView("access_combo")->setEnabled(allow_modify);
+ getChildView("estate_id")->setEnabled(false);
+ getChildView("grid_position_x")->setEnabled(false);
+ getChildView("grid_position_y")->setEnabled(false);
// now set in processRegionInfo for teen grid detection
getChildView("kick_btn")->setEnabled(allow_modify);
getChildView("kick_all_btn")->setEnabled(allow_modify);
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 9b7a4e5134..3c84f5b459 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -123,19 +123,32 @@ void LLFloaterSearch::initiateSearch(const LLSD& tokens)
subs["COLLECTION"] = "";
if (subs["TYPE"] == "standard")
{
+ std::string collection_args;
if (mCollectionType.find(collection) != mCollectionType.end())
{
- subs["COLLECTION"] = "&collection_chosen=" + std::string(collection);
+ collection_args = "&collection_chosen=" + std::string(collection);
}
- else
+ else if (tokens.has("collections") && tokens["collections"].isArray())
+ {
+ const LLSD &sd = tokens["collections"];
+ for (LLSD::array_const_iterator it = sd.beginArray();
+ it != sd.endArray();
+ ++it)
+ {
+ if (mCollectionType.find(it->asString()) != mCollectionType.end())
+ {
+ collection_args += "&collection_chosen=" + std::string(*it);
+ }
+ }
+ }
+ if (collection_args.empty())
{
- std::string collection_args("");
for (std::set<std::string>::iterator it = mCollectionType.begin(); it != mCollectionType.end(); ++it)
{
collection_args += "&collection_chosen=" + std::string(*it);
}
- subs["COLLECTION"] = collection_args;
}
+ subs["COLLECTION"] = collection_args;
}
// Default to PG
diff --git a/indra/newview/llfloatersimplesnapshot.cpp b/indra/newview/llfloatersimplesnapshot.cpp
index 55b39d9193..4671f74d6d 100644
--- a/indra/newview/llfloatersimplesnapshot.cpp
+++ b/indra/newview/llfloatersimplesnapshot.cpp
@@ -54,87 +54,162 @@ void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, L
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("post_profile_image_coro", httpPolicy);
+ httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("post_thumbnail_image_coro", httpPolicy);
LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
LLCore::HttpHeaders::ptr_t httpHeaders;
LLCore::HttpOptions::ptr_t httpOpts = std::make_shared<LLCore::HttpOptions>();
httpOpts->setFollowRedirects(true);
- LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
+ // Retry stage-2 upload by re-requesting a fresh one-time uploader capability (up to 3 attempts total)
+ const S32 MAX_UPLOAD_RETRIES = 2;
+ S32 upload_retry_count = 0;
+ LLUUID result_uuid;
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status)
- {
- // todo: notification?
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
- return;
- }
- if (!result.has("uploader"))
+ while (upload_retry_count <= MAX_UPLOAD_RETRIES)
{
- // todo: notification?
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
- return;
- }
- std::string uploader_cap = result["uploader"].asString();
- if (uploader_cap.empty())
- {
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
- return;
- }
+ // Stage 1: Request uploader URL
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
- // Upload the image
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- LLCore::HttpRequest::ptr_t uploaderhttpRequest = std::make_shared<LLCore::HttpRequest>();
- LLCore::HttpHeaders::ptr_t uploaderhttpHeaders = std::make_shared<LLCore::HttpHeaders>();
- LLCore::HttpOptions::ptr_t uploaderhttpOpts = std::make_shared<LLCore::HttpOptions>();
- S64 length;
+ if (!status)
+ {
+ LL_WARNS("Thumbnail") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
+ return;
+ }
- {
- llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate);
- if (!instream.is_open())
+ if (!result.has("uploader"))
{
- LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL;
+ LL_WARNS("Thumbnail") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
return;
}
- length = instream.tellg();
- }
- uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional
- uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required!
- uploaderhttpOpts->setFollowRedirects(true);
+ std::string uploader_cap = result["uploader"].asString();
+ if (uploader_cap.empty())
+ {
+ LL_WARNS("Thumbnail") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
+ return;
+ }
- result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders);
+ // Stage 2: Upload the image
+ LLCore::HttpRequest::ptr_t uploaderhttpRequest = std::make_shared<LLCore::HttpRequest>();
+ LLCore::HttpHeaders::ptr_t uploaderhttpHeaders = std::make_shared<LLCore::HttpHeaders>();
+ LLCore::HttpOptions::ptr_t uploaderhttpOpts = std::make_shared<LLCore::HttpOptions>();
+ S64 length;
- httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ {
+ llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate);
+ if (!instream.is_open())
+ {
+ LL_WARNS("Thumbnail") << "Failed to open file " << path_to_image << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
+ return;
+ }
+ length = instream.tellg();
+ }
- LL_DEBUGS("Thumbnail") << result << LL_ENDL;
+ uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2");
+ uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, std::to_string(length));
+ uploaderhttpOpts->setFollowRedirects(true);
- if (!status)
- {
- LL_WARNS("Thumbnail") << "Failed to upload image " << status.toString() << LL_ENDL;
- return;
- }
+ result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders);
- if (result["state"].asString() != "complete")
- {
- if (result.has("message"))
- {
- LL_WARNS("Thumbnail") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL;
- }
- else
+ httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ LL_DEBUGS("Thumbnail") << result << LL_ENDL;
+
+ if (!status)
{
- LL_WARNS("Thumbnail") << "Failed to upload image " << result << LL_ENDL;
+ if (upload_retry_count < MAX_UPLOAD_RETRIES)
+ {
+ upload_retry_count++;
+ LL_WARNS("Thumbnail") << "Failed to upload image (attempt " << upload_retry_count
+ << " of " << (MAX_UPLOAD_RETRIES + 1) << "): " << status.toString()
+ << ", re-requesting uploader..." << LL_ENDL;
+ llcoro::suspendUntilTimeout(1.0f);
+ continue;
+ }
+ else
+ {
+ LL_WARNS("Thumbnail") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts: " << status.toString() << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
+ return;
+ }
}
- if (callback)
+ if (result["state"].asString() != "complete")
{
- callback(LLUUID());
+ if (upload_retry_count < MAX_UPLOAD_RETRIES)
+ {
+ upload_retry_count++;
+ if (result.has("message"))
+ {
+ LL_WARNS("Thumbnail") << "Failed to upload image, state " << result["state"]
+ << " message: " << result["message"] << " (attempt "
+ << upload_retry_count << " of " << (MAX_UPLOAD_RETRIES + 1)
+ << "), re-requesting uploader..." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Thumbnail") << "Failed to upload image (attempt " << upload_retry_count
+ << " of " << (MAX_UPLOAD_RETRIES + 1)
+ << "), re-requesting uploader..." << LL_ENDL;
+ }
+ llcoro::suspendUntilTimeout(1.0f);
+ continue;
+ }
+ else
+ {
+ if (result.has("message"))
+ {
+ LL_WARNS("Thumbnail") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts, state " << result["state"]
+ << " message: " << result["message"] << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Thumbnail") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts" << LL_ENDL;
+ }
+ if (callback)
+ {
+ callback(LLUUID());
+ }
+ LLFile::remove(path_to_image);
+ return;
+ }
}
- return;
+
+ // Success!
+ result_uuid = result["new_asset"].asUUID();
+ break;
}
if (first_data.has("category_id"))
@@ -143,7 +218,7 @@ void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, L
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat)
{
- cat->setThumbnailUUID(result["new_asset"].asUUID());
+ cat->setThumbnailUUID(result_uuid);
}
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat_id);
}
@@ -153,16 +228,18 @@ void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, L
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item)
{
- item->setThumbnailUUID(result["new_asset"].asUUID());
+ item->setThumbnailUUID(result_uuid);
}
- // Are we supposed to get BulkUpdateInventory?
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
}
if (callback)
{
- callback(result["new_asset"].asUUID());
+ callback(result_uuid);
}
+
+ // Cleanup
+ LLFile::remove(path_to_image);
}
///----------------------------------------------------------------------------
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index faf7ed0d8c..83d7a92846 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1043,7 +1043,7 @@ bool LLFloaterSnapshot::postBuild()
getChild<LLComboBox>("profile_size_combo")->selectNthItem(0);
getChild<LLComboBox>("postcard_size_combo")->selectNthItem(0);
getChild<LLComboBox>("texture_size_combo")->selectNthItem(0);
- getChild<LLComboBox>("local_size_combo")->selectNthItem(8);
+ getChild<LLComboBox>("local_size_combo")->selectNthItem(0);
getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
impl->mPreviewHandle = previewp->getHandle();
diff --git a/indra/newview/llfloatersounddevices.cpp b/indra/newview/llfloatersounddevices.cpp
deleted file mode 100644
index f11c5c0ad8..0000000000
--- a/indra/newview/llfloatersounddevices.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @file llfloatersounddevices.cpp
- * @author Leyla Farazha
- * @brief Sound Preferences used for minimal skin
- *
-* $LicenseInfo:firstyear=2011&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 "llfloatersounddevices.h"
-
-#include "lldraghandle.h"
-
-#include "llpanelvoicedevicesettings.h"
-
-// Library includes
-#include "indra_constants.h"
-
-// protected
-LLFloaterSoundDevices::LLFloaterSoundDevices(const LLSD& key)
-: LLTransientDockableFloater(NULL, false, key)
-{
- LLTransientFloaterMgr::getInstance()->addControlView(this);
-
- // force docked state since this floater doesn't save it between recreations
- setDocked(true);
-}
-
-LLFloaterSoundDevices::~LLFloaterSoundDevices()
-{
- LLTransientFloaterMgr::getInstance()->removeControlView(this);
-}
-
-// virtual
-bool LLFloaterSoundDevices::postBuild()
-{
- LLTransientDockableFloater::postBuild();
-
- updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
-
- LLPanelVoiceDeviceSettings* panel = findChild<LLPanelVoiceDeviceSettings>("device_settings_panel");
- if (panel)
- {
- panel->setUseTuningMode(false);
- getChild<LLUICtrl>("voice_input_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
- getChild<LLUICtrl>("voice_output_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
- getChild<LLUICtrl>("mic_volume_slider")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
- }
- return true;
-}
-
-//virtual
-void LLFloaterSoundDevices::setDocked(bool docked, bool pop_on_undock/* = true*/)
-{
- LLTransientDockableFloater::setDocked(docked, pop_on_undock);
-}
-
-// virtual
-void LLFloaterSoundDevices::setFocus(bool b)
-{
- LLTransientDockableFloater::setFocus(b);
-
- // Force using active floater transparency
- // We have to override setFocus() for because selecting an item of the
- // combobox causes the floater to lose focus and thus become transparent.
- updateTransparency(TT_ACTIVE);
-}
diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp
deleted file mode 100644
index 9f7c9aba87..0000000000
--- a/indra/newview/llfloatervoiceeffect.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/**
- * @file llfloatervoiceeffect.cpp
- * @author Aimee
- * @brief Selection and preview of voice effect.
- *
- * $LicenseInfo:firstyear=2010&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 "llfloatervoiceeffect.h"
-
-#include "llscrolllistctrl.h"
-#include "lltrans.h"
-#include "llweb.h"
-
-LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key)
- : LLFloater(key)
-{
- mCommitCallbackRegistrar.add("VoiceEffect.Record", boost::bind(&LLFloaterVoiceEffect::onClickRecord, this));
- mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this));
- mCommitCallbackRegistrar.add("VoiceEffect.Stop", boost::bind(&LLFloaterVoiceEffect::onClickStop, this));
-// mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this));
-}
-
-// virtual
-LLFloaterVoiceEffect::~LLFloaterVoiceEffect()
-{
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->removeObserver(this);
- }
- }
-}
-
-// virtual
-bool LLFloaterVoiceEffect::postBuild()
-{
- setDefaultBtn("record_btn");
- getChild<LLButton>("record_btn")->setFocus(true);
- getChild<LLUICtrl>("voice_morphing_link")->setTextArg("[URL]", LLTrans::getString("voice_morphing_url"));
-
- mVoiceEffectList = getChild<LLScrollListCtrl>("voice_effect_list");
- if (mVoiceEffectList)
- {
- mVoiceEffectList->setCommitCallback(boost::bind(&LLFloaterVoiceEffect::onClickPlay, this));
-// mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this));
- }
-
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->addObserver(this);
-
- // Disconnect from the current voice channel ready to record a voice sample for previewing
- effect_interface->enablePreviewBuffer(true);
- }
-
- refreshEffectList();
- updateControls();
-
- return true;
-}
-
-// virtual
-void LLFloaterVoiceEffect::onClose(bool app_quitting)
-{
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->enablePreviewBuffer(false);
- }
-}
-
-void LLFloaterVoiceEffect::refreshEffectList()
-{
- if (!mVoiceEffectList)
- {
- return;
- }
-
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (!effect_interface)
- {
- mVoiceEffectList->setEnabled(false);
- return;
- }
-
- LL_DEBUGS("Voice")<< "Rebuilding Voice Morph list."<< LL_ENDL;
-
- // Preserve selected items and scroll position
- S32 scroll_pos = mVoiceEffectList->getScrollPos();
- uuid_vec_t selected_items;
- std::vector<LLScrollListItem*> items = mVoiceEffectList->getAllSelected();
- for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++)
- {
- selected_items.push_back((*it)->getUUID());
- }
-
- mVoiceEffectList->deleteAllItems();
-
- {
- // Add the "No Voice Morph" entry
- LLSD element;
-
- element["id"] = LLUUID::null;
- element["columns"][NAME_COLUMN]["column"] = "name";
- element["columns"][NAME_COLUMN]["value"] = getString("no_voice_effect");
- element["columns"][NAME_COLUMN]["font"]["style"] = "BOLD";
-
- LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM);
- // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :(
- if(sl_item)
- {
- ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(LLFontGL::BOLD);
- }
- }
-
- // Add each Voice Morph template, if there are any (template list includes all usable effects)
- const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList();
- if (!template_list.empty())
- {
- for (voice_effect_list_t::const_iterator it = template_list.begin(); it != template_list.end(); ++it)
- {
- const LLUUID& effect_id = it->second;
-
- std::string localized_effect = "effect_" + it->first;
- std::string effect_name = hasString(localized_effect) ? getString(localized_effect) : it->first; // XML contains localized effects names
-
- LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id);
-
- // Tag the active effect.
- if (effect_id == LLVoiceClient::instance().getVoiceEffectDefault())
- {
- effect_name += " " + getString("active_voice_effect");
- }
-
- // Tag available effects that are new this session
- if (effect_properties["is_new"].asBoolean())
- {
- effect_name += " " + getString("new_voice_effect");
- }
-
- LLDate expiry_date = effect_properties["expiry_date"].asDate();
- bool is_template_only = effect_properties["template_only"].asBoolean();
-
- std::string font_style = "NORMAL";
- if (!is_template_only)
- {
- font_style = "BOLD";
- }
-
- LLSD element;
- element["id"] = effect_id;
-
- element["columns"][NAME_COLUMN]["column"] = "name";
- element["columns"][NAME_COLUMN]["value"] = effect_name;
- element["columns"][NAME_COLUMN]["font"]["style"] = font_style;
-
- element["columns"][1]["column"] = "expires";
- if (!is_template_only)
- {
- element["columns"][DATE_COLUMN]["value"] = expiry_date;
- element["columns"][DATE_COLUMN]["type"] = "date";
- }
- else {
- element["columns"][DATE_COLUMN]["value"] = getString("unsubscribed_voice_effect");
- }
-// element["columns"][DATE_COLUMN]["font"]["style"] = "NORMAL";
-
- LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM);
- // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :(
- if(sl_item)
- {
- LLFontGL::StyleFlags style = is_template_only ? LLFontGL::NORMAL : LLFontGL::BOLD;
- LLScrollListText* slt = dynamic_cast<LLScrollListText*>(sl_item->getColumn(0));
- llassert(slt);
- if (slt)
- {
- slt->setFontStyle(style);
- }
- }
- }
- }
-
- // Re-select items that were selected before, and restore the scroll position
- for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++)
- {
- mVoiceEffectList->selectByID(*it);
- }
- mVoiceEffectList->setScrollPos(scroll_pos);
- mVoiceEffectList->setEnabled(true);
-}
-
-void LLFloaterVoiceEffect::updateControls()
-{
- bool recording = false;
-
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- recording = effect_interface->isPreviewRecording();
- }
-
- getChild<LLButton>("record_btn")->setVisible(!recording);
- getChild<LLButton>("record_stop_btn")->setVisible(recording);
-}
-
-// virtual
-void LLFloaterVoiceEffect::onVoiceEffectChanged(bool effect_list_updated)
-{
- if (effect_list_updated)
- {
- refreshEffectList();
- }
- updateControls();
-}
-
-void LLFloaterVoiceEffect::onClickRecord()
-{
- LL_DEBUGS("Voice") << "Record clicked" << LL_ENDL;
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->recordPreviewBuffer();
- }
- updateControls();
-}
-
-void LLFloaterVoiceEffect::onClickPlay()
-{
- LL_DEBUGS("Voice") << "Play clicked" << LL_ENDL;
- if (!mVoiceEffectList)
- {
- return;
- }
-
- const LLUUID& effect_id = mVoiceEffectList->getCurrentID();
-
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->playPreviewBuffer(effect_id);
- }
- updateControls();
-}
-
-void LLFloaterVoiceEffect::onClickStop()
-{
- LL_DEBUGS("Voice") << "Stop clicked" << LL_ENDL;
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->stopPreviewBuffer();
- }
- updateControls();
-}
-
-//void LLFloaterVoiceEffect::onClickActivate()
-//{
-// LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
-// if (effect_interface && mVoiceEffectList)
-// {
-// effect_interface->setVoiceEffect(mVoiceEffectList->getCurrentID());
-// }
-//}
-
diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h
deleted file mode 100644
index 323beb64ae..0000000000
--- a/indra/newview/llfloatervoiceeffect.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * @file llfloatervoiceeffect.h
- * @author Aimee
- * @brief Selection and preview of voice effects.
- *
- * $LicenseInfo:firstyear=2010&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_LLFLOATERVOICEEFFECT_H
-#define LL_LLFLOATERVOICEEFFECT_H
-
-#include "llfloater.h"
-#include "llvoiceclient.h"
-
-class LLButton;
-class LLScrollListCtrl;
-
-class LLFloaterVoiceEffect
- : public LLFloater
- , public LLVoiceEffectObserver
-{
-public:
- LOG_CLASS(LLFloaterVoiceEffect);
-
- LLFloaterVoiceEffect(const LLSD& key);
- virtual ~LLFloaterVoiceEffect();
-
- bool postBuild() override;
- void onClose(bool app_quitting) override;
-
-private:
- enum ColumnIndex
- {
- NAME_COLUMN = 0,
- DATE_COLUMN = 1,
- };
-
- void refreshEffectList();
- void updateControls();
-
- /// Called by voice effect provider when voice effect list is changed.
- virtual void onVoiceEffectChanged(bool effect_list_updated) override;
-
- void onClickRecord();
- void onClickPlay();
- void onClickStop();
-// void onClickActivate();
-
- LLUUID mSelectedID;
- LLScrollListCtrl* mVoiceEffectList;
-};
-
-#endif
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
index ac8477a615..b784419780 100644
--- a/indra/newview/llgltfmateriallist.cpp
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -170,7 +170,7 @@ namespace
void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::string& data_in)
{
- std::istringstream str(data_in);
+ boost::iostreams::stream<boost::iostreams::array_source> str(data_in.data(), data_in.size());
LLSD data;
diff --git a/indra/newview/llgroupcolormap.cpp b/indra/newview/llgroupcolormap.cpp
new file mode 100644
index 0000000000..36fde1ce38
--- /dev/null
+++ b/indra/newview/llgroupcolormap.cpp
@@ -0,0 +1,150 @@
+/**
+ * @file llgroupcolormap.cpp
+ * @brief Per-group nameplate tint registry.
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgroupcolormap.h"
+
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llsdutil_math.h" // ll_sd_from_color4 / ll_color4_from_sd
+#include "llvoavatar.h" // LLVOAvatar::invalidateNameTags()
+
+static constexpr char GROUP_COLOR_FILE[] = "settings_group_colors.xml";
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+
+LLGroupColorMap::LLGroupColorMap()
+{
+}
+
+// ---------------------------------------------------------------------------
+// Public API
+// ---------------------------------------------------------------------------
+
+void LLGroupColorMap::setGroupColor(const LLUUID& group_id, const LLColor4& color)
+{
+ if (group_id.isNull())
+ return;
+
+ // Treat fully-transparent as "no color" (remove entry)
+ if (color.mV[VW] < 0.01f)
+ {
+ clearGroupColor(group_id);
+ return;
+ }
+
+ mColors[group_id] = color;
+ saveToDisk();
+ invalidateAllNameTags();
+}
+
+LLColor4 LLGroupColorMap::getGroupColor(const LLUUID& group_id) const
+{
+ if (group_id.isNull())
+ return LLColor4::transparent;
+
+ auto it = mColors.find(group_id);
+ if (it != mColors.end())
+ return it->second;
+
+ return LLColor4::transparent;
+}
+
+bool LLGroupColorMap::hasGroupColor(const LLUUID& group_id) const
+{
+ if (group_id.isNull())
+ return false;
+ return mColors.find(group_id) != mColors.end();
+}
+
+void LLGroupColorMap::clearGroupColor(const LLUUID& group_id)
+{
+ if (mColors.erase(group_id) > 0)
+ {
+ saveToDisk();
+ invalidateAllNameTags();
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Persistence
+// ---------------------------------------------------------------------------
+
+// static
+std::string LLGroupColorMap::getFilePath()
+{
+ std::string path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "");
+ if (!path.empty())
+ return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, GROUP_COLOR_FILE);
+ // Fall back to app_settings (before first login, path not yet set)
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, GROUP_COLOR_FILE);
+}
+
+void LLGroupColorMap::loadFromDisk()
+{
+ mColors.clear();
+
+ const std::string filepath = getFilePath();
+ if (!gDirUtilp->fileExists(filepath))
+ return;
+
+ llifstream stream(filepath.c_str());
+ if (!stream.is_open())
+ {
+ LL_WARNS("GroupColor") << "Cannot open " << filepath << LL_ENDL;
+ return;
+ }
+
+ LLSD data;
+ if (LLSDSerialize::fromXMLDocument(data, stream) < 0)
+ {
+ LL_WARNS("GroupColor") << "Failed to parse " << filepath << LL_ENDL;
+ return;
+ }
+
+ // Format: map of { group_uuid_string : [r, g, b, a] }
+ for (LLSD::map_const_iterator it = data.beginMap(); it != data.endMap(); ++it)
+ {
+ LLUUID group_id(it->first);
+ if (group_id.isNull()) continue;
+ LLColor4 color = ll_color4_from_sd(it->second);
+ if (color.mV[VW] >= 0.01f)
+ mColors[group_id] = color;
+ }
+
+ LL_INFOS("GroupColor") << "Loaded " << mColors.size()
+ << " group color(s) from " << filepath << LL_ENDL;
+}
+
+void LLGroupColorMap::saveToDisk() const
+{
+ const std::string filepath = getFilePath();
+
+ LLSD data = LLSD::emptyMap();
+ for (const auto& [group_id, color] : mColors)
+ data[group_id.asString()] = ll_sd_from_color4(color);
+
+ llofstream stream(filepath.c_str());
+ if (!stream.is_open())
+ {
+ LL_WARNS("GroupColor") << "Cannot write " << filepath << LL_ENDL;
+ return;
+ }
+ LLSDSerialize::toPrettyXML(data, stream);
+}
+
+// ---------------------------------------------------------------------------
+// Invalidation
+// ---------------------------------------------------------------------------
+
+// static
+void LLGroupColorMap::invalidateAllNameTags()
+{
+ LLVOAvatar::invalidateNameTags();
+}
diff --git a/indra/newview/llgroupcolormap.h b/indra/newview/llgroupcolormap.h
new file mode 100644
index 0000000000..d6f661c43a
--- /dev/null
+++ b/indra/newview/llgroupcolormap.h
@@ -0,0 +1,64 @@
+/**
+ * @file llgroupcolormap.h
+ * @brief Per-group nameplate tint registry.
+ *
+ * Stores a client-side color for each group UUID. When the group color is
+ * set, every avatar whose *active* group tag matches that UUID gets their
+ * nameplate rendered in that color instead of the default.
+ *
+ * Data is persisted to <account_dir>/settings_group_colors.xml so colors
+ * survive relogs. The file is keyed by group UUID string → LLColor4 LLSD.
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1 only.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGROUPCOLORMAP_H
+#define LL_LLGROUPCOLORMAP_H
+
+#include "llsingleton.h"
+#include "lluuid.h"
+#include "v4color.h"
+#include <unordered_map>
+
+class LLGroupColorMap : public LLSingleton<LLGroupColorMap>
+{
+ LLSINGLETON(LLGroupColorMap);
+ ~LLGroupColorMap() = default;
+ LOG_CLASS(LLGroupColorMap);
+
+public:
+ // ---- Color CRUD ---------------------------------------------------------
+
+ /** Set (or clear) the nameplate tint for a group.
+ * Pass LLColor4::transparent (alpha == 0) to remove the color entry. */
+ void setGroupColor(const LLUUID& group_id, const LLColor4& color);
+
+ /** Return the tint for @p group_id, or LLColor4::transparent if none. */
+ LLColor4 getGroupColor(const LLUUID& group_id) const;
+
+ /** True if a non-transparent color is stored for this group. */
+ bool hasGroupColor(const LLUUID& group_id) const;
+
+ /** Remove the color entry for this group. */
+ void clearGroupColor(const LLUUID& group_id);
+
+ // ---- Persistence --------------------------------------------------------
+ void loadFromDisk();
+ void saveToDisk() const;
+
+ // ---- Cache invalidation -------------------------------------------------
+ /** Called after a color is changed so nametags rebuild on next idle. */
+ static void invalidateAllNameTags();
+
+private:
+ static std::string getFilePath();
+
+ // group_uuid → RGBA color (std::hash<LLUUID> is specialised in lluuid.h)
+ std::unordered_map<LLUUID, LLColor4> mColors;
+};
+
+#endif // LL_LLGROUPCOLORMAP_H
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 7659e5f082..074cda1683 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -317,7 +317,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL
// virtual
bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
- // Why is "new group" sufficient?
+ // "new group" is sufficient because update_group_floaters always calls that on group changes
if (event->desc() == "new group")
{
setDirty();
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 11f049564a..4327d281e5 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -301,7 +301,7 @@ void LLHUDNameTag::renderText()
const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f)));
label_top_rect.mBottom = label_top_rect.mTop - label_height;
LLColor4 label_top_color = text_color;
- label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor;
+ label_top_color.mV[VALPHA] = bubble_opacity() * alpha_factor;
mRoundedRectTopImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);
}
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 779ed725ac..54d17be370 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -1206,7 +1206,8 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
case IM_LURE_USER:
case IM_TELEPORT_REQUEST:
{
- if (is_muted)
+ static LLCachedControl<bool> block_teleport_offers(gSavedSettings, "BlockTeleportOffers");
+ if (is_muted || block_teleport_offers)
{
return;
}
@@ -1485,6 +1486,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
LLNotification::Params params("OfferFriendship");
params.substitutions = args;
params.payload = payload;
+ params.offer_from_agent = true;
LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
}
}
@@ -1533,7 +1535,7 @@ void LLIMProcessing::requestOfflineMessages()
&& isAgentAvatarValid()
&& gAgent.getRegion()
&& gAgent.getRegion()->capabilitiesReceived()
- && (LLMuteList::getInstance()->isLoaded() || LLMuteList::getInstance()->getLoadFailed()))
+ && LLMuteList::getInstance()->updateLoadState())
{
std::string cap_url = gAgent.getRegionCapability("ReadOfflineMsgs");
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index f3cef660f6..0a260b9916 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -91,8 +91,7 @@ const S32 XL8_PADDING = 3; // XL8_START_TAG.size() + XL8_END_TAG.size()
const static U32 SESSION_INITIALIZATION_TIMEOUT = 30;
// This enum corresponds to the sim's and adds P2P_CHAT_SESSION,
-// as webrtc uses the multiagent chat mechanism for p2p calls,
-// instead of relying on vivox calling.
+// as webrtc uses the multiagent chat mechanism for p2p calls.
// Don't change this without consulting a server developer.
enum EMultiAgentChatSessionType
{
@@ -1945,12 +1944,6 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
- // Old call to send messages to SLim client, no longer supported.
- //if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
- //{
- // // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
- // sent = LLVoiceClient::getInstance()->sendTextMessage(other_participant_id, utf8_text);
- //}
if(!sent)
{
@@ -3090,8 +3083,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
{
if (type == IM_SESSION_P2P_INVITE)
{
- // decline p2p voice, either via the vivox-style call mechanism
- // or via the webrtc-style "decline p2p" mechanism.
+ // decline p2p voice, via the webrtc-style "decline p2p" mechanism.
LLVoiceP2PIncomingCallInterfacePtr call = LLVoiceClient::getInstance()->getIncomingCallInterface(payload["voice_channel_info"]);
if (call)
{
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 7d9fad5a54..7605887f6c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -336,7 +336,7 @@ bool LLInvFVBridge::cutToClipboard()
const LLInventoryObject* obj = gInventory.getObject(mUUID);
if (obj && isItemMovable() && isItemRemovable())
{
- const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
const bool cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id);
if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) ||
@@ -1378,7 +1378,7 @@ bool LLInvFVBridge::isInboxFolder() const
bool LLInvFVBridge::isMarketplaceListingsFolder() const
{
- const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID folder_id = gInventory.getMarketplaceListingsUUID();
if (folder_id.isNull())
{
@@ -1686,7 +1686,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const
{
std::string error_msg;
LLInventoryModel* model = getInventoryModel();
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID();
if (marketplacelistings_id.notNull())
{
LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id);
@@ -1845,7 +1845,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
{
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
// Note: For a single item, if it's not a copy, then it's a move
move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action));
}
@@ -1912,6 +1912,11 @@ void LLItemBridge::doShowOnMap(LLLandmark* landmark)
void copy_slurl_to_clipboard_callback_inv(const std::string& slurl)
{
+ if (slurl.empty())
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ return;
+ }
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
LLSD args;
args["SLURL"] = slurl;
@@ -2685,7 +2690,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
const LLUUID from_folder_uuid = inv_cat->getParentUUID();
const bool move_is_into_current_outfit = (mUUID == current_outfit_id);
@@ -3765,7 +3770,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
{
LLInventoryCategory * cat = gInventory.getCategory(mUUID);
if (!cat) return;
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action)));
}
else if ("copy_folder_uuid" == action)
@@ -4019,7 +4024,7 @@ void LLFolderBridge::pasteFromClipboard()
LLInventoryModel* model = getInventoryModel();
if (model && isClipboardPasteable())
{
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID();
const bool paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
bool cut_from_marketplacelistings = false;
@@ -4081,7 +4086,7 @@ void LLFolderBridge::perform_pasteFromClipboard()
if (model && isClipboardPasteable())
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
@@ -4378,7 +4383,7 @@ void LLFolderBridge::pasteLinkFromClipboard()
if(model)
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
const bool move_is_into_current_outfit = (mUUID == current_outfit_id);
@@ -4478,7 +4483,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
- const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplace_listings_id = model->getMarketplaceListingsUUID();
const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
if (outfits_id == mUUID)
@@ -5717,7 +5722,7 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
const LLUUID from_folder_uuid = inv_item->getParentUUID();
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 3cc57e851f..a6fda946ef 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -405,7 +405,7 @@ void update_all_marketplace_count(const LLUUID& cat_id)
void update_all_marketplace_count()
{
// Get the marketplace root and launch the recursive exploration
- const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID();
if (!marketplace_listings_uuid.isNull())
{
update_all_marketplace_count(marketplace_listings_uuid);
@@ -634,12 +634,6 @@ bool get_is_item_worn(const LLUUID& id, const LLViewerInventoryItem* item)
return false;
}
- // Consider the item as worn if it has links in COF.
- if (LLAppearanceMgr::instance().isLinkedInCOF(id))
- {
- return true;
- }
-
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
@@ -1050,11 +1044,7 @@ void open_marketplace_listings()
S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
{
- // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none
- // Todo: findCategoryUUIDForType is somewhat expensive with large
- // flat root folders yet we use depth_nesting_in_marketplace at
- // every turn, find a way to correctly cache this id.
- const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID();
if (marketplace_listings_uuid.isNull())
{
return -1;
@@ -2559,7 +2549,7 @@ bool get_is_favorite(const LLUUID& obj_id)
return obj && obj->getIsFavorite();
}
- return object->getIsFavorite();
+ return object && object->getIsFavorite();
}
void set_favorite(const LLUUID& obj_id, bool favorite)
@@ -3420,7 +3410,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
if ("delete" == action)
{
- const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
bool marketplacelistings_item = false;
bool has_worn = false;
bool needs_replacement = false;
@@ -3601,7 +3591,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
if (action == "wear" || action == "wear_add")
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
- const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID mp_id = gInventory.getMarketplaceListingsUUID();
std::copy_if(selected_uuid_set.begin(),
selected_uuid_set.end(),
std::back_inserter(ids),
@@ -4011,7 +4001,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root)
// target listing *and* the original listing. So we need to keep track of both.
// Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt.
sMarketplaceFolders.clear();
- const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.isNull())
{
return;
diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp
index f77088e0b1..24b0866041 100644
--- a/indra/newview/llinventorygallery.cpp
+++ b/indra/newview/llinventorygallery.cpp
@@ -1726,7 +1726,7 @@ bool is_category_removable(const LLUUID& folder_id, bool check_worn)
}
}
- const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID mp_id = gInventory.getMarketplaceListingsUUID();
if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id))
{
return false;
@@ -1768,7 +1768,7 @@ void LLInventoryGallery::paste()
return;
}
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (mSelectedItemIDs.size() == 1 && gInventory.isObjectDescendentOf(*mSelectedItemIDs.begin(), marketplacelistings_id))
{
return;
@@ -2114,7 +2114,7 @@ void LLInventoryGallery::pasteAsLink()
}
const LLUUID& current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
std::vector<LLUUID> objects;
@@ -3333,7 +3333,7 @@ bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop,
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
const bool move_is_into_current_outfit = (folder_id == current_outfit_id);
@@ -3727,7 +3727,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID();
//const LLUUID from_folder_uuid = inv_cat->getParentUUID();
const bool move_is_into_current_outfit = (dest_id == current_outfit_id);
const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(dest_id, marketplacelistings_id);
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index 22f6414960..ff7cab0ee3 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -409,7 +409,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
if (can_copy)
{
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (itemp)
{
move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation);
@@ -428,7 +428,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
// option == 0 Move no copy item(s)
// option == 1 Don't move no copy item(s) (leave them behind)
bool copy_and_move = option == 0;
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
// main inventory only allows one item?
LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front());
@@ -563,7 +563,7 @@ bool can_list_on_marketplace(const LLUUID &id)
if (can_list)
{
std::string error_msg;
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.notNull())
{
LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id);
@@ -1065,7 +1065,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
// Marketplace
bool can_list = false;
- const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType())
{
if (is_folder)
diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp
index a435a4f7c7..aa6ba6d023 100644
--- a/indra/newview/llinventorylistitem.cpp
+++ b/indra/newview/llinventorylistitem.cpp
@@ -41,7 +41,7 @@
#include "llinventorymodel.h"
#include "llviewerinventory.h"
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item");
constexpr S32 WIDGET_SPACING = 3;
constexpr S32 FAVORITE_IMAGE_SIZE = 14;
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3a7bc20c30..2657f11d0e 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -433,6 +433,8 @@ LLInventoryModel::LLInventoryModel()
: // These are now ordered, keep them that way.
mBacklinkMMap(),
mIsAgentInvUsable(false),
+ mLibrarySkeletonLoadTime(0.f),
+ mAgentSkeletonLoadTime(0.f),
mRootFolderID(),
mLibraryRootFolderID(),
mLibraryOwnerID(),
@@ -975,6 +977,15 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp
return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID());
}
+const LLUUID LLInventoryModel::getMarketplaceListingsUUID()
+{
+ if (mMarketplaceListingsUUID.isNull())
+ {
+ mMarketplaceListingsUUID = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ }
+ return mMarketplaceListingsUUID;
+}
+
// Convenience function to create a new category. You could call
// updateCategory() with a newly generated UUID category, but this
// version will take care of details like what the name should be
@@ -1692,7 +1703,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32
mask |= LLInventoryObserver::LABEL;
}
// Under marketplace, category labels are quite complex and need extra upate
- const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplace_id = getMarketplaceListingsUUID();
if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id))
{
mask |= LLInventoryObserver::LABEL;
@@ -2374,10 +2385,22 @@ void LLInventoryModel::cache(
items,
INCLUDE_TRASH,
can_cache);
+
+ if (categories.empty() && items.empty())
+ {
+ LL_WARNS(LOG_INV) << "Nothing to cache for " << parent_folder_id << LL_ENDL;
+ return;
+ }
+
// Use temporary file to avoid potential conflicts with other
// instances (even a 'read only' instance unzips into a file)
std::string temp_file = gDirUtilp->getTempFilename();
- saveToFile(temp_file, categories, items);
+ if (!saveToFile(temp_file, categories, items))
+ {
+ LL_WARNS(LOG_INV) << "Failed to save inventory cache for " << parent_folder_id << LL_ENDL;
+ LLFile::remove(temp_file);
+ return;
+ }
std::string gzip_filename = getInvCacheAddres(agent_id);
gzip_filename.append(".gz");
if(gzip_file(temp_file, gzip_filename))
@@ -2980,6 +3003,16 @@ bool LLInventoryModel::loadSkeleton(
<< " after " << timer.getElapsedTimeF32() << " seconds."
<< LL_ENDL;
+ const F32 elapsed = timer.getElapsedTimeF32();
+ if (owner_id == mLibraryOwnerID)
+ {
+ mLibrarySkeletonLoadTime = elapsed;
+ }
+ else
+ {
+ mAgentSkeletonLoadTime = elapsed;
+ }
+
return rv;
}
@@ -3416,6 +3449,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
LLSD inventory;
if (!is_cache_obsolete)
{
+ LL_PROFILE_ZONE_NAMED("inventory load from file - llsd parse");
LLPointer<LLSDParser> parser = new LLSDBinaryParser();
if (parser->parse(file, inventory, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
@@ -3427,56 +3461,61 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
if (!is_cache_obsolete)
{
- const LLSD& llsd_cats = inventory["categories"];
- if (llsd_cats.isArray())
{
- LLSD::array_const_iterator iter = llsd_cats.beginArray();
- LLSD::array_const_iterator end = llsd_cats.endArray();
- for (; iter != end; ++iter)
+ LL_PROFILE_ZONE_NAMED("inventory load from file - categories");
+ const LLSD& llsd_cats = inventory["categories"];
+ if (llsd_cats.isArray())
{
- LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
- if (inv_cat->importLLSDMap(*iter))
+ LLSD::array_const_iterator iter = llsd_cats.beginArray();
+ LLSD::array_const_iterator end = llsd_cats.endArray();
+ for (; iter != end; ++iter)
{
- categories.push_back(inv_cat);
+ LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
+ if (inv_cat->importLLSDMap(*iter))
+ {
+ categories.push_back(inv_cat);
+ }
}
}
}
- const LLSD& llsd_items = inventory["items"];
- if (llsd_items.isArray())
{
- LLSD::array_const_iterator iter = llsd_items.beginArray();
- LLSD::array_const_iterator end = llsd_items.endArray();
- for (; iter != end; ++iter)
+ LL_PROFILE_ZONE_NAMED("inventory load from file - items");
+ const LLSD& llsd_items = inventory["items"];
+ if (llsd_items.isArray())
{
- LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
- if (inv_item->fromLLSD(*iter))
+ LLSD::array_const_iterator iter = llsd_items.beginArray();
+ LLSD::array_const_iterator end = llsd_items.endArray();
+ for (; iter != end; ++iter)
{
- if (inv_item->getUUID().isNull())
+ LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
+ if (inv_item->fromLLSD(*iter))
{
- LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: "
- << inv_item->getName() << LL_ENDL;
- }
- else
- {
- if (inv_item->getType() == LLAssetType::AT_UNKNOWN)
+ if (inv_item->getUUID().isNull())
{
- cats_to_update.insert(inv_item->getParentUUID());
+ LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: " << inv_item->getName() << LL_ENDL;
}
else
{
- items.push_back(inv_item);
+ if (inv_item->getType() == LLAssetType::AT_UNKNOWN)
+ {
+ cats_to_update.insert(inv_item->getParentUUID());
+ }
+ else
+ {
+ items.push_back(inv_item);
+ }
}
}
- }
- // TODO(brad) - figure out how to reenable this without breaking everything else
- // static constexpr U64 BATCH_SIZE = 512U;
- // if ((++lines_count % BATCH_SIZE) == 0)
- // {
- // // SL-19968 - make sure message system code gets a chance to run every so often
- // pump_idle_startup_network();
- // }
+ // TODO(brad) - figure out how to reenable this without breaking everything else
+ // static constexpr U64 BATCH_SIZE = 512U;
+ // if ((++lines_count % BATCH_SIZE) == 0)
+ // {
+ // // SL-19968 - make sure message system code gets a chance to run every so often
+ // pump_idle_startup_network();
+ // }
+ }
}
}
}
@@ -3522,6 +3561,11 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
S32 cat_count = 0;
for (auto& cat : categories)
{
+ if (cat.isNull())
+ {
+ LL_WARNS(LOG_INV) << "Skipping null category during inventory save" << LL_ENDL;
+ continue;
+ }
if (cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
LLSD sd;
@@ -3536,6 +3580,11 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
auto it_count = items.size();
for (auto& item : items)
{
+ if (item.isNull())
+ {
+ LL_WARNS(LOG_INV) << "Skipping null item during inventory save" << LL_ENDL;
+ continue;
+ }
LLSD sd;
item->asLLSD(sd);
item_array.append(sd);
@@ -3552,6 +3601,12 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
LL_INFOS(LOG_INV) << "Inventory saved: " << (S32)cat_count << " categories, " << (S32)it_count << " items." << LL_ENDL;
}
+ catch(std::bad_alloc&)
+ {
+ // We are quiting, so just log an error and move on.
+ LL_WARNS(LOG_INV) << "Failed to save inventory to cache due to memory allocation failure." << LL_ENDL;
+ return false;
+ }
catch (...)
{
LOG_UNHANDLED_EXCEPTION("");
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 2859923df9..3aaba69a60 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -158,8 +158,12 @@ protected:
public:
// The inventory model usage is sensitive to the initial construction of the model
bool isInventoryUsable() const;
+ F32 getLibrarySkeletonLoadTime() const { return mLibrarySkeletonLoadTime; }
+ F32 getAgentSkeletonLoadTime() const { return mAgentSkeletonLoadTime; }
private:
bool mIsAgentInvUsable; // used to handle an invalid inventory state
+ F32 mLibrarySkeletonLoadTime;
+ F32 mAgentSkeletonLoadTime;
// One-time initialization of HTTP system.
void initHttpRequest();
@@ -201,13 +205,13 @@ private:
// the inventory using several different identifiers.
// mInventory member data is the 'master' list of inventory, and
// mCategoryMap and mItemMap store uuid->object mappings.
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
+ typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
+ typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryItem>> item_map_t;
cat_map_t mCategoryMap;
item_map_t mItemMap;
// This last set of indices is used to map parents to children.
- typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
- typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
+ typedef std::unordered_map<LLUUID, cat_array_t*> parent_cat_map_t;
+ typedef std::unordered_map<LLUUID, item_array_t*> parent_item_map_t;
parent_cat_map_t mParentChildCategoryTree;
parent_item_map_t mParentChildItemTree;
@@ -329,6 +333,8 @@ public:
// user specified one or it does not exist, creates default category if it is missing.
const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const;
+ const LLUUID getMarketplaceListingsUUID();
+
// Get whatever special folder this object is a child of, if any.
const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
@@ -361,6 +367,8 @@ public:
private:
mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups
+ LLUUID mMarketplaceListingsUUID;
+
//--------------------------------------------------------------------
// Count
//--------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 1e5f771ba7..b02b2e2eb9 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -192,6 +192,8 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch():
mFetchCount(0),
mLastFetchCount(0),
mFetchFolderCount(0),
+ mInitialFetchDuration(0.f),
+ mInitialFetchDurationCaptured(false),
mAllRecursiveFoldersFetched(false),
mRecursiveInventoryFetchStarted(false),
mRecursiveLibraryFetchStarted(false),
@@ -199,6 +201,15 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch():
mMinTimeBetweenFetches(0.3f)
{}
+void LLInventoryModelBackgroundFetch::markFetchStarted()
+{
+ if (!mBackgroundFetchActive)
+ {
+ mFetchStartTimer.reset();
+ }
+ mBackgroundFetchActive = true;
+}
+
LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
{
gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, nullptr);
@@ -289,7 +300,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive)
// it's a folder, do a bulk fetch
LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
- mBackgroundFetchActive = true;
+ markFetchStarted();
mFolderFetchActive = true;
EFetchType recursion_type = recursive ? FT_RECURSIVE : FT_DEFAULT;
if (id.isNull())
@@ -376,7 +387,7 @@ void LLInventoryModelBackgroundFetch::scheduleFolderFetch(const LLUUID& cat_id,
{
if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id)
{
- mBackgroundFetchActive = true;
+ markFetchStarted();
mFolderFetchActive = true;
if (forced)
@@ -403,7 +414,7 @@ void LLInventoryModelBackgroundFetch::scheduleItemFetch(const LLUUID& item_id, b
{
if (mFetchItemQueue.empty() || mFetchItemQueue.front().mUUID != item_id)
{
- mBackgroundFetchActive = true;
+ markFetchStarted();
if (forced)
{
// check if already requested
@@ -447,7 +458,7 @@ void LLInventoryModelBackgroundFetch::fetchFolderAndLinks(const LLUUID& cat_id,
});
// start idle loop to track completion
- mBackgroundFetchActive = true;
+ markFetchStarted();
mFolderFetchActive = true;
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, nullptr);
}
@@ -489,14 +500,14 @@ void LLInventoryModelBackgroundFetch::fetchCOF(nullary_func_t callback)
});
// start idle loop to track completion
- mBackgroundFetchActive = true;
+ markFetchStarted();
mFolderFetchActive = true;
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, nullptr);
}
void LLInventoryModelBackgroundFetch::findLostItems()
{
- mBackgroundFetchActive = true;
+ markFetchStarted();
mFolderFetchActive = true;
mFetchFolderQueue.emplace_back(LLUUID::null, FT_RECURSIVE);
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, nullptr);
@@ -515,13 +526,18 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
mFolderFetchActive = false;
if (isBulkFetchProcessingComplete())
{
+ if (mAllRecursiveFoldersFetched && !mInitialFetchDurationCaptured)
+ {
+ mInitialFetchDuration = mFetchStartTimer.getElapsedTimeF32();
+ mInitialFetchDurationCaptured = true;
+ }
mBackgroundFetchActive = false;
}
// For now only informs about initial fetch being done
mFoldersFetchedSignal();
- LL_INFOS(LOG_INV) << "Inventory background fetch completed" << LL_ENDL;
+ LL_INFOS(LOG_INV) << "Inventory background fetch completed after: " << mFetchStartTimer.getElapsedTimeF32() << LL_ENDL;
}
boost::signals2::connection LLInventoryModelBackgroundFetch::setFetchCompletionCallback(folders_fetched_callback_t cb)
@@ -828,7 +844,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis()
// Intent is for marketplace request to happen after
// main inventory is done, unless requested by floater
mRecursiveMarketplaceFetchStarted = true;
- const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.notNull())
{
mFetchFolderQueue.emplace_front(marketplacelistings_id, FT_FOLDER_AND_CONTENT);
@@ -843,6 +859,11 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis()
if (isBulkFetchProcessingComplete())
{
+ if (mAllRecursiveFoldersFetched && !mInitialFetchDurationCaptured)
+ {
+ mInitialFetchDuration = mFetchStartTimer.getElapsedTimeF32();
+ mInitialFetchDurationCaptured = true;
+ }
mBackgroundFetchActive = false;
}
}
diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index ef6fa06e9f..6a5e0f66ff 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -70,6 +70,7 @@ public:
bool inventoryFetchStarted() const;
bool inventoryFetchCompleted() const;
bool inventoryFetchInProgress() const;
+ F32 getInitialFetchDuration() const { return mInitialFetchDuration; }
void findLostItems();
void incrFetchCount(S32 fetching);
@@ -120,6 +121,8 @@ protected:
bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
private:
+ void markFetchStarted();
+
bool mRecursiveInventoryFetchStarted;
bool mRecursiveLibraryFetchStarted;
bool mRecursiveMarketplaceFetchStarted; // AIS3 specific
@@ -133,6 +136,9 @@ private:
S32 mLastFetchCount; // for debug
S32 mFetchFolderCount;
+ LLFrameTimer mFetchStartTimer;
+ F32 mInitialFetchDuration;
+ bool mInitialFetchDurationCaptured;
LLFrameTimer mFetchTimer;
F32 mMinTimeBetweenFetches;
fetch_queue_t mFetchFolderQueue;
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 9919dd5f8f..039567ea76 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1855,6 +1855,7 @@ void LLInventoryPanel::purgeSelectedItems()
{
if (!mFolderRoot.get()) return;
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
const std::set<LLFolderViewItem*> inventory_selected = mFolderRoot.get()->getSelectionList();
if (inventory_selected.empty()) return;
LLSD args;
@@ -1864,12 +1865,17 @@ void LLInventoryPanel::purgeSelectedItems()
it != end_it;
++it)
{
+ // Selection allows items outside trash folder, only count the ones inside.
LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
- count += items.size() + cats.size();
- selected_items.push_back(item_id);
+ LLInventoryObject* obj = gInventory.getObject(item_id);
+ if (obj->getParentUUID() == trash_id)
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
+ count += items.size() + cats.size();
+ selected_items.push_back(item_id);
+ }
}
args["COUNT"] = static_cast<S32>(count);
LLNotificationsUtil::add("PurgeSelectedItems", args, LLSD(), boost::bind(callbackPurgeSelectedItems, _1, _2, selected_items));
@@ -2125,8 +2131,7 @@ LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id)
{
LL_PROFILE_ZONE_SCOPED;
- std::map<LLUUID, LLFolderViewItem*>::iterator map_it;
- map_it = mItemMap.find(id);
+ auto map_it = mItemMap.find(id);
if (map_it != mItemMap.end())
{
return map_it->second;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 644e0a1855..a17817c764 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -301,7 +301,7 @@ protected:
LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge;
Params mParams; // stored copy of parameter block
- std::map<LLUUID, LLFolderViewItem*> mItemMap;
+ std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap;
/**
* Pointer to LLInventoryFolderViewModelBuilder.
*
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 6e56aac270..1329b1308d 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -596,7 +596,7 @@ void LLLocalBitmap::updateUserVolumes(LLUUID old_id, LLUUID new_id, U32 channel)
if (object->isSculpted() && object->getVolume() &&
object->getVolume()->getParams().getSculptID() == old_id)
{
- LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams* old_params = object->getSculptParams();
LLSculptParams new_params(*old_params);
new_params.setSculptTexture(new_id, (*old_params).getSculptType());
object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, true);
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 0358233637..2f0a52e78b 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -134,6 +134,7 @@ void LLLoginInstance::reconnect()
{
// Sort of like connect, only using the pre-existing
// request params.
+ mAttemptComplete = false;
std::vector<std::string> uris;
LLGridManager::getInstance()->getLoginURIs(uris);
mLoginModule->connect(uris.front(), mRequestData);
@@ -387,7 +388,7 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
relnotes = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (!LLStringUtil::endsWith(relnotes, "/"))
relnotes += "/";
- relnotes += LLURI::escape(login_version) + ".html";
+ relnotes += "#" + LLURI::escape(login_version); // + ".html";
}
if (gViewerWindow)
diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp
index 51c38aba3a..0a90cf0699 100644
--- a/indra/newview/llmachineid.cpp
+++ b/indra/newview/llmachineid.cpp
@@ -398,6 +398,8 @@ bool getSerialNumber(unsigned char *unique_id, size_t len)
S32 LLMachineID::init()
{
+ LL_PROFILE_ZONE_SCOPED;
+
size_t len = sizeof(static_unique_id);
memset(static_unique_id, 0, len);
S32 ret_code = 0;
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index ac2f52a262..30f634f6d4 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -850,7 +850,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot
// Get/Post/Put requests to the SLM Server using the SLM API
void LLMarketplaceData::getSLMListings()
{
- const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplaceFolderId = gInventory.getMarketplaceListingsUUID();
setUpdating(marketplaceFolderId, true);
LLCoros::instance().launch("getSLMListings",
@@ -1757,7 +1757,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth)
}
else
{
- const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID();
std::set<LLUUID>::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid);
if (it != mPendingUpdateSet.end())
{
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index 1279b77ad4..c04f874923 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -33,9 +33,42 @@
#include "httprequest.h"
#include "httpheaders.h"
#include "httpoptions.h"
+#include <boost/container_hash/hash.hpp>
class LLViewerRegion;
+// struct for TE-specific material ID query
+class TEMaterialPair
+{
+public:
+ U32 te;
+ LLMaterialID materialID;
+
+ bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
+};
+
+inline bool operator<(const TEMaterialPair& lhs, const TEMaterialPair& rhs)
+{
+ return (lhs.te < rhs.te) ? true : (lhs.materialID < rhs.materialID);
+}
+
+// std::hash implementation for TEMaterialPair
+namespace std
+{
+ template<>
+ struct hash<TEMaterialPair>
+ {
+ inline size_t operator()(const TEMaterialPair& p) const noexcept
+ {
+ // Utilize boost::hash_combine to generate a good hash
+ size_t seed = 0;
+ boost::hash_combine(seed, p.te + 1);
+ boost::hash_combine(seed, p.materialID);
+ return seed;
+ }
+ };
+} // namespace std
+
class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
{
LLSINGLETON(LLMaterialMgr);
@@ -83,29 +116,6 @@ private:
void onRegionRemoved(LLViewerRegion* regionp);
private:
- // struct for TE-specific material ID query
- class TEMaterialPair
- {
- public:
-
- U32 te;
- LLMaterialID materialID;
-
- bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
- };
-
- // definitions follow class
- friend std::hash<TEMaterialPair>;
- friend size_t hash_value(const TEMaterialPair&) noexcept;
-
- friend inline bool operator<(
- const LLMaterialMgr::TEMaterialPair& lhs,
- const LLMaterialMgr::TEMaterialPair& rhs)
- {
- return (lhs.te < rhs.te) ? true :
- (lhs.materialID < rhs.materialID);
- }
-
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
@@ -113,7 +123,7 @@ private:
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
- typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
+ typedef std::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
typedef std::set<LLUUID> getall_queue_t;
typedef std::map<LLUUID, F64> getall_pending_map_t;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
@@ -142,23 +152,5 @@ private:
U32 getMaxEntries(const LLViewerRegion* regionp);
};
-// std::hash implementation for TEMaterialPair
-namespace std
-{
- template<> struct hash<LLMaterialMgr::TEMaterialPair>
- {
- inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept
- {
- return size_t((p.te + 1) * p.materialID.getDigest64());
- }
- };
-}
-
-// For use with boost containers.
-inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept
-{
- return size_t((p.te + 1) * p.materialID.getDigest64());
-}
-
#endif // LL_LLMATERIALMGR_H
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index c7b60b2fd5..4a808ba052 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -739,7 +739,7 @@ bool LLMediaCtrl::ensureMediaSourceExists()
mMediaSource->setUsedInUI(true);
mMediaSource->setHomeURL(mHomePageUrl, mHomePageMimeType);
mMediaSource->setTarget(mTarget);
- mMediaSource->setVisible( getVisible() );
+ mMediaSource->setVisible( isInVisibleChain() );
mMediaSource->addObserver( this );
mMediaSource->setBackgroundColor( getBackgroundColor() );
mMediaSource->setTrustedBrowser(mTrusted);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index c0b1a5326a..fb6ecedcbf 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -2847,8 +2847,44 @@ void LLMeshUploadThread::packModelIntance(
texture_index.find(texture) == texture_index.end())
{
texture_index[texture] = texture_num;
- std::string str = texture_str.str();
- res["texture_list"][texture_num] = LLSD::Binary(str.begin(), str.end());
+ if (include_textures)
+ {
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(), str.end());
+ }
+ else
+ { // When not including the whole texture, we need to send some metadata about the image
+ // to ensure accurate price estimation. If not included, the server will assume all
+ // textures are 1024 x 1024, which could lead to a low estimate.
+ LLSD info = LLSD::emptyMap();
+
+ S32 texture_width = 0;
+ S32 texture_height = 0;
+ if (texture->hasSavedRawImage())
+ {
+ LLImageDataLock lock(texture->getSavedRawImage());
+
+ LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+ if (!upload_file.isNull() && upload_file->getDataSize() && !upload_file->isBufferInvalid())
+ {
+ texture_width = upload_file->getWidth();
+ texture_height = upload_file->getHeight();
+ }
+ }
+
+ if ((texture_width <= 0) || (texture_height <= 0))
+ {
+ // Fall back to the texture's stored dimensions if we can't get dimensions from the raw image.
+ texture_width = texture->getFullWidth();
+ texture_height = texture->getFullHeight();
+ }
+
+ info["width"] = texture_width;
+ info["height"] = texture_height;
+ res["texture_info"][texture_num] = info;
+ res["texture_list"][texture_num] = LLSD::Binary(); // empty binary to indicate texture is not included, for older server compatibility
+ }
// store indexes for error handling;
texture_list_dest.push_back(material.mDiffuseMapFilename);
texture_num++;
@@ -2881,8 +2917,8 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, std::vector<std::string>&
LLSD res;
if (mDestinationFolderId.isNull())
{
- result["folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_OBJECT);
- result["texture_folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
+ result["folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ result["texture_folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
}
else
{
@@ -3331,6 +3367,8 @@ void LLMeshRepoThread::notifyLoadedMeshes()
loaded_queue.swap(mLoadedQ);
mLoadedMutex->unlock();
+ LL_PROFILE_ZONE_NAMED("notify loaded meshes");
+
update_metrics = true;
// Process the elements free of the lock
@@ -3362,6 +3400,8 @@ void LLMeshRepoThread::notifyLoadedMeshes()
unavil_queue.swap(mUnavailableQ);
mLoadedMutex->unlock();
+ LL_PROFILE_ZONE_NAMED("notify unavail meshes");
+
update_metrics = true;
// Process the elements free of the lock
@@ -3380,6 +3420,7 @@ void LLMeshRepoThread::notifyLoadedMeshes()
{
if (mLoadedMutex->trylock())
{
+ LL_PROFILE_ZONE_NAMED("notify misc meshes");
std::deque<LLPointer<LLMeshSkinInfo>> skin_info_q;
std::deque<UUIDBasedRequest> skin_info_unavail_q;
std::list<LLModel::Decomposition*> decomp_q;
@@ -4271,20 +4312,63 @@ S32 LLMeshRepository::update()
return static_cast<S32>(size);
}
-void LLMeshRepository::unregisterMesh(LLVOVolume* vobj)
+void LLMeshRepository::unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail)
{
- for (auto& lod : mLoadingMeshes)
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
+ llassert((mesh_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH);
+ llassert(mesh_params.getSculptID().notNull());
+ auto& lod = mLoadingMeshes[detail];
+ auto param_iter = lod.find(mesh_params.getSculptID());
+ if (param_iter != lod.end())
{
- for (auto& param : lod)
+ param_iter->second.mVolumes.erase(vobj);
+ llassert(!param_iter->second.mVolumes.contains(vobj));
+ if (param_iter->second.mVolumes.empty())
{
- vector_replace_with_last(param.second.mVolumes, vobj);
+ lod.erase(param_iter);
}
}
+}
- for (auto& skin_pair : mLoadingSkins)
+void LLMeshRepository::unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
+ llassert(mesh_id.notNull());
+ auto skin_pair_iter = mLoadingSkins.find(mesh_id);
+ if (skin_pair_iter != mLoadingSkins.end())
+ {
+ skin_pair_iter->second.mVolumes.erase(vobj);
+ llassert(!skin_pair_iter->second.mVolumes.contains(vobj));
+ if (skin_pair_iter->second.mVolumes.empty())
+ {
+ mLoadingSkins.erase(skin_pair_iter);
+ }
+ }
+}
+
+// Lots of dead objects make expensive calls to
+// LLMeshRepository::unregisterMesh which may delay shutdown. Avoid this by
+// preemptively unregistering all meshes.
+// We can also do this safely if all objects are confirmed dead for some other
+// reason.
+void LLMeshRepository::unregisterAllMeshes()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
+ // The size of mLoadingMeshes and mLoadingSkins may be large and thus
+ // expensive to iterate over in LLVOVolume::~LLVOVolume.
+ // This is unnecessary during shutdown, so we ignore the referenced objects in the
+ // least expensive way which is still safe: by clearing these containers.
+ // Clear now and not in LLMeshRepository::shutdown because
+ // LLMeshRepository::notifyLoadedMeshes could (depending on invocation
+ // order) reference a pointer to an object after it has been deleted.
+ for (auto& lod : mLoadingMeshes)
{
- vector_replace_with_last(skin_pair.second.mVolumes, vobj);
+ lod.clear();
}
+ mLoadingSkins.clear();
}
S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 new_lod, S32 last_lod)
@@ -4306,7 +4390,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
mesh_load_map::iterator iter = mLoadingMeshes[new_lod].find(mesh_id);
if (iter != mLoadingMeshes[new_lod].end())
{ //request pending for this mesh, append volume id to list
- auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), vobj);
+ auto it = iter->second.mVolumes.find(vobj);
if (it == iter->second.mVolumes.end()) {
iter->second.addVolume(vobj);
}
@@ -4804,7 +4888,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV
skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
if (iter != mLoadingSkins.end())
{ //request pending for this mesh, append volume id to list
- auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), requesting_obj);
+ auto it = iter->second.mVolumes.find(requesting_obj);
if (it == iter->second.mVolumes.end()) {
iter->second.addVolume(requesting_obj);
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 01b51e753e..061b4b5428 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -290,7 +290,7 @@ private:
class MeshLoadData
{
public:
- MeshLoadData() {}
+ MeshLoadData() = default;
~MeshLoadData()
{
if (std::shared_ptr<PendingRequestBase> request = mRequest.lock())
@@ -300,19 +300,19 @@ public:
}
void initData(LLVOVolume* vol, std::shared_ptr<PendingRequestBase>& request)
{
- mVolumes.push_back(vol);
+ mVolumes.insert(vol);
request->trackData(this);
mRequest = request;
}
void addVolume(LLVOVolume* vol)
{
- mVolumes.push_back(vol);
+ mVolumes.insert(vol);
if (std::shared_ptr<PendingRequestBase> request = mRequest.lock())
{
request->setScoreDirty();
}
}
- std::vector<LLVOVolume*> mVolumes;
+ std::unordered_set<LLVOVolume*> mVolumes;
private:
std::weak_ptr<PendingRequestBase> mRequest;
};
@@ -442,7 +442,7 @@ public:
LLCondition* mSignal;
//map of known mesh headers
- typedef boost::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data
+ typedef std::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
class HeaderRequest : public RequestStats
@@ -862,10 +862,12 @@ public:
LLMeshRepository();
void init();
+ void unregisterAllMeshes();
void shutdown();
S32 update();
- void unregisterMesh(LLVOVolume* volume);
+ void unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail);
+ void unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj);
//mesh management functions
S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 new_lod = 0, S32 last_lod = -1);
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 6a7c25ec0f..d3f28b3c18 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -3461,7 +3461,7 @@ bool LLModelPreview::render()
LLViewerCamera::getInstance()->setAspect(aspect);
- LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
+ LLViewerCamera::getInstance()->setViewNoBroadcast(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
LLVector3 offset = mCameraOffset;
LLVector3 target_pos = mPreviewTarget + offset;
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index f47a8cd241..b72301c566 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -92,7 +92,17 @@ public:
const LLUUID& invoice,
const sparam_t& strings)
{
- LLMuteList::getInstance()->setLoaded();
+ // We've gotten a message from the server that indicates our mute list is empty there.
+
+ // First we want to make sure that if we had a cached mute list, we clear it assuming it is outdated.
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ if(mute_list->mLoadSource == LLMuteList::MLS_FALLBACK_CACHE && !mute_list->getMutes().empty())
+ {
+ LL_WARNS() << "Our current mute list is not empty, but the server says that it should be. Is our cache outdated, or did our mutes get lost?" << LL_ENDL;
+ mute_list->clearCachedMutes();
+ }
+ // Lastly we set the load state to loaded with the source of server empty. We are now in a clean and ready state.
+ mute_list->setLoaded(LLMuteList::MLS_SERVER_EMPTY);
return true;
}
};
@@ -155,7 +165,9 @@ std::string LLMute::getDisplayType() const
//-----------------------------------------------------------------------------
LLMuteList::LLMuteList() :
mLoadState(ML_INITIAL),
- mRequestStartTime(0.f)
+ mLoadSource(MLS_NONE),
+ mRequestStartTime(0.f),
+ mTriedCacheFallback(false)
{
gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
@@ -178,6 +190,8 @@ LLMuteList::LLMuteList() :
// but this way is just more convinient
onAccountNameChanged(id, av_name.getUserName());
});
+ // Register our region change callback handler early, we'll clean it up if/when we don't need it anymore.
+ mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLMuteList::onRegionChanged, this));
}
//-----------------------------------------------------------------------------
@@ -191,6 +205,10 @@ LLMuteList::~LLMuteList()
void LLMuteList::cleanupSingleton()
{
LLAvatarNameCache::getInstance()->setAccountNameChangedCallback(nullptr);
+ if (mRegionChangedCallback.connected())
+ {
+ mRegionChangedCallback.disconnect();
+ }
}
bool LLMuteList::isLinden(const std::string& name)
@@ -210,9 +228,9 @@ bool LLMuteList::isLinden(const std::string& name)
return last_name == "linden";
}
-bool LLMuteList::getLoadFailed() const
+bool LLMuteList::updateLoadState()
{
- if (mLoadState == ML_FAILED)
+ if (isLoaded() || isFailed())
{
return true;
}
@@ -221,9 +239,83 @@ bool LLMuteList::getLoadFailed() const
constexpr F64 WAIT_SECONDS = 30;
if (mRequestStartTime + WAIT_SECONDS < LLTimer::getTotalSeconds())
{
- return true;
+ LL_WARNS() << "Mute list request timed out; trying cache fallback once" << LL_ENDL;
+ tryLoadCacheFallback(gAgent.getID(), "request timeout");
+ return isLoaded() || isFailed();
+ }
+ }
+ return false;
+}
+
+void LLMuteList::clearCachedMutes()
+{
+ mMutes.clear();
+ mLegacyMutes.clear();
+ LL_WARNS() << "Cached mutes cleared" << LL_ENDL;
+}
+
+const char* LLMuteList::sourceToString(EMuteListSource source)
+{
+ switch (source)
+ {
+ case MLS_NONE:
+ return "none";
+ case MLS_SERVER:
+ return "server";
+ case MLS_SERVER_EMPTY:
+ return "server-empty";
+ case MLS_SERVER_CACHE:
+ return "server-cached";
+ case MLS_FALLBACK_CACHE:
+ return "fallback-cache";
+ default:
+ return "unknown";
+ }
+}
+
+std::string LLMuteList::getCacheFilename(const LLUUID& agent_id) const
+{
+ std::string agent_id_string;
+ agent_id.toString(agent_id_string);
+ return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".cached_mute";
+}
+
+void LLMuteList::setFailed(const std::string& reason)
+{
+ mLoadState = ML_FAILED;
+ if (mLoadSource == MLS_NONE)
+ {
+ LL_WARNS() << "Mute list unavailable: " << reason << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "Mute list unavailable: " << reason << " (last source=" << sourceToString(mLoadSource) << ")" << LL_ENDL;
+ }
+ notifyObservers();
+}
+
+bool LLMuteList::tryLoadCacheFallback(const LLUUID& agent_id, const std::string& reason)
+{
+ if (mTriedCacheFallback)
+ {
+ if (!isLoaded())
+ {
+ setFailed("cache fallback already attempted before " + reason);
}
+ return isLoaded();
}
+
+ mTriedCacheFallback = true;
+ const std::string filename = getCacheFilename(agent_id);
+ LL_INFOS() << "Trying mute list cache fallback due to " << reason << ": " << filename << LL_ENDL;
+
+ if (loadFromFile(filename, MLS_FALLBACK_CACHE))
+ {
+ LL_WARNS() << "Loaded mute list from cache fallback due to " << reason << LL_ENDL;
+ return true;
+ }
+
+ setFailed("cache fallback failed after " + reason);
return false;
}
@@ -580,12 +672,14 @@ std::vector<LLMute> LLMuteList::getMutes() const
//-----------------------------------------------------------------------------
// loadFromFile()
//-----------------------------------------------------------------------------
-bool LLMuteList::loadFromFile(const std::string& filename)
+bool LLMuteList::loadFromFile(const std::string& filename, EMuteListSource source)
{
+ LL_PROFILE_ZONE_SCOPED;
+
if(!filename.size())
{
LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL;
- mLoadState = ML_FAILED;
+ setFailed("empty filename");
return false;
}
@@ -593,10 +687,13 @@ bool LLMuteList::loadFromFile(const std::string& filename)
if (!fp)
{
LL_WARNS() << "Couldn't open mute list " << filename << LL_ENDL;
- mLoadState = ML_FAILED;
+ setFailed("cannot open " + filename);
return false;
}
+ // Replace previous server-backed state so fallback can be superseded by authoritative data.
+ clearCachedMutes();
+
// *NOTE: Changing the size of these buffers will require changes
// in the scanf below.
char id_buffer[MAX_STRING]; /*Flawfinder: ignore*/
@@ -625,7 +722,7 @@ bool LLMuteList::loadFromFile(const std::string& filename)
}
}
fclose(fp);
- setLoaded();
+ setLoaded(source);
// server does not maintain up-to date account names (not display names!)
// in this list, so it falls to viewer.
@@ -735,12 +832,16 @@ bool LLMuteList::isMuted(const std::string& username, U32 flags) const
//-----------------------------------------------------------------------------
void LLMuteList::requestFromServer(const LLUUID& agent_id)
{
- std::string agent_id_string;
- std::string filename;
- agent_id.toString(agent_id_string);
- filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
+ if(isLoadedFromServer())
+ {
+ LL_WARNS() << "Blocked attempt to request mute list from server when already loaded from server!" << LL_ENDL;
+ return;
+ }
+ const std::string filename = getCacheFilename(agent_id);
LLCRC crc;
crc.update(filename);
+ mTriedCacheFallback = false;
+ mLoadSource = MLS_NONE;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_MuteListRequest);
@@ -753,17 +854,19 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id)
if (gDisconnected)
{
LL_WARNS() << "Trying to request mute list when disconnected!" << LL_ENDL;
- mLoadState = ML_FAILED;
+ // Guard against potentially writing back to disk since we're not recovering our connection
+ mLoadState = ML_LOADED;
+ mLoadSource = MLS_FALLBACK_CACHE;
return;
}
if (!gAgent.getRegion())
{
LL_WARNS() << "No region for agent yet, skipping mute list request!" << LL_ENDL;
- mLoadState = ML_FAILED;
+ tryLoadCacheFallback(agent_id, "no region for request");
return;
}
mLoadState = ML_REQUESTED;
- mRequestStartTime = LLTimer::getElapsedSeconds();
+ mRequestStartTime = LLTimer::getTotalSeconds();
// Double amount of retries due to this request happening during busy stage
// Ideally this should be turned into a capability
gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
@@ -775,15 +878,16 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id)
void LLMuteList::cache(const LLUUID& agent_id)
{
- // Write to disk even if empty.
- if(isLoaded())
+ // Write to disk even if empty, but never from degraded fallback state.
+ if (isLoaded() && mLoadSource != MLS_FALLBACK_CACHE)
{
- std::string agent_id_string;
- std::string filename;
- agent_id.toString(agent_id_string);
- filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
+ const std::string filename = getCacheFilename(agent_id);
saveToFile(filename);
}
+ else if (isLoaded())
+ {
+ LL_WARNS() << "Skipping mute list cache write from fallback-only state" << LL_ENDL;
+ }
}
//-----------------------------------------------------------------------------
@@ -793,11 +897,16 @@ void LLMuteList::cache(const LLUUID& agent_id)
void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
{
LL_INFOS() << "LLMuteList::processMuteListUpdate()" << LL_ENDL;
+ LLMuteList* mute_list = getInstance();
+ if(mute_list->mTriedRegionChangeRetry)
+ {
+ LL_WARNS() << "Received mute list update after retrying region change; success!" << LL_ENDL;
+ }
LLUUID agent_id;
msg->getUUIDFast(_PREHASH_MuteData, _PREHASH_AgentID, agent_id);
if(agent_id != gAgent.getID())
{
- LL_WARNS() << "Got an mute list update for the wrong agent." << LL_ENDL;
+ LL_WARNS() << "Got a mute list update for the wrong agent." << LL_ENDL;
return;
}
std::string unclean_filename;
@@ -808,9 +917,8 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
LL_WARNS() << "Received empty mute list filename." << LL_ENDL;
}
- LLMuteList* mute_list = getInstance();
mute_list->mLoadState = ML_REQUESTED;
- mute_list->mRequestStartTime = LLTimer::getElapsedSeconds();
+ mute_list->mRequestStartTime = LLTimer::getTotalSeconds();
// Todo: Based of logs and testing, there is no callback
// from server if file doesn't exist server side.
@@ -829,12 +937,12 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**)
{
LL_INFOS() << "LLMuteList::processUseCachedMuteList()" << LL_ENDL;
-
- std::string agent_id_string;
- gAgent.getID().toString(agent_id_string);
- std::string filename;
- filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
- LLMuteList::getInstance()->loadFromFile(filename);
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ if(mute_list->mTriedRegionChangeRetry)
+ {
+ LL_WARNS() << "Received use cached mute list message after retrying region change; success!" << LL_ENDL;
+ }
+ mute_list->loadFromFile(mute_list->getCacheFilename(gAgent.getID()), MLS_SERVER_CACHE);
}
void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -843,13 +951,13 @@ void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_
if(local_filename_and_path && !local_filename_and_path->empty() && (error_code == 0))
{
LL_INFOS() << "Received mute list from server" << LL_ENDL;
- LLMuteList::getInstance()->loadFromFile(*local_filename_and_path);
+ LLMuteList::getInstance()->loadFromFile(*local_filename_and_path, MLS_SERVER);
LLFile::remove(*local_filename_and_path);
}
else
{
LL_INFOS() << "LLMuteList xfer failed with code " << error_code << LL_ENDL;
- LLMuteList::getInstance()->mLoadState = ML_FAILED;
+ LLMuteList::getInstance()->tryLoadCacheFallback(gAgent.getID(), "xfer failure");
}
delete local_filename_and_path;
}
@@ -906,10 +1014,21 @@ void LLMuteList::removeObserver(LLMuteListObserver* observer)
mObservers.erase(observer);
}
-void LLMuteList::setLoaded()
+void LLMuteList::setLoaded(EMuteListSource source)
{
+ if(isLoaded())
+ {
+ LL_WARNS() << "Mute list was already loaded from " << sourceToString(mLoadSource) << ", switching to " << sourceToString(source) << LL_ENDL;
+ }
mLoadState = ML_LOADED;
+ mLoadSource = source;
notifyObservers();
+ LL_INFOS() << "Mute list loaded from " << sourceToString(source) << LL_ENDL;
+ if(isLoadedFromServer() && mRegionChangedCallback.connected())
+ {
+ LL_INFOS() << "Mute list loaded from server, disconnecting region change callback" << LL_ENDL;
+ mRegionChangedCallback.disconnect();
+ }
}
void LLMuteList::notifyObservers()
@@ -938,6 +1057,23 @@ void LLMuteList::notifyObserversDetailed(const LLMute& mute)
}
}
+void LLMuteList::onRegionChanged()
+{
+ // If we are in a degraded state, either some protocol messages got lost between us and our login region, or our login region was having a bad day.
+ // Since the previous region might've been unable to provide our mute list, we can try to request it again from our new region.
+ // This is limited to one retry per session.
+ if(isLoadedDegraded() && !mTriedRegionChangeRetry)
+ {
+ if(mRegionChangedCallback.connected())
+ {
+ mRegionChangedCallback.disconnect();
+ }
+ LL_WARNS() << "Region changed while mute list is in degraded state, queueing a retry of the mute list request" << LL_ENDL;
+ mTriedRegionChangeRetry = true;
+ requestFromServer(gAgent.getID());
+ }
+}
+
LLRenderMuteList::LLRenderMuteList()
{}
@@ -966,6 +1102,8 @@ bool LLRenderMuteList::saveToFile()
bool LLRenderMuteList::loadFromFile()
{
+ LL_PROFILE_ZONE_SCOPED;
+
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt");
LLFILE* fp = LLFile::fopen(filename, "rb");
if (!fp)
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index b65fd61fcc..2781e9b177 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -31,6 +31,8 @@
#include "lluuid.h"
#include "llextendedstatus.h"
+#include <boost/signals2/connection.hpp>
+
class LLViewerObject;
class LLMessageSystem;
class LLMuteListObserver;
@@ -82,6 +84,15 @@ class LLMuteList : public LLSingleton<LLMuteList>
ML_LOADED,
ML_FAILED,
};
+
+ enum EMuteListSource
+ {
+ MLS_NONE,
+ MLS_SERVER,
+ MLS_SERVER_EMPTY,
+ MLS_SERVER_CACHE,
+ MLS_FALLBACK_CACHE,
+ };
public:
// reasons for auto-unmuting a resident
enum EAutoReason
@@ -115,8 +126,17 @@ public:
static bool isLinden(const std::string& name);
- bool isLoaded() const { return mLoadState == ML_LOADED; }
- bool getLoadFailed() const;
+ // Load state accessors.
+ bool isLoaded() const { return mLoadState == ML_LOADED; } // Loaded, but not necessarily from server.
+ bool isFailed() const { return mLoadState == ML_FAILED; } // Unable to load any mute list. Server did not reply.
+ // Loaded from server, which is the only source we consider authoritative.
+ bool isLoadedFromServer() const { return isLoaded() && (mLoadSource == MLS_SERVER || mLoadSource == MLS_SERVER_EMPTY); }
+ // Loaded, but from cache. Would be nice to upgrade to a server load from here if possible.
+ bool isLoadedDegraded() const { return isLoaded() && !isLoadedFromServer(); }
+
+ // Advance the load state machine, trying cache fallback if necessary.
+ // Return value indicates mute list consumption readiness.
+ bool updateLoadState();
std::vector<LLMute> getMutes() const;
@@ -126,11 +146,19 @@ public:
// call this method on logout to save everything.
void cache(const LLUUID& agent_id);
+ // Handler for region change event, used for server request retries if isLoadedDegraded() is true
+ void onRegionChanged();
+
private:
- bool loadFromFile(const std::string& filename);
+ void clearCachedMutes();
+ bool loadFromFile(const std::string& filename, EMuteListSource source);
bool saveToFile(const std::string& filename);
+ bool tryLoadCacheFallback(const LLUUID& agent_id, const std::string& reason);
+ void setFailed(const std::string& reason);
+ static const char* sourceToString(EMuteListSource source);
+ std::string getCacheFilename(const LLUUID& agent_id) const;
- void setLoaded();
+ void setLoaded(EMuteListSource source);
void notifyObservers();
void notifyObserversDetailed(const LLMute &mute);
@@ -177,7 +205,11 @@ private:
observer_set_t mObservers;
EMuteListState mLoadState;
+ EMuteListSource mLoadSource;
F64 mRequestStartTime;
+ bool mTriedCacheFallback;
+ bool mTriedRegionChangeRetry;
+ boost::signals2::connection mRegionChangedCallback;
friend class LLDispatchEmptyMuteList;
};
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index dfead5ee8a..9a0612e9f9 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -712,7 +712,14 @@ void LLNavigationBar::resizeLayoutPanel()
}
void LLNavigationBar::invokeSearch(std::string search_text)
{
- LLFloaterReg::showInstance("search", LLSD().with("category", "standard").with("query", LLSD(search_text)));
+ LLSD key;
+ key["category"] = "standard";
+ key["query"] = search_text;
+ LLSD collections = LLSD::emptyArray();
+ collections.append("destinations");
+ collections.append("places");
+ key["collections"] = collections;
+ LLFloaterReg::showInstance("search", key);
}
void LLNavigationBar::clearHistoryCache()
diff --git a/indra/newview/llnearbyvoicemoderation.cpp b/indra/newview/llnearbyvoicemoderation.cpp
new file mode 100644
index 0000000000..a5ee0e9423
--- /dev/null
+++ b/indra/newview/llnearbyvoicemoderation.cpp
@@ -0,0 +1,220 @@
+/**
+ * @file llnearbyvoicemoderation.cpp
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llnotificationsutil.h"
+#include "llviewerregion.h"
+#include "llvoavatar.h"
+#include "llvoicechannel.h"
+#include "llvoiceclient.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "roles_constants.h"
+
+#include "llnearbyvoicemoderation.h"
+
+LLNearbyVoiceModeration::LLNearbyVoiceModeration()
+{
+}
+
+LLNearbyVoiceModeration::~LLNearbyVoiceModeration()
+{
+}
+
+LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id)
+{
+ LLViewerObject *obj = gObjectList.findObject(agent_id);
+ while (obj && obj->isAttachment())
+ {
+ obj = (LLViewerObject*)obj->getParent();
+ }
+
+ if (obj && obj->isAvatar())
+ {
+ return (LLVOAvatar*)obj;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+const std::string LLNearbyVoiceModeration::getCapUrlFromRegion(LLViewerRegion* region)
+{
+ if (! region || ! region->capabilitiesReceived())
+ {
+ return std::string();
+ }
+
+ std::string url = region->getCapability("SpatialVoiceModerationRequest");
+ if (url.empty())
+ {
+ LL_INFOS() << "Capability URL for region " << region->getName() << " is empty" << LL_ENDL;
+ return std::string();
+ }
+ LL_INFOS() << "Capability URL for region " << region->getName() << " is " << url << LL_ENDL;
+
+ return url;
+}
+
+void LLNearbyVoiceModeration::requestMuteIndividual(const LLUUID& agent_id, bool mute)
+{
+ LLVOAvatar* avatar = getVOAvatarFromId(agent_id);
+ if (avatar)
+ {
+ const std::string cap_url = getCapUrlFromRegion(avatar->getRegion());
+ if (cap_url.length())
+ {
+ const std::string operand = mute ? "mute" : "unmute";
+
+ LLSD body;
+ body["operand"] = operand;
+ body["agent_id"] = agent_id;
+
+ const std::string agent_name = avatar->getFullname();
+ LL_INFOS() << "Resident " << agent_name
+ << " (" << agent_id << ")" << " applying " << operand << LL_ENDL;
+
+ std::string success_msg =
+ STRINGIZE("Resident " << agent_name
+ << " (" << agent_id << ")" << " nearby voice was set to " << operand);
+
+ std::string failure_msg =
+ STRINGIZE("Unable to change voice muting for resident "
+ << agent_name << " (" << agent_id << ")");
+
+ LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(
+ cap_url,
+ body,
+ success_msg,
+ failure_msg);
+ }
+ }
+}
+
+void LLNearbyVoiceModeration::requestMuteAll(bool mute)
+{
+ // Use our own avatar to get the region name
+ LLViewerRegion* region = gAgent.getRegion();
+
+ const std::string cap_url = getCapUrlFromRegion(region);
+ if (cap_url.length())
+ {
+ const std::string operand = mute ? "mute_all" : "unmute_all";
+
+ LLSD body;
+ body["operand"] = operand;
+
+ LL_INFOS() << "For all residents in this region, applying: " << operand << LL_ENDL;
+
+ std::string success_msg =
+ STRINGIZE("Nearby voice for all residents was set to: " << operand);
+
+ std::string failure_msg =
+ STRINGIZE("Unable to set nearby voice for all residents to: " << operand);
+
+ LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(
+ cap_url,
+ body,
+ success_msg,
+ failure_msg);
+ }
+}
+
+void LLNearbyVoiceModeration::setMutedInfo(const std::string& channelID, bool mute)
+{
+ auto it = mChannelMuteMap.find(channelID);
+ if (it == mChannelMuteMap.end())
+ {
+ if (mute)
+ {
+ // Channel is new and being muted
+ showMutedNotification(true);
+ }
+ mChannelMuteMap[channelID] = mute;
+ }
+ else
+ {
+ if (it->second != mute)
+ {
+ // Flag changed
+ showMutedNotification(mute);
+ it->second = mute;
+ }
+ }
+ if (mute && LLVoiceClient::getInstance()->getUserPTTState())
+ {
+ LLVoiceClient::getInstance()->setUserPTTState(false);
+ }
+}
+
+bool LLNearbyVoiceModeration::showNotificationIfNeeded()
+{
+ if (LLVoiceClient::getInstance()->inProximalChannel() &&
+ LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID))
+ {
+ return showMutedNotification(true);
+ }
+ return false;
+}
+
+bool LLNearbyVoiceModeration::showMutedNotification(bool is_muted)
+{
+ // Check if the current voice channel is nearby chat
+ if (LLVoiceClient::getInstance()->inProximalChannel())
+ {
+ LLNotificationsUtil::add(is_muted ? "NearbyVoiceMutedByModerator" : "NearbyVoiceUnmutedByModerator");
+ return true;
+ }
+ return false;
+}
+
+bool LLNearbyVoiceModeration::isNearbyChatModerator()
+{
+ // Region doesn't support WebRTC voice
+ if (!gAgent.getRegion() || !gAgent.getRegion()->isRegionWebRTCEnabled())
+ {
+ return false;
+ }
+
+ // Only show moderator options when connected to spatial voice chat
+ LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (!channel || channel->getSessionID().notNull() || !LLAgent::isActionAllowed("speak"))
+ {
+ return false;
+ }
+
+ if (LLViewerParcelMgr::getInstance()->isVoiceRestricted())
+ {
+ // Only the parcel owner should have access to moderate parcel voice space
+ return LLViewerParcelMgr::getInstance()->allowVoiceModeration();
+ }
+ else
+ {
+ return gAgent.canManageEstate();
+ }
+}
diff --git a/indra/newview/llnearbyvoicemoderation.h b/indra/newview/llnearbyvoicemoderation.h
new file mode 100644
index 0000000000..619f169883
--- /dev/null
+++ b/indra/newview/llnearbyvoicemoderation.h
@@ -0,0 +1,50 @@
+/**
+ * @file llnearbyvoicemoderation.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+class LLVOAvatar;
+
+class LLNearbyVoiceModeration : public LLSingleton <LLNearbyVoiceModeration> {
+ LLSINGLETON(LLNearbyVoiceModeration);
+ ~LLNearbyVoiceModeration();
+
+ public:
+ void requestMuteIndividual(const LLUUID& userID, bool mute);
+ void requestMuteAll(bool mute);
+
+ void setMutedInfo(const std::string& channelID, bool mute);
+ bool showMutedNotification(bool is_muted);
+ bool showNotificationIfNeeded();
+
+ bool isNearbyChatModerator();
+
+ private:
+ LLVOAvatar* getVOAvatarFromId(const LLUUID& id);
+ const std::string getCapUrlFromRegion(LLViewerRegion* region);
+
+ boost::signals2::connection mParcelCallbackConnection;
+ std::map<std::string, bool> mChannelMuteMap;
+};
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index af472c4259..a2a0731256 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -47,6 +47,9 @@
#include "llagent.h"
#include "llagentcamera.h"
#include "llappviewer.h" // for gDisconnected
+#include "llavataractions.h"
+#include "llgroupcolormap.h" // group-based dot tinting
+#include "llvoavatar.h" // group-based dot tinting
#include "llcallingcard.h" // LLAvatarTracker
#include "llfloaterland.h"
#include "llfloaterworldmap.h"
@@ -397,20 +400,59 @@ void LLNetMap::draw()
LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal());
- // Draw avatars
+ std::vector<std::pair<U32, bool>> indexed_avatars;
+ indexed_avatars.reserve(avatar_ids.size());
for (U32 i = 0; i < avatar_ids.size(); i++)
{
- LLUUID uuid = avatar_ids[i];
+ indexed_avatars.emplace_back(i, LLAvatarActions::isFriend(avatar_ids[i]));
+ }
+
+ // Sort avatars so non-friends are drawn first and friend dots will appear on top
+ std::sort(indexed_avatars.begin(), indexed_avatars.end(),
+ [](const auto& a, const auto& b) { return a.second < b.second; });
+
+ uuid_vec_t sorted_avatar_ids;
+ std::vector<LLVector3d> sorted_positions;
+ sorted_avatar_ids.reserve(avatar_ids.size());
+ sorted_positions.reserve(positions.size());
+
+ // Reorder avatar_ids and positions based on sorted indices
+ for (const auto& indexed_avatar : indexed_avatars)
+ {
+ sorted_avatar_ids.push_back(avatar_ids[indexed_avatar.first]);
+ sorted_positions.push_back(positions[indexed_avatar.first]);
+ }
+
+ // Draw avatars
+ for (U32 i = 0; i < sorted_avatar_ids.size(); i++)
+ {
+ LLUUID uuid = sorted_avatar_ids[i];
// Skip self, we'll draw it later
if (uuid == gAgent.getID()) continue;
- pos_map = globalPosToView(positions[i]);
+ pos_map = globalPosToView(sorted_positions[i]);
- bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL);
+ LLColor4 color = LLAvatarActions::isFriend(uuid) ? map_avatar_friend_color : map_avatar_color;
- LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color;
+ // Group-based dot tinting: override with group color if one is set.
+ // Look up the avatar's active group UUID from the LLVOAvatar object.
+ if (LLViewerObject* obj = gObjectList.findObject(uuid))
+ {
+ if (LLVOAvatar* av = dynamic_cast<LLVOAvatar*>(obj))
+ {
+ LLUUID active_group = av->getActiveGroupID();
+ if (active_group.notNull())
+ {
+ LLColor4 group_color = LLGroupColorMap::getInstance()->getGroupColor(active_group);
+ if (group_color.mV[VW] >= 0.01f)
+ {
+ color = group_color;
+ }
+ }
+ }
+ }
- unknown_relative_z = positions[i].mdV[VZ] >= COARSEUPDATE_MAX_Z &&
+ unknown_relative_z = sorted_positions[i].mdV[VZ] >= COARSEUPDATE_MAX_Z &&
camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z;
LLWorldMapView::drawAvatar(
@@ -483,10 +525,23 @@ void LLNetMap::draw()
LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
if (you)
{
+ // Group-based dot tinting for self: use gAgent.getGroupID() directly
+ LLColor4 self_color = UI_VERTEX_COLOR;
+ LLUUID self_group = gAgent.getGroupID();
+ if (self_group.notNull())
+ {
+ LLColor4 group_color = LLGroupColorMap::getInstance()->getGroupColor(self_group);
+ if (group_color.mV[VW] >= 0.01f)
+ {
+ self_color = group_color;
+ }
+ }
+
you->draw(ll_round(pos_map.mV[VX] - mDotRadius),
ll_round(pos_map.mV[VY] - mDotRadius),
dot_width,
- dot_width);
+ dot_width,
+ self_color);
F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]),
LLVector2((F32)local_mouse_x, (F32)local_mouse_y));
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index 9a33bcb1b9..4939cd5fbb 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -175,13 +175,15 @@ void LLNotificationListItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" ));
mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" ));
+ mNoticeTextExp->setBgReadOnlyColor(LLUIColorTable::instance().getColor("SelectedBgReadOnlyColor"));
}
void LLNotificationListItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
-}
+ mNoticeTextExp->setBgReadOnlyColor(LLUIColorTable::instance().getColor("TextBgReadOnlyColor"));
+ }
//static
LLNotificationListItem* LLNotificationListItem::create(const Params& p)
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index b65da28bda..27ef28f32a 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -36,6 +36,7 @@
#include "llscriptfloater.h"
#include "llimview.h"
#include "llnotificationsutil.h"
+#include "llchannelmanager.h"
#include <boost/regex.hpp>
@@ -135,7 +136,13 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification,
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
if(channel)
+ {
+ if (LLChannelManager::getInstance()->getStartUpToastInited() && notification->getOfferFromAgent())
+ {
+ LLChannelManager::getInstance()->onStartUpToastClose();
+ }
channel->addToast(p);
+ }
}
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 8589afae06..852f2dab21 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -850,7 +850,12 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
// Start observing changes in "My Outfits" category.
mCategoriesObserver->addCategory(cat_id,
- boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id), true);
+ [this, cat_id]()
+ {
+ mPendingOutfitRefreshes.insert(cat_id);
+ startIdleLoop(cat_id);
+ },
+ true);
outfit_category->fetch();
refreshOutfit(cat_id);
@@ -901,6 +906,18 @@ void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat,
}
}
+bool LLOutfitGallery::updateOneOutfit()
+{
+ if (mPendingOutfitRefreshes.empty())
+ return false;
+
+ auto it = mPendingOutfitRefreshes.begin();
+ LLUUID outfit_id = *it;
+ mPendingOutfitRefreshes.erase(it);
+ refreshOutfit(outfit_id);
+ return true;
+}
+
void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
{
if (mOutfitMenu && cat_id.notNull())
diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h
index 5801a32a39..183b6ea9d5 100644
--- a/indra/newview/lloutfitgallery.h
+++ b/indra/newview/lloutfitgallery.h
@@ -98,6 +98,7 @@ public:
/*virtual*/ void updateAddedCategory(LLUUID cat_id);
/*virtual*/ void updateRemovedCategory(LLUUID cat_id);
/*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name);
+ /*virtual*/ bool updateOneOutfit(); // bulk processing, scheduled by observer when updates are needed
/*virtual*/ bool hasItemSelected();
/*virtual*/ bool canWearSelected();
@@ -190,6 +191,7 @@ private:
typedef item_num_map_t::value_type item_numb_map_value_t;
item_num_map_t mItemIndexMap;
std::map<S32, LLOutfitGalleryItem*> mIndexToItemMap;
+ std::set<LLUUID> mPendingOutfitRefreshes;
LLInventoryCategoriesObserver* mOutfitsObserver;
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 32831fcd9b..7db79c7010 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -1055,6 +1055,15 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
}
}
+void LLOutfitListBase::startIdleLoop(const LLUUID cat_id)
+{
+ if (mRefreshListState.CategoryUUID.isNull())
+ {
+ mRefreshListState.CategoryUUID = cat_id;
+ gIdleCallbacks.addFunction(onIdle, this);
+ }
+}
+
// static
void LLOutfitListBase::onIdle(void* userdata)
{
@@ -1129,6 +1138,14 @@ void LLOutfitListBase::onIdleRefreshList()
return;
}
+ // Let derived classes process their own updates.
+ while (updateOneOutfit())
+ {
+ curent_time = LLTimer::getTotalSeconds();
+ if (curent_time >= end_time)
+ return;
+ }
+
sortOutfits();
highlightBaseOutfit();
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index bcf7e45696..408ff07116 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -95,6 +95,17 @@ public:
virtual void updateAddedCategory(LLUUID cat_id) = 0;
virtual void updateRemovedCategory(LLUUID cat_id) = 0;
virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0;
+
+ /*
+ * Optional hook for derived classes to perform additional processing.
+ * This is called by the outfit list update logic after the core
+ * bookkeeping for an outfit has been handled.
+ *
+ * @return true if update processing should continue,
+ * false if no additional work is required.
+ * The base implementation returns false.
+ */
+ virtual bool updateOneOutfit() { return false; };
virtual void sortOutfits();
void removeSelected();
@@ -138,6 +149,7 @@ protected:
bool isOutfitFolder(LLViewerInventoryCategory* cat) const;
+ void startIdleLoop(const LLUUID cat_id);
static void onIdle(void* userdata);
void onIdleRefreshList();
@@ -150,6 +162,7 @@ protected:
uuid_vec_t::const_iterator RemovedIterator;
} mRefreshListState;
std::set<LLUUID> mChangedItems;
+ std::set<LLUUID> mPendingOutfitRefreshes;
bool mIsInitialized;
LLInventoryCategoriesObserver* mCategoriesObserver;
diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp
index 69f51b03b6..178f994beb 100644
--- a/indra/newview/llpanelblockedlist.cpp
+++ b/indra/newview/llpanelblockedlist.cpp
@@ -78,6 +78,10 @@ bool LLPanelBlockedList::postBuild()
{
mBlockedList = getChild<LLBlockList>("blocked");
mBlockedList->setCommitOnSelectionChange(true);
+ mBlockedList->setNoItemsMsg(getString("no_blocked"));
+ mBlockedList->setNoFilteredItemsMsg(getString("no_filtered_blocked"));
+ mBlockedList->setLoadingItemsMsg(getString("loading_blocked"));
+ mBlockedList->setFailedItemsMsg(getString("failed_blocked"));
this->setVisibleCallback(boost::bind(&LLPanelBlockedList::removePicker, this));
switch (gSavedSettings.getU32("BlockPeopleSortOrder"))
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 6c0ff4a929..e8cb53d263 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -852,6 +852,27 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
}
+
+ // Also align GLTF material if any
+ S32 gltf_info_index = 0; // base texture
+ LLVector2 gltf_offset, gltf_scale;
+ F32 gltf_rot;
+ if (facep->calcAlignedPlanarGLTF(mCenterFace, &gltf_offset, &gltf_scale, &gltf_rot, gltf_info_index))
+ {
+ LLGLTFMaterial new_override;
+ const LLTextureEntry* tep = object->getTE(te);
+ if (tep && tep->getGLTFMaterialOverride())
+ {
+ new_override = *tep->getGLTFMaterialOverride();
+ }
+
+ LLGLTFMaterial::TextureTransform& transform = new_override.mTextureTransform[gltf_info_index];
+ transform.mOffset.set(gltf_offset.mV[0], gltf_offset.mV[1]);
+ transform.mScale.set(gltf_scale.mV[0], gltf_scale.mV[1]);
+ transform.mRotation = gltf_rot;
+
+ LLGLTFMaterialList::queueModify(object, te, &new_override);
+ }
}
if (!set_aligned)
{
@@ -1906,7 +1927,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
if (mColorSwatch)
{
mColorSwatch->setEnabled( false );
- mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") );
+ mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image") );
mColorSwatch->setValid(false);
}
diff --git a/indra/newview/llpanelgenerictip.cpp b/indra/newview/llpanelgenerictip.cpp
index bc2b28269f..1b5228713e 100644
--- a/indra/newview/llpanelgenerictip.cpp
+++ b/indra/newview/llpanelgenerictip.cpp
@@ -43,5 +43,13 @@ LLPanelGenericTip::LLPanelGenericTip(
S32 max_line_count = gSavedSettings.getS32("TipToastMessageLineCount");
snapToMessageHeight(getChild<LLTextBox> ("message"), max_line_count);
+
+ // Check if notification should respond to mouse clicks
+ if (notification->getPayload().has("respond_on_mousedown")
+ && notification->getPayload()["respond_on_mousedown"])
+ {
+ setMouseDownCallback(boost::bind(&LLNotification::respond,
+ notification, notification->getResponseTemplate()));
+ }
}
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index ecb66f9cea..ad65293b98 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -191,6 +191,13 @@ bool LLPanelGroup::postBuild()
mButtonJoin->setCommitCallback(boost::bind(&LLPanelGroup::onBtnJoin,this));
mJoinText = panel_general->getChild<LLUICtrl>("join_cost_text");
+
+ mButtonActivate = panel_general->getChild<LLButton>("btn_activate");
+ mButtonActivate->setVisible(false);
+ mButtonActivate->setEnabled(gAgent.getGroupID() != mID);
+ mButtonActivate->setCommitCallback(boost::bind(&LLPanelGroup::onBtnActivate, this));
+
+ gAgent.addListener(this, "new group");
}
LLVoiceClient::addObserver(this);
@@ -267,6 +274,7 @@ void LLPanelGroup::onBtnJoin()
if (LLGroupActions::isInGroup(mID))
{
LLGroupActions::leave(mID);
+ mButtonActivate->setVisible(false);
}
else
{
@@ -275,6 +283,12 @@ void LLPanelGroup::onBtnJoin()
}
}
+void LLPanelGroup::onBtnActivate()
+{
+ LLGroupActions::activate(mID);
+ mButtonActivate->setEnabled(false);
+}
+
void LLPanelGroup::changed(LLGroupChange gc)
{
for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
@@ -312,6 +326,8 @@ void LLPanelGroup::update(LLGroupChange gc)
bool join_btn_visible = is_member || gdatap->mOpenEnrollment;
mButtonJoin->setVisible(join_btn_visible);
+ mButtonActivate->setEnabled(gAgent.getGroupID() != mID);
+ mButtonActivate->setVisible(is_member);
mJoinText->setVisible(join_btn_visible);
if (is_member)
@@ -384,6 +400,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
if(mButtonJoin)
mButtonJoin->setVisible(false);
+ if (mButtonActivate)
+ mButtonActivate->setVisible(false);
if(is_null_group_id)//creating new group
@@ -598,4 +616,20 @@ void LLPanelGroup::showNotice(const std::string& subject,
}
+bool LLPanelGroup::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ if (event->desc() == "new group")
+ {
+ mButtonActivate->setEnabled(gAgent.getGroupID() != mID);
+ return true;
+ }
+
+ if (event->desc() == "value_changed")
+ {
+ mButtonActivate->setEnabled(gAgent.getGroupID() != mID);
+ return true;
+ }
+
+ return false;
+}
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index b43a93bc40..d3550264a0 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -26,6 +26,7 @@
#ifndef LL_LLPANELGROUP_H
#define LL_LLPANELGROUP_H
+#include "llevent.h"
#include "llgroupmgr.h"
#include "llpanel.h"
#include "lltimer.h"
@@ -44,7 +45,8 @@ class LLAgent;
class LLPanelGroup : public LLPanel,
public LLGroupMgrObserver,
- public LLVoiceClientStatusObserver
+ public LLVoiceClientStatusObserver,
+ public LLOldEvents::LLSimpleListener
{
public:
LLPanelGroup();
@@ -94,6 +96,7 @@ protected:
void onBackBtnClick();
void onBtnJoin();
+ void onBtnActivate();
static void onBtnApply(void*);
static void onBtnRefresh(void*);
@@ -120,11 +123,15 @@ protected:
LLUICtrl* mGroupNameCtrl = nullptr;
LLButton* mButtonJoin = nullptr;
+ LLButton* mButtonActivate = nullptr;
LLButton* mButtonApply = nullptr;
LLButton* mButtonCall = nullptr;
LLButton* mButtonChat = nullptr;
LLButton* mButtonRefresh = nullptr;
LLUICtrl* mJoinText;
+
+private:
+ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // for agent group list changes
};
class LLPanelGroupTab : public LLPanel
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 38ae818910..aaa5b2ce9c 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -28,6 +28,8 @@
#include "llpanelgroupgeneral.h"
+#include "llcolorswatch.h" // LLColorSwatchCtrl – group nameplate tinting
+#include "llgroupcolormap.h" // per-group nameplate tinting
#include "llavatarnamecache.h"
#include "llagent.h"
#include "llagentbenefits.h"
@@ -188,6 +190,22 @@ bool LLPanelGroupGeneral::postBuild()
mIncompleteMemberDataStr = getString("incomplete_member_data_str");
+ // Group nameplate tinting: wire up the color swatch
+ mGroupColorSwatch = getChild<LLColorSwatchCtrl>("group_nametag_color", recurse);
+ if (mGroupColorSwatch)
+ {
+ mGroupColorSwatch->setCanApplyImmediately(false);
+ mGroupColorSwatch->setCommitCallback([this](LLUICtrl*, const LLSD&) { onGroupColorChanged(); });
+ mGroupColorSwatch->setOnCancelCallback([this](LLUICtrl*, const LLSD&) { onGroupColorCancelled(); });
+ mGroupColorSwatch->setOnSelectCallback([this](LLUICtrl*, const LLSD&) { onGroupColorChanged(); });
+ refreshGroupColorSwatch();
+ }
+ LLButton* clear_color_btn = getChild<LLButton>("group_nametag_color_clear", recurse);
+ if (clear_color_btn)
+ {
+ clear_color_btn->setCommitCallback([this](LLUICtrl*, const LLSD&) { onGroupColorCleared(); });
+ }
+
// If the group_id is null, then we are creating a new group
if (mGroupID.isNull())
{
@@ -798,7 +816,65 @@ void LLPanelGroupGeneral::setGroupID(const LLUUID& id)
mInsignia->setImageAssetID(LLUUID::null);
+ // Refresh the nameplate color swatch to show the stored color for this group
+ refreshGroupColorSwatch();
+
resetDirty();
activate();
}
+
+// ---------------------------------------------------------------------------
+// Group nameplate tinting callbacks
+// ---------------------------------------------------------------------------
+
+void LLPanelGroupGeneral::onGroupColorChanged()
+{
+ if (!mGroupColorSwatch || mGroupID.isNull())
+ return;
+
+ LLColor4 color = mGroupColorSwatch->get();
+ LLGroupColorMap::getInstance()->setGroupColor(mGroupID, color);
+}
+
+void LLPanelGroupGeneral::onGroupColorCancelled()
+{
+ // Picker was cancelled — restore whatever is currently saved
+ refreshGroupColorSwatch();
+}
+
+void LLPanelGroupGeneral::onGroupColorCleared()
+{
+ if (mGroupID.isNull())
+ return;
+
+ LLGroupColorMap::getInstance()->clearGroupColor(mGroupID);
+ refreshGroupColorSwatch();
+}
+
+void LLPanelGroupGeneral::refreshGroupColorSwatch()
+{
+ if (!mGroupColorSwatch)
+ return;
+
+ if (mGroupID.isNull())
+ {
+ // No group selected — show a neutral white and disable
+ mGroupColorSwatch->set(LLColor4::white, false);
+ mGroupColorSwatch->setEnabled(false);
+ return;
+ }
+
+ mGroupColorSwatch->setEnabled(true);
+
+ LLColor4 stored = LLGroupColorMap::getInstance()->getGroupColor(mGroupID);
+ if (stored.mV[VW] >= 0.01f)
+ {
+ mGroupColorSwatch->set(stored, false);
+ }
+ else
+ {
+ // No color stored yet — show white as a neutral default
+ mGroupColorSwatch->set(LLColor4::white, false);
+ }
+}
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index 37db2e96a0..613cc7b3a6 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -39,6 +39,7 @@ class LLCheckBoxCtrl;
class LLComboBox;
class LLSpinCtrl;
class LLAvatarName;
+class LLColorSwatchCtrl; // group nameplate tinting
class LLPanelGroupGeneral : public LLPanelGroupTab
{
@@ -99,6 +100,13 @@ private:
LLComboBox *mComboActiveTitle;
LLComboBox *mComboMature;
LLCheckBoxCtrl *mCtrlReceiveGroupChat; // <exodus/>
+
+ // Group nameplate tinting (client-side, stored in LLGroupColorMap)
+ LLColorSwatchCtrl* mGroupColorSwatch { nullptr };
+ void onGroupColorChanged();
+ void onGroupColorCancelled();
+ void onGroupColorCleared();
+ void refreshGroupColorSwatch();
};
#endif
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 0a585722f2..15cc8b421c 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -51,6 +51,7 @@
#include "llstartup.h"
#include "lltextbox.h"
#include "llui.h"
+#include "llframetimer.h"
#include "lluiconstants.h"
#include "llslurl.h"
#include "llversioninfo.h"
@@ -177,6 +178,19 @@ public:
};
LLLoginLocationAutoHandler gLoginLocationAutoHandler;
+std::string getShortGridLabel(const std::string& slurl_grid)
+{
+ if (slurl_grid == MAINGRID)
+ {
+ return LLTrans::getString("AgniGridLabelShort");
+ }
+ if (slurl_grid == BETAGRID)
+ {
+ return LLTrans::getString("AditiGridLabelShort");
+ }
+ return LLGridManager::getInstance()->getGridLabel(slurl_grid);
+}
+
//---------------------------------------------------------------------------
// Public methods
//---------------------------------------------------------------------------
@@ -187,11 +201,11 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
mCallback(callback),
mCallbackData(cb_data),
mListener(std::make_unique<LLPanelLoginListener>(this)),
- mFirstLoginThisInstall(gSavedSettings.getBOOL("FirstLoginThisInstall")),
mUsernameLength(0),
mPasswordLength(0),
mLocationLength(0),
- mShowFavorites(false)
+ mShowFavorites(false),
+ mAlertNotif(false)
{
setBackgroundVisible(false);
setBackgroundOpaque(true);
@@ -206,15 +220,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
login_holder->addChild(this);
}
- if (mFirstLoginThisInstall)
- {
- buildFromFile( "panel_login_first.xml");
- }
- else
- {
- buildFromFile( "panel_login.xml");
- }
-
+ buildFromFile( "panel_login.xml");
reshape(rect.getWidth(), rect.getHeight());
LLLineEditor* password_edit(getChild<LLLineEditor>("password_edit"));
@@ -222,13 +228,20 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
// STEAM-14: When user presses Enter with this field in focus, initiate login
password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, false));
+ childSetAction("connect_btn", onClickConnect, this);
+ childSetAction("sign_btn", onClickSignUp, this);
+
+ mLoginBtn = getChild<LLButton>("connect_btn");
+ setDefaultBtn(mLoginBtn);
+
// change z sort of clickable text to be behind buttons
sendChildToBack(getChildView("forgot_password_text"));
- sendChildToBack(getChildView("sign_up_text"));
+
+ mLoginStack = getChild<LLLayoutStack>("login_stack");
+ mGridPanel = getChild<LLLayoutPanel>("grid_panel");
std::string current_grid = LLGridManager::getInstance()->getGrid();
- if (!mFirstLoginThisInstall)
- {
+
LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, false));
@@ -248,17 +261,16 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
if (!grid_choice->first.empty() && current_grid != grid_choice->first)
{
LL_DEBUGS("AppInit") << "adding " << grid_choice->first << LL_ENDL;
- server_choice_combo->add(grid_choice->second, grid_choice->first);
+ server_choice_combo->add(getShortGridLabel(grid_choice->first), grid_choice->first);
}
}
server_choice_combo->sortByName();
LL_DEBUGS("AppInit") << "adding current " << current_grid << LL_ENDL;
- server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
+ server_choice_combo->add(getShortGridLabel(current_grid),
current_grid,
ADD_TOP);
server_choice_combo->selectFirstItem();
- }
LLSLURL start_slurl(LLStartUp::getStartSLURL());
// The StartSLURL might have been set either by an explicit command-line
@@ -298,11 +310,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
onUpdateStartSLURL(start_slurl); // updates grid if needed
}
- childSetAction("connect_btn", onClickConnect, this);
-
- LLButton* def_btn = getChild<LLButton>("connect_btn");
- setDefaultBtn(def_btn);
-
std::string channel = LLVersionInfo::instance().getChannel();
std::string version = stringize(LLVersionInfo::instance().getShortVersion(), " (",
LLVersionInfo::instance().getBuild(), ')');
@@ -310,12 +317,9 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
forgot_password_text->setClickedCallback(onClickForgotPassword, NULL);
- LLTextBox* sign_up_text = getChild<LLTextBox>("sign_up_text");
- sign_up_text->setClickedCallback(onClickSignUp, NULL);
-
// get the web browser control
- LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
- web_browser->addObserver(this);
+ mWebBrowser = getChild<LLMediaCtrl>("login_html");
+ mWebBrowser->addObserver(this);
loadLoginPage();
@@ -330,19 +334,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this));
getChild<LLCheckBoxCtrl>("remember_password")->setCommitCallback(boost::bind(&LLPanelLogin::onRememberPasswordCheck, this));
+
+ mAlertListener = LLNotifications::instance().getChannel("Alerts")->connectChanged([this](const LLSD& notify){ return onUpdateNotification(notify); });
}
void LLPanelLogin::addFavoritesToStartLocation()
{
- if (mFirstLoginThisInstall)
- {
- // first login panel has no favorites, just update name length and buttons
- std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
- mUsernameLength = static_cast<unsigned int>(user_defined_name.length());
- updateLoginButtons();
- return;
- }
-
// Clear the combo.
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
if (!combo) return;
@@ -412,7 +409,7 @@ void LLPanelLogin::addFavoritesToStartLocation()
gSavedSettings.setBOOL("RememberPassword", save_password);
if (!save_password)
{
- getChild<LLButton>("connect_btn")->setEnabled(false);
+ mLoginBtn->setEnabled(false);
}
update_password_setting = false;
}
@@ -562,16 +559,8 @@ void LLPanelLogin::resetFields()
// function is used to reset list in case of changes by external sources
return;
}
- if (sInstance->mFirstLoginThisInstall)
- {
- // no list to populate
- LL_WARNS() << "Shouldn't happen, user should have no ability to modify list on first install" << LL_ENDL;
- }
- else
- {
- LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
- sInstance->populateUserList(cred);
- }
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ sInstance->populateUserList(cred);
}
// static
@@ -752,6 +741,11 @@ void LLPanelLogin::updateLocationSelectorsVisibility()
{
server_combo->setVisible(show_server);
}
+ if (LLTextBox* grid_txt = sInstance->getChild<LLTextBox>("grid_text"))
+ {
+ grid_txt->setVisible(show_server);
+ }
+ sInstance->collapseGridPanel(!show_server);
}
}
@@ -787,7 +781,7 @@ void LLPanelLogin::onUpdateStartSLURL(const LLSLURL& new_start_slurl)
// update the grid selector to match the slurl
LLComboBox* server_combo = sInstance->getChild<LLComboBox>("server_combo");
- std::string server_label(LLGridManager::getInstance()->getGridLabel(slurl_grid));
+ std::string server_label(getShortGridLabel(slurl_grid));
server_combo->setSimple(server_label);
updateServer(); // to change the links and splash screen
@@ -860,11 +854,9 @@ void LLPanelLogin::setAlwaysRefresh(bool refresh)
{
if (sInstance && LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
{
- LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
- if (web_browser)
+ if (sInstance->mWebBrowser)
{
- web_browser->setAlwaysRefresh(refresh);
+ sInstance->mWebBrowser->setAlwaysRefresh(refresh);
}
}
}
@@ -921,16 +913,35 @@ void LLPanelLogin::loadLoginPage()
gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
- LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
- if (web_browser->getCurrentNavUrl() != login_uri.asString())
+ if (sInstance->mWebBrowser)
{
- LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL;
- web_browser->navigateTo( login_uri.asString(), "text/html" );
+ if (sInstance->mWebBrowser->getCurrentNavUrl() != login_uri.asString())
+ {
+ LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL;
+ sInstance->mWebBrowser->navigateTo(login_uri.asString(), "text/html");
+ }
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "No web browser control for login panel" << LL_ENDL;
}
}
-void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
+void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
{
+ constexpr F32 REFRESH_DELAY = 2.f;
+ switch (event)
+ {
+ case MEDIA_EVENT_SIZE_CHANGED:
+ {
+ mForceRefreshTimer.reset();
+ mForceRefreshTimer.setTimerExpirySec(REFRESH_DELAY);
+ mForceRefresh = true;
+ break;
+ }
+ default:
+ break;
+ }
}
//---------------------------------------------------------------------------
@@ -952,7 +963,7 @@ void LLPanelLogin::onClickConnect(bool commit_fields)
}
#endif
- if (sInstance && sInstance->mCallback)
+ if (sInstance && sInstance->mCallback && !sInstance->mAlertNotif)
{
if (commit_fields)
{
@@ -1097,8 +1108,7 @@ void LLPanelLogin::onRememberUserCheck(void*)
LLComboBox* user_combo(sInstance->getChild<LLComboBox>("username_combo"));
bool remember = remember_name->getValue().asBoolean();
- if (!sInstance->mFirstLoginThisInstall
- && user_combo->getCurrentIndex() != -1
+ if (user_combo->getCurrentIndex() != -1
&& !remember)
{
remember = true;
@@ -1209,21 +1219,16 @@ void LLPanelLogin::updateServer()
void LLPanelLogin::updateLoginButtons()
{
- LLButton* login_btn = getChild<LLButton>("connect_btn");
+ mLoginBtn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0 && !mAlertNotif);
- login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0);
-
- if (!mFirstLoginThisInstall)
+ LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+ LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+ if (user_combo->getCurrentIndex() != -1)
{
- LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
- LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
- if (user_combo->getCurrentIndex() != -1)
- {
- remember_name->setValue(true);
- LLCheckBoxCtrl* remember_pass = getChild<LLCheckBoxCtrl>("remember_password");
- remember_pass->setEnabled(true);
- } // Note: might be good idea to do "else remember_name->setValue(mRememberedState)" but it might behave 'weird' to user
- }
+ remember_name->setValue(true);
+ LLCheckBoxCtrl* remember_pass = getChild<LLCheckBoxCtrl>("remember_password");
+ remember_pass->setEnabled(true);
+ } // Note: might be good idea to do "else remember_name->setValue(mRememberedState)" but it might behave 'weird' to user
}
void LLPanelLogin::populateUserList(LLPointer<LLCredential> credential)
@@ -1383,3 +1388,48 @@ std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred)
return "unknown";
}
+bool LLPanelLogin::onUpdateNotification(const LLSD& notify)
+{
+ // disable Login button while alert notification is displayed
+ LLNotificationPtr notifyp = LLNotifications::instance().find(notify["id"].asUUID());
+ if (notifyp && notifyp->getName() == "PromptOptionalUpdate")
+ {
+ std::string sigtype = notify["sigtype"].asString();
+ if (sigtype == "add")
+ {
+ mAlertNotif = true;
+ }
+ else if (sigtype == "delete")
+ {
+ mAlertNotif = false;
+ }
+ updateLoginButtons();
+ }
+ return false;
+}
+
+void LLPanelLogin::collapseGridPanel(bool collapse)
+{
+ if (mGridPanel->isCollapsed() == collapse)
+ {
+ return;
+ }
+ mLoginStack->collapsePanel(mGridPanel, collapse);
+ mLoginStack->updateLayout();
+}
+
+void LLPanelLogin::draw()
+{
+ LLPanel::draw();
+
+ // Workaround for the black screen issue (see #5607)
+ // Should be removed after the proper fix for resizing is implemented
+ if (mForceRefresh && mForceRefreshTimer.hasExpired())
+ {
+ if (mWebBrowser->getMediaPlugin())
+ {
+ mWebBrowser->getMediaPlugin()->forceRenderRefresh();
+ }
+ mForceRefresh = false;
+ }
+}
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index a1bf25fb05..a00081795e 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -48,6 +48,8 @@ public:
void *callback_data);
~LLPanelLogin();
+ void draw();
+
virtual void setFocus( bool b );
static void show(const LLRect &rect,
@@ -87,6 +89,8 @@ public:
// extract name from cred in a format apropriate for username field
static std::string getUserName(LLPointer<LLCredential> &cred);
+ void collapseGridPanel(bool collapse);
+
private:
friend class LLPanelLoginListener;
void addFavoritesToStartLocation();
@@ -105,8 +109,11 @@ private:
static void onRememberPasswordCheck(void*);
static void onPassKey(LLLineEditor* caller, void* user_data);
+ bool onUpdateNotification(const LLSD& notify);
+
private:
std::unique_ptr<LLPanelLoginListener> mListener;
+ LLTempBoundListener mAlertListener;
void updateLoginButtons();
void populateUserList(LLPointer<LLCredential> credential);
@@ -119,13 +126,22 @@ private:
static LLPanelLogin* sInstance;
static bool sCapslockDidNotification;
- bool mFirstLoginThisInstall;
static bool sCredentialSet;
unsigned int mUsernameLength;
unsigned int mPasswordLength;
unsigned int mLocationLength;
+
+ LLTimer mForceRefreshTimer;
+ bool mForceRefresh {false};
+
+ bool mAlertNotif;
+ LLButton* mLoginBtn;
+ LLLayoutPanel* mGridPanel;
+ LLLayoutStack* mLoginStack;
+
+ LLMediaCtrl* mWebBrowser;
};
#endif
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index ad7aa57842..04eebcefc1 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -216,14 +216,14 @@ bool LLPanelMainInventory::postBuild()
mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2));
}
- LLInventoryPanel* favorites_panel = getChild<LLInventoryPanel>(FAVORITES);
- if (favorites_panel)
+ mFavoritesPanel = getChild<LLInventoryPanel>(FAVORITES);
+ if (mFavoritesPanel)
{
- favorites_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER));
- LLInventoryFilter& favorites_filter = favorites_panel->getFilter();
+ mFavoritesPanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER));
+ LLInventoryFilter& favorites_filter = mFavoritesPanel->getFilter();
favorites_filter.setEmptyLookupMessage("InventoryNoMatchingFavorites");
favorites_filter.markDefault();
- favorites_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, favorites_panel, _1, _2));
+ mFavoritesPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mFavoritesPanel, _1, _2));
}
mSearchTypeCombo = getChild<LLComboBox>("search_type");
@@ -319,6 +319,10 @@ bool LLPanelMainInventory::postBuild()
menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str);
}
+ mFilterTabs->setTabVisibility(mRecentPanel, gSavedSettings.getBOOL("InventoryShowRecentTab"));
+ mFilterTabs->setTabVisibility(mWornItemsPanel, gSavedSettings.getBOOL("InventoryShowWornTab"));
+ mFilterTabs->setTabVisibility(mFavoritesPanel, gSavedSettings.getBOOL("InventoryShowFavoritesTab"));
+
// Trigger callback for focus received so we can deselect items in inbox/outbox
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
@@ -1613,8 +1617,10 @@ void LLPanelMainInventory::initSingleFolderRoot(const LLUUID& start_folder_id)
void LLPanelMainInventory::initInventoryViews()
{
mAllItemsPanel->initializeViewBuilding();
- mRecentPanel->initializeViewBuilding();
- mWornItemsPanel->initializeViewBuilding();
+ if (gSavedSettings.getBOOL("InventoryShowRecentTab"))
+ mRecentPanel->initializeViewBuilding();
+ if (gSavedSettings.getBOOL("InventoryShowWornTab"))
+ mWornItemsPanel->initializeViewBuilding();
}
void LLPanelMainInventory::toggleViewMode()
@@ -2056,6 +2062,27 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
{
setViewMode(MODE_COMBINATION);
}
+
+ if (command_name == "toggle_recent_tab")
+ {
+ bool visibility = !gSavedSettings.getBOOL("InventoryShowRecentTab");
+ gSavedSettings.setBOOL("InventoryShowRecentTab", visibility);
+ mFilterTabs->setTabVisibility(mRecentPanel, visibility);
+ mRecentPanel->initializeViewBuilding();
+ }
+ if (command_name == "toggle_worn_tab")
+ {
+ bool visibility = !gSavedSettings.getBOOL("InventoryShowWornTab");
+ gSavedSettings.setBOOL("InventoryShowWornTab", visibility);
+ mFilterTabs->setTabVisibility(mWornItemsPanel, visibility);
+ mWornItemsPanel->initializeViewBuilding();
+ }
+ if (command_name == "toggle_favorites_tab")
+ {
+ bool visibility = !gSavedSettings.getBOOL("InventoryShowFavoritesTab");
+ gSavedSettings.setBOOL("InventoryShowFavoritesTab", visibility);
+ mFilterTabs->setTabVisibility(mFavoritesPanel, visibility);
+ }
}
void LLPanelMainInventory::onVisibilityChange( bool new_visibility )
@@ -2283,6 +2310,19 @@ bool LLPanelMainInventory::isActionChecked(const LLSD& userdata)
return isCombinationViewMode();
}
+ if (command_name == "recent_tab")
+ {
+ return mFilterTabs->getTabVisibility(mRecentPanel);
+ }
+ if (command_name == "worn_tab")
+ {
+ return mFilterTabs->getTabVisibility(mWornItemsPanel);
+ }
+ if (command_name == "favorites_tab")
+ {
+ return mFilterTabs->getTabVisibility(mFavoritesPanel);
+ }
+
return false;
}
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index a78c0c0fad..03650e7fc1 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -199,6 +199,7 @@ private:
LLInventoryPanel* mAllItemsPanel = nullptr;
LLInventoryPanel* mRecentPanel = nullptr;
LLInventoryPanel* mWornItemsPanel = nullptr;
+ LLInventoryPanel* mFavoritesPanel = nullptr;
bool mResortActivePanel;
LLSaveFolderState* mSavedFolderState;
std::string mFilterText;
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 23e6a9fbcf..69be65d9c9 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -625,7 +625,7 @@ void LLPanelObject::getState( )
}
- if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
+ if (objectp->getSculptParams())
{
selected_item = MI_SCULPT;
//LLFirstUse::useSculptedPrim();
@@ -1078,7 +1078,7 @@ void LLPanelObject::getState( )
LLUUID id;
- LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = objectp->getSculptParams();
if (sculpt_params) // if we have a legal sculpt param block for this object:
@@ -1246,13 +1246,13 @@ void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata )
if (selected_type == MI_SCULPT)
{
self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, true, true);
- LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = self->mObject->getSculptParams();
if (sculpt_params)
volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType());
}
else
{
- LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = self->mObject->getSculptParams();
if (sculpt_params)
self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true);
}
@@ -2264,24 +2264,21 @@ void LLPanelObject::onCopyParams()
mClipboardParams["volume_params"] = params.asLLSD();
// Sculpted Prim
- if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
+ LLSculptParams *sculpt_params = objectp->getSculptParams();
+ if (sculpt_params)
{
- LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- if (sculpt_params)
+ LLUUID texture_id = sculpt_params->getSculptTexture();
+ if (get_can_copy_texture(texture_id))
{
- LLUUID texture_id = sculpt_params->getSculptTexture();
- if (get_can_copy_texture(texture_id))
- {
- LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL;
- mClipboardParams["sculpt"]["id"] = texture_id;
- }
- else
- {
- mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE;
- }
-
- mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType();
+ LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL;
+ mClipboardParams["sculpt"]["id"] = texture_id;
}
+ else
+ {
+ mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE;
+ }
+
+ mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType();
}
}
@@ -2304,7 +2301,7 @@ void LLPanelObject::onPasteParams()
}
else
{
- LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = objectp->getSculptParams();
if (sculpt_params)
{
objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true);
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index a31a54bb67..d27ce81e4f 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -1830,7 +1830,7 @@ void LLPanelObjectInventory::onFocusReceived()
LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id )
{
- std::map<LLUUID, LLFolderViewItem*>::iterator map_it = mItemMap.find(id);
+ auto map_it = mItemMap.find(id);
if (map_it != mItemMap.end())
{
return map_it->second;
diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h
index 154639e4bb..13e27b489c 100644
--- a/indra/newview/llpanelobjectinventory.h
+++ b/indra/newview/llpanelobjectinventory.h
@@ -109,7 +109,7 @@ protected:
bool isSelectionRemovable();
private:
- std::map<LLUUID, LLFolderViewItem*> mItemMap;
+ std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap;
LLScrollContainer* mScroller;
LLFolderView* mFolders;
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 794ae4ad44..537ea28a4d 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -84,11 +84,14 @@ LLContextMenu* PeopleContextMenu::createMenu()
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
registrar.add("Avatar.Freeze", boost::bind(&LLAvatarActions::freezeAvatar, id));
registrar.add("Avatar.Eject", boost::bind(&PeopleContextMenu::eject, this));
+ registrar.add("Avatar.EstateKick", boost::bind(&LLAvatarActions::estateKickAvatar, id));
+ registrar.add("Avatar.EstateBan", boost::bind(&LLAvatarActions::estateBanAvatar, id));
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));
enable_registrar.add("Avatar.EnableFreezeEject", boost::bind(&PeopleContextMenu::enableFreezeEject, this, _2));
+ enable_registrar.add("Avatar.EnableEstateEjectBan", boost::bind(&PeopleContextMenu::enableEstateEjectBan, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby.xml");
@@ -318,6 +321,17 @@ bool PeopleContextMenu::enableFreezeEject(const LLSD& userdata)
return new_value;
}
+bool PeopleContextMenu::enableEstateEjectBan(const LLSD& userdata)
+{
+ if (gAgent.getID() == mUUIDs.front() || mUUIDs.size() != 1)
+ return false;
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return false;
+ if (gAgent.isGodlike()) return true;
+ return region->getOwner() == gAgent.getID() || region->isEstateManager();
+}
+
void PeopleContextMenu::requestTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(),
@@ -419,6 +433,8 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
items.push_back(std::string("block_unblock"));
items.push_back(std::string("freeze"));
items.push_back(std::string("eject"));
+ items.push_back(std::string("estate_eject"));
+ items.push_back(std::string("estate_ban"));
}
hide_context_entries(menu, items, disabled_items);
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
index ad38cebc31..ad6a26c645 100644
--- a/indra/newview/llpanelpeoplemenus.h
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -47,6 +47,7 @@ private:
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
bool enableFreezeEject(const LLSD& userdata);
+ bool enableEstateEjectBan(const LLSD& userdata);
void offerTeleport();
void eject();
void startConference();
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index cbf5819fda..cff09b0778 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -786,7 +786,9 @@ void LLPanelPermissions::refresh()
getChildView("Edit Cost")->setEnabled(change_sale_allowed && !is_for_sale_mixed);
// Set the checkbox to tentative if the prices of each object selected
// are not the same.
- getChild<LLUICtrl>("checkbox for sale")->setTentative( is_for_sale_mixed);
+ // If object is marked for sale yet is not transferable, mark as tentative,
+ // as it is in a state where it can't be sold
+ getChild<LLUICtrl>("checkbox for sale")->setTentative((!can_transfer && num_for_sale) || is_for_sale_mixed);
getChildView("sale type")->setEnabled(num_for_sale && can_transfer && !is_sale_price_mixed);
getChildView("Next owner can:")->setEnabled(true);
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 5435a79e16..5c866905d6 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -1356,6 +1356,12 @@ static bool is_agent_in_selected_parcel(LLParcel* parcel)
static void onSLURLBuilt(std::string& slurl)
{
+ if (slurl.empty())
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ return;
+ }
+
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
LLSD args;
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
index 3916e34e31..e870ab7a2c 100644
--- a/indra/newview/llpanelplacestab.cpp
+++ b/indra/newview/llpanelplacestab.cpp
@@ -67,6 +67,12 @@ void LLPanelPlacesTab::onRegionResponse(const LLVector3d& landmark_global_pos,
sl_url = "";
}
+ if (sl_url.empty())
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ return;
+ }
+
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(sl_url));
LLSD args;
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 758ca0b0fa..3d8e5575ae 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -113,77 +113,131 @@ LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::stri
LLCore::HttpOptions::ptr_t httpOpts = std::make_shared<LLCore::HttpOptions>();
httpOpts->setFollowRedirects(true);
- LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
+ // Retry stage-2 upload by re-requesting a fresh one-time uploader capability (up to 3 attempts total)
+ const S32 MAX_UPLOAD_RETRIES = 2;
+ S32 upload_retry_count = 0;
+ LLUUID result_uuid;
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status)
- {
- // todo: notification?
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
- return LLUUID::null;
- }
- if (!result.has("uploader"))
+ while (upload_retry_count <= MAX_UPLOAD_RETRIES)
{
- // todo: notification?
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
- return LLUUID::null;
- }
- std::string uploader_cap = result["uploader"].asString();
- if (uploader_cap.empty())
- {
- LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
- return LLUUID::null;
- }
+ // Stage 1: Request uploader URL
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
- // Upload the image
- LLCore::HttpRequest::ptr_t uploaderhttpRequest = std::make_shared<LLCore::HttpRequest>();
- LLCore::HttpHeaders::ptr_t uploaderhttpHeaders = std::make_shared<LLCore::HttpHeaders>();
- LLCore::HttpOptions::ptr_t uploaderhttpOpts = std::make_shared<LLCore::HttpOptions>();
- S64 length;
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- {
- llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate);
- if (!instream.is_open())
+ if (!status)
{
- LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL;
+ // todo: notification?
+ LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
+ return LLUUID::null;
+ }
+
+ if (!result.has("uploader"))
+ {
+ // todo: notification?
+ LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
return LLUUID::null;
}
- length = instream.tellg();
- }
- uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional
- uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required!
- uploaderhttpOpts->setFollowRedirects(true);
+ std::string uploader_cap = result["uploader"].asString();
+ if (uploader_cap.empty())
+ {
+ LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
+ return LLUUID::null;
+ }
+
+ // Stage 2: Upload the image
+ LLCore::HttpRequest::ptr_t uploaderhttpRequest = std::make_shared<LLCore::HttpRequest>();
+ LLCore::HttpHeaders::ptr_t uploaderhttpHeaders = std::make_shared<LLCore::HttpHeaders>();
+ LLCore::HttpOptions::ptr_t uploaderhttpOpts = std::make_shared<LLCore::HttpOptions>();
+ S64 length;
+
+ {
+ llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate);
+ if (!instream.is_open())
+ {
+ LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL;
+ return LLUUID::null;
+ }
+ length = instream.tellg();
+ }
- result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders);
+ uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2");
+ uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, std::to_string(length));
+ uploaderhttpOpts->setFollowRedirects(true);
- httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders);
- LL_DEBUGS("AvatarProperties") << result << LL_ENDL;
+ httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- if (!status)
- {
- LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL;
- return LLUUID::null;
- }
+ LL_DEBUGS("AvatarProperties") << result << LL_ENDL;
- if (result["state"].asString() != "complete")
- {
- if (result.has("message"))
+ if (!status)
{
- LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL;
+ if (upload_retry_count < MAX_UPLOAD_RETRIES)
+ {
+ upload_retry_count++;
+ LL_WARNS("AvatarProperties") << "Failed to upload image (attempt " << upload_retry_count
+ << " of " << (MAX_UPLOAD_RETRIES + 1) << "): " << status.toString()
+ << ", re-requesting uploader..." << LL_ENDL;
+ llcoro::suspendUntilTimeout(1.0f);
+ continue;
+ }
+ else
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts: " << status.toString() << LL_ENDL;
+ return LLUUID::null;
+ }
}
- else
+
+ // Todo: should we really repeat if 'complete' not set?
+ if (result["state"].asString() != "complete")
{
- LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL;
+ if (upload_retry_count < MAX_UPLOAD_RETRIES)
+ {
+ upload_retry_count++;
+ if (result.has("message"))
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"]
+ << " message: " << result["message"] << " (attempt "
+ << upload_retry_count << " of " << (MAX_UPLOAD_RETRIES + 1)
+ << "), re-requesting uploader..." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload image (attempt " << upload_retry_count
+ << " of " << (MAX_UPLOAD_RETRIES + 1)
+ << "), re-requesting uploader..." << LL_ENDL;
+ }
+ llcoro::suspendUntilTimeout(1.0f);
+ continue;
+ }
+ else
+ {
+ if (result.has("message"))
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts, state " << result["state"]
+ << " message: " << result["message"] << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload image after " << (MAX_UPLOAD_RETRIES + 1)
+ << " attempts" << LL_ENDL;
+ }
+ return LLUUID::null;
+ }
}
- return LLUUID::null;
+
+ // Success!
+ result_uuid = result["new_asset"].asUUID();
+ break;
}
- return result["new_asset"].asUUID();
+ return result_uuid;
}
enum EProfileImageType
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index bfdfa68e01..0fac70dbd2 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -1012,6 +1012,11 @@ LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTa
void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl)
{
+ if (slurl.empty())
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ return;
+ }
LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, static_cast<S32>(slurl.size()));
LLSD args;
diff --git a/indra/newview/llpanelvoicedevicesettings.cpp b/indra/newview/llpanelvoicedevicesettings.cpp
index d8d6bcf5fd..5aaa53b732 100644
--- a/indra/newview/llpanelvoicedevicesettings.cpp
+++ b/indra/newview/llpanelvoicedevicesettings.cpp
@@ -338,8 +338,12 @@ void LLPanelVoiceDeviceSettings::initialize()
// put voice client in "tuning" mode
if (mUseTuningMode)
{
+ // WebRTC tuning only affects the local audio device (mic-level
+ // monitoring and device selection); the peer connection stays up and
+ // its send/receive tracks are disabled for the duration. Unlike Vivox,
+ // there's no need to suspend (and tear down) the voice channel, which
+ // previously dropped the call and failed to reconnect on resume.
LLVoiceClient::getInstance()->tuningStart();
- LLVoiceChannel::suspend();
}
}
@@ -348,7 +352,6 @@ void LLPanelVoiceDeviceSettings::cleanup()
if (mUseTuningMode)
{
LLVoiceClient::getInstance()->tuningStop();
- LLVoiceChannel::resume();
}
}
diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp
deleted file mode 100644
index a0129b2cb1..0000000000
--- a/indra/newview/llpanelvoiceeffect.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * @file llpanelvoiceeffect.cpp
- * @author Aimee
- * @brief Panel to select Voice Morphs.
- *
- * $LicenseInfo:firstyear=2010&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 "llpanelvoiceeffect.h"
-
-#include "llcombobox.h"
-#include "llfloaterreg.h"
-#include "llpanel.h"
-#include "lltrans.h"
-#include "lltransientfloatermgr.h"
-#include "llvoiceclient.h"
-#include "llweb.h"
-
-static LLPanelInjector<LLPanelVoiceEffect> t_panel_voice_effect("panel_voice_effect");
-
-LLPanelVoiceEffect::LLPanelVoiceEffect()
- : mVoiceEffectCombo(NULL)
-{
- mCommitCallbackRegistrar.add("Voice.CommitVoiceEffect", boost::bind(&LLPanelVoiceEffect::onCommitVoiceEffect, this));
-}
-
-LLPanelVoiceEffect::~LLPanelVoiceEffect()
-{
- LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox");
- LLTransientFloaterMgr::getInstance()->removeControlView(combo_list_view);
-
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->removeObserver(this);
- }
- }
-}
-
-// virtual
-bool LLPanelVoiceEffect::postBuild()
-{
- mVoiceEffectCombo = getChild<LLComboBox>("voice_effect");
-
- // Need to tell LLTransientFloaterMgr about the combo list, otherwise it can't
- // be clicked while in a docked floater as it extends outside the floater area.
- LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox");
- LLTransientFloaterMgr::getInstance()->addControlView(combo_list_view);
-
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interface)
- {
- effect_interface->addObserver(this);
- }
-
- update(true);
-
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////
-/// PRIVATE SECTION
-//////////////////////////////////////////////////////////////////////////
-
-void LLPanelVoiceEffect::onCommitVoiceEffect()
-{
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (!effect_interface)
- {
- mVoiceEffectCombo->setEnabled(false);
- return;
- }
-
- LLSD value = mVoiceEffectCombo->getValue();
- if (value.asInteger() == PREVIEW_VOICE_EFFECTS)
- {
- // Open the Voice Morph preview floater
- LLFloaterReg::showInstance("voice_effect");
- }
- else if (value.asInteger() == GET_VOICE_EFFECTS)
- {
- // Open the voice morphing info web page
- LLWeb::loadURL(LLTrans::getString("voice_morphing_url"));
- }
- else
- {
- effect_interface->setVoiceEffect(value.asUUID());
- }
-
- mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect());
-}
-
-// virtual
-void LLPanelVoiceEffect::onVoiceEffectChanged(bool effect_list_updated)
-{
- update(effect_list_updated);
-}
-
-void LLPanelVoiceEffect::update(bool list_updated)
-{
- if (mVoiceEffectCombo)
- {
- LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- if (!effect_interface) return;
- if (list_updated)
- {
- // Add the default "No Voice Morph" entry.
- mVoiceEffectCombo->removeall();
- mVoiceEffectCombo->add(getString("no_voice_effect"), LLUUID::null);
- mVoiceEffectCombo->addSeparator();
-
- // Add entries for each Voice Morph.
- const voice_effect_list_t& effect_list = effect_interface->getVoiceEffectList();
- if (!effect_list.empty())
- {
- for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it)
- {
- mVoiceEffectCombo->add(it->first, it->second, ADD_BOTTOM);
- }
-
- mVoiceEffectCombo->addSeparator();
- }
-
- // Add the fixed entries to go to the preview floater or marketing page.
- mVoiceEffectCombo->add(getString("preview_voice_effects"), PREVIEW_VOICE_EFFECTS);
- mVoiceEffectCombo->add(getString("get_voice_effects"), GET_VOICE_EFFECTS);
- }
-
- if (effect_interface && LLVoiceClient::instance().isVoiceWorking())
- {
- // Select the current Voice Morph.
- mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect());
- mVoiceEffectCombo->setEnabled(true);
- }
- else
- {
- // If voice isn't working or Voice Effects are not supported disable the control.
- mVoiceEffectCombo->setValue(LLUUID::null);
- mVoiceEffectCombo->setEnabled(false);
- }
- }
-}
diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h
deleted file mode 100644
index f920e41081..0000000000
--- a/indra/newview/llpanelvoiceeffect.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * @file llpanelvoiceeffect.h
- * @author Aimee
- * @brief Panel to select Voice Effects.
- *
- * $LicenseInfo:firstyear=2010&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_PANELVOICEEFFECT_H
-#define LL_PANELVOICEEFFECT_H
-
-#include "llpanel.h"
-#include "llvoiceclient.h"
-
-class LLComboBox;
-
-class LLPanelVoiceEffect
- : public LLPanel
- , public LLVoiceEffectObserver
-{
-public:
- LOG_CLASS(LLPanelVoiceEffect);
-
- LLPanelVoiceEffect();
- virtual ~LLPanelVoiceEffect();
-
- bool postBuild() override;
-
-private:
- void onCommitVoiceEffect();
- void update(bool list_updated);
-
- /// Called by voice effect provider when voice effect list is changed.
- void onVoiceEffectChanged(bool effect_list_updated) override;
-
- // Fixed entries in the Voice Morph list
- typedef enum e_voice_effect_combo_items
- {
- NO_VOICE_EFFECT = 0,
- PREVIEW_VOICE_EFFECTS = 1,
- GET_VOICE_EFFECTS = 2
- } EVoiceEffectComboItems;
-
- LLComboBox* mVoiceEffectCombo;
-};
-
-
-#endif //LL_PANELVOICEEFFECT_H
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 5916163f60..94864797d5 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -532,7 +532,7 @@ void LLPanelVolume::getState( )
getChildView("FlexForceY")->setEnabled(true);
getChildView("FlexForceZ")->setEnabled(true);
- LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
+ LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData();
getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD());
getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity());
@@ -643,7 +643,7 @@ void LLPanelVolume::getState( )
mComboPhysicsShapeType->add(getString("None"), LLSD(1));
bool isMesh = false;
- LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = objectp->getSculptParams();
if (sculpt_params)
{
U8 sculpt_type = sculpt_params->getSculptType();
@@ -1043,7 +1043,7 @@ void LLPanelVolume::onCopyFeatures()
// Flexi Prim
if (volobjp && volobjp->isFlexible())
{
- LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
+ LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData();
if (attributes)
{
clipboard["flex"]["lod"] = attributes->getSimulateLOD();
@@ -1141,7 +1141,7 @@ void LLPanelVolume::onPasteFeatures()
objectp->setClickAction(CLICK_ACTION_NONE);
}
- LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
+ LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData();
if (attributes)
{
LLFlexibleObjectData new_attributes;
@@ -1568,7 +1568,7 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
return;
}
- LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
+ LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData();
if (attributes)
{
LLFlexibleObjectData new_attributes;
diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h
index 1a2098ec7e..38deb87237 100644
--- a/indra/newview/llperfstats.h
+++ b/indra/newview/llperfstats.h
@@ -223,7 +223,7 @@ namespace LLPerfStats
static void updateMeanFrameTime(U64 tot_frame_time_raw);
// StatsArray is a uint64_t for each possible statistic type.
using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>;
- using StatsMap = std::unordered_map<LLUUID, StatsArray, boost::hash<LLUUID>>;
+ using StatsMap = std::unordered_map<LLUUID, StatsArray>;
using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 9a991727b2..eefd19e153 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -79,6 +79,7 @@ LLPreviewNotecard::LLPreviewNotecard(const LLSD& key) //const LLUUID& item_id,
LLPreviewNotecard::~LLPreviewNotecard()
{
delete mLiveFile;
+ mEditor = nullptr;
}
bool LLPreviewNotecard::postBuild()
@@ -166,7 +167,7 @@ bool LLPreviewNotecard::handleKeyHere(KEY key, MASK mask)
// virtual
bool LLPreviewNotecard::canClose()
{
- if(mForceClose || mEditor->isPristine())
+ if(mForceClose || !mEditor || mEditor->isPristine())
{
return true;
}
diff --git a/indra/newview/llquickprefs.cpp b/indra/newview/llquickprefs.cpp
new file mode 100644
index 0000000000..9e83857a15
--- /dev/null
+++ b/indra/newview/llquickprefs.cpp
@@ -0,0 +1,228 @@
+/**
+ * @file llquickprefs.cpp
+ * @brief Quick Preferences floater: hover height and bandwidth sliders.
+ *
+ * Ported from Firestorm Viewer (quickprefs.cpp).
+ * Original authors: WoLf Loonie, Zi Ree, Ansariel Hiller @ Second Life.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Phoenix Firestorm Viewer Source Code
+ * Copyright (C) 2011, WoLf Loonie @ Second Life
+ *
+ * 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.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llquickprefs.h"
+
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llcheckboxctrl.h"
+#include "llsliderctrl.h"
+#include "lltextbox.h"
+#include "llviewercontrol.h"
+#include "llviewerregion.h"
+#include "llvoavatar.h" // for MIN_HOVER_Z / MAX_HOVER_Z
+#include "llvoavatarself.h" // for gAgentAvatarp, isAgentAvatarValid()
+
+// ---------------------------------------------------------------------------
+// Constructor / destructor
+// ---------------------------------------------------------------------------
+
+LLFloaterQuickPrefs::LLFloaterQuickPrefs(const LLSD& key)
+ : LLFloater(key)
+ , mAvatarZOffsetSlider(nullptr)
+{
+}
+
+LLFloaterQuickPrefs::~LLFloaterQuickPrefs()
+{
+ if (mRegionChangedSlot.connected())
+ {
+ mRegionChangedSlot.disconnect();
+ }
+}
+
+// ---------------------------------------------------------------------------
+// postBuild – wire up all widgets
+// ---------------------------------------------------------------------------
+
+bool LLFloaterQuickPrefs::postBuild()
+{
+ // ---- Hover height slider ------------------------------------------------
+ mAvatarZOffsetSlider = getChild<LLSliderCtrl>("HoverHeightSlider");
+ mAvatarZOffsetSlider->setMinValue(MIN_HOVER_Z);
+ mAvatarZOffsetSlider->setMaxValue(MAX_HOVER_Z);
+
+ // Live preview while dragging
+ mAvatarZOffsetSlider->setCommitCallback(
+ boost::bind(&LLFloaterQuickPrefs::onAvatarZOffsetSliderMoved, this));
+
+ // Persist on release or typed entry
+ mAvatarZOffsetSlider->setSliderMouseUpCallback(
+ boost::bind(&LLFloaterQuickPrefs::onAvatarZOffsetFinalCommit, this));
+ mAvatarZOffsetSlider->setSliderEditorCommitCallback(
+ boost::bind(&LLFloaterQuickPrefs::onAvatarZOffsetFinalCommit, this));
+
+ // Pull current value from settings
+ syncAvatarZOffsetFromPreferenceSetting();
+
+ // Keep slider in sync when something else changes the setting (e.g. RLVa,
+ // the Edit Shape floater, or the standalone Hover Height floater).
+ if (gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ"))
+ {
+ gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")
+ ->getCommitSignal()
+ ->connect(boost::bind(
+ &LLFloaterQuickPrefs::syncAvatarZOffsetFromPreferenceSetting, this));
+ }
+ else
+ {
+ LL_WARNS("QuickPrefs") << "Control 'AvatarHoverOffsetZ' not found" << LL_ENDL;
+ }
+
+ // Watch for region changes so we can enable/disable the slider
+ if (!mRegionChangedSlot.connected())
+ {
+ mRegionChangedSlot = gAgent.addRegionChangedCallback(
+ boost::bind(&LLFloaterQuickPrefs::onRegionChanged, this));
+ }
+ onRegionChanged(); // evaluate current region immediately
+
+ // OTS aim mode checkbox
+ mOTSEnabledCheck = getChild<LLCheckBoxCtrl>("ots_enabled");
+ if (mOTSEnabledCheck)
+ {
+ mOTSEnabledCheck->setCommitCallback(
+ boost::bind(&LLFloaterQuickPrefs::onOTSEnabledChanged, this));
+ }
+
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+// onClose
+// ---------------------------------------------------------------------------
+
+void LLFloaterQuickPrefs::onClose(bool app_quitting)
+{
+ if (mRegionChangedSlot.connected())
+ {
+ mRegionChangedSlot.disconnect();
+ }
+ LLFloater::onClose(app_quitting);
+}
+
+// ---------------------------------------------------------------------------
+// Hover height callbacks
+// ---------------------------------------------------------------------------
+
+void LLFloaterQuickPrefs::onAvatarZOffsetSliderMoved()
+{
+ F32 value = mAvatarZOffsetSlider->getValueF32();
+ LLVector3 offset(0.0f, 0.0f, llclamp(value, MIN_HOVER_Z, MAX_HOVER_Z));
+
+ LL_INFOS("Avatar") << "QuickPrefs: setting hover from slider moved " << offset[VZ] << LL_ENDL;
+
+ if (gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled())
+ {
+ if (mAvatarZOffsetSlider->isMouseHeldDown())
+ {
+ // Live preview: send to avatar but don't persist yet
+ if (isAgentAvatarValid())
+ {
+ gAgentAvatarp->setHoverOffset(offset, false);
+ }
+ }
+ else
+ {
+ // Committed (e.g. arrow-key step): persist immediately
+ gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ", value);
+ }
+ }
+ else if (isAgentAvatarValid())
+ {
+ gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ", value);
+ }
+}
+
+void LLFloaterQuickPrefs::onAvatarZOffsetFinalCommit()
+{
+ F32 value = mAvatarZOffsetSlider->getValueF32();
+ LL_INFOS("Avatar") << "QuickPrefs: setting hover from slider final commit " << value << LL_ENDL;
+ gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ",
+ llclamp(value, MIN_HOVER_Z, MAX_HOVER_Z));
+}
+
+// ---------------------------------------------------------------------------
+// Enable / disable based on region support
+// ---------------------------------------------------------------------------
+
+void LLFloaterQuickPrefs::updateAvatarZOffsetEditEnabled()
+{
+ bool enabled = gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+
+ if (!enabled && isAgentAvatarValid())
+ {
+ enabled = true;
+ }
+
+ mAvatarZOffsetSlider->setEnabled(enabled);
+
+ if (enabled)
+ {
+ syncAvatarZOffsetFromPreferenceSetting();
+ }
+}
+
+void LLFloaterQuickPrefs::onRegionChanged()
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region && region->simulatorFeaturesReceived())
+ {
+ updateAvatarZOffsetEditEnabled();
+ }
+ else if (region)
+ {
+ region->setSimulatorFeaturesReceivedCallback(
+ boost::bind(&LLFloaterQuickPrefs::onSimulatorFeaturesReceived, this, _1));
+ }
+}
+
+void LLFloaterQuickPrefs::onSimulatorFeaturesReceived(const LLUUID& region_id)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region && region->getRegionID() == region_id)
+ {
+ updateAvatarZOffsetEditEnabled();
+ }
+}
+
+void LLFloaterQuickPrefs::syncAvatarZOffsetFromPreferenceSetting()
+{
+ F32 value = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
+ mAvatarZOffsetSlider->setValue(value, false); // false = no commit signal
+}
+
+void LLFloaterQuickPrefs::onOTSEnabledChanged()
+{
+ if (mOTSEnabledCheck)
+ {
+ gSavedSettings.setBOOL("OTSEnabled", mOTSEnabledCheck->get());
+ // If currently in OTS mode and checkbox was unchecked, exit OTS
+ if (!mOTSEnabledCheck->get() && gAgentCamera.cameraOTS())
+ {
+ gAgentCamera.changeCameraFromOTS();
+ }
+ }
+}
diff --git a/indra/newview/llquickprefs.h b/indra/newview/llquickprefs.h
new file mode 100644
index 0000000000..b90333831c
--- /dev/null
+++ b/indra/newview/llquickprefs.h
@@ -0,0 +1,86 @@
+/**
+ * @file llquickprefs.h
+ * @brief Quick Preferences floater: hover height and bandwidth sliders.
+ *
+ * Ported from Firestorm Viewer (quickprefs.h / quickprefs.cpp).
+ * Original authors: WoLf Loonie, Zi Ree, Ansariel Hiller @ Second Life.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Phoenix Firestorm Viewer Source Code
+ * Copyright (C) 2011, WoLf Loonie @ Second Life
+ *
+ * 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.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLQUICKPREFS_H
+#define LL_LLQUICKPREFS_H
+
+#include "llfloater.h"
+
+class LLSliderCtrl;
+class LLCheckBoxCtrl;
+class LLTextBox;
+
+/**
+ * @class LLFloaterQuickPrefs
+ *
+ * A lightweight "Quick Preferences" panel that lets the user adjust commonly
+ * tweaked settings on the fly without opening the full Preferences dialog:
+ * - Avatar hover height
+ * - Maximum network bandwidth
+ *
+ * Hover-height logic is ported 1:1 from Firestorm's FloaterQuickPrefs so that
+ * live-preview while dragging, final commit on mouse-up, and region-feature
+ * gating all work exactly the same way.
+ */
+class LLFloaterQuickPrefs : public LLFloater
+{
+public:
+ LLFloaterQuickPrefs(const LLSD& key);
+ virtual ~LLFloaterQuickPrefs();
+
+ bool postBuild() override;
+ void onClose(bool app_quitting) override;
+
+private:
+ // ---- Hover height -------------------------------------------------------
+ LLSliderCtrl* mAvatarZOffsetSlider;
+
+ /** Called every frame while the slider thumb is being dragged.
+ * Sends a live (non-persistent) hover offset to the avatar so the user
+ * gets immediate visual feedback. */
+ void onAvatarZOffsetSliderMoved();
+
+ /** Called when the drag ends (mouse-up) or the user types a value.
+ * Persists the value to AvatarHoverOffsetZ. */
+ void onAvatarZOffsetFinalCommit();
+
+ /** Enable/disable the slider based on whether the current region supports
+ * server-side hover height. */
+ void updateAvatarZOffsetEditEnabled();
+
+ /** Called when the region changes so we can re-evaluate the above. */
+ void onRegionChanged();
+ void onSimulatorFeaturesReceived(const LLUUID& region_id);
+
+ /** Pulls AvatarHoverOffsetZ from saved settings and pushes it to the slider
+ * without triggering a commit (avoids feedback loops). */
+ void syncAvatarZOffsetFromPreferenceSetting();
+
+ boost::signals2::connection mRegionChangedSlot;
+
+ // OTS over-the-shoulder aim
+ LLCheckBoxCtrl* mOTSEnabledCheck { nullptr };
+ void onOTSEnabledChanged();
+};
+
+#endif // LL_LLQUICKPREFS_H
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index 7f5076bd56..f4f3e39f17 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -45,7 +45,8 @@ LLReflectionMap::~LLReflectionMap()
{
if (mOcclusionQuery)
{
- glDeleteQueries(1, &mOcclusionQuery);
+ gPipeline.mReflectionMapManager.recycleQuery(mOcclusionQuery);
+ mOcclusionQuery = 0;
}
}
@@ -341,7 +342,7 @@ void LLReflectionMap::doOcclusion(const LLVector4a& eye)
if (mOcclusionQuery == 0)
{ // no query was previously issued, allocate one and issue
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGenQueries");
- glGenQueries(1, &mOcclusionQuery);
+ mOcclusionQuery = gPipeline.mReflectionMapManager.allocateQuery();
do_query = true;
}
else
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index aa48035aa8..4d8f56d0c0 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -574,6 +574,7 @@ void LLReflectionMapManager::refreshSettings()
mRenderReflectionProbeLevel = gSavedSettings.getS32("RenderReflectionProbeLevel");
mRenderReflectionProbeCount = gSavedSettings.getU32("RenderReflectionProbeCount");
mRenderReflectionProbeDynamicAllocation = gSavedSettings.getS32("RenderReflectionProbeDynamicAllocation");
+ cleanupQueryPool();
}
LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
@@ -621,6 +622,25 @@ U32 LLReflectionMapManager::probeMemory()
return (mDynamicProbeCount * 6 * (mProbeResolution * mProbeResolution) * 4) / 1024 / 1024 + (mDynamicProbeCount * 6 * (LL_IRRADIANCE_MAP_RESOLUTION * LL_IRRADIANCE_MAP_RESOLUTION) * 4) / 1024 / 1024;
}
+GLuint LLReflectionMapManager::allocateQuery()
+{
+ if (mQueryPool.empty())
+ {
+ GLuint query;
+ glGenQueries(1, &query);
+ return query;
+ }
+
+ GLuint query = mQueryPool.front();
+ mQueryPool.pop_front();
+ return query;
+}
+
+void LLReflectionMapManager::recycleQuery(GLuint query)
+{
+ mQueryPool.push_back(query);
+}
+
struct CompareProbeDepth
{
bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs)
@@ -764,6 +784,7 @@ void LLReflectionMapManager::deleteProbe(U32 i)
other->mNeighbors.erase(iter);
}
+ // Probes are distance sorted, order matters.
mProbes.erase(mProbes.begin() + i);
}
@@ -1700,10 +1721,23 @@ void LLReflectionMapManager::cleanup()
glDeleteBuffers(1, &mUBO);
mUBO = 0;
+ cleanupQueryPool();
+
// note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state
initCubeFree();
}
+void LLReflectionMapManager::cleanupQueryPool()
+{
+ if (!mQueryPool.empty())
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("cleanup query pool");
+ std::vector<GLuint> queries(mQueryPool.begin(), mQueryPool.end());
+ glDeleteQueries(static_cast<GLsizei>(queries.size()), queries.data());
+ mQueryPool.clear();
+ }
+}
+
void LLReflectionMapManager::doOcclusion()
{
LLVector4a eye;
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 337c4ca7fa..cfca9afcb4 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -106,6 +106,7 @@ public:
// release any GL state
void cleanup();
+ void cleanupQueryPool();
// maintain reflection probes
void update();
@@ -164,6 +165,10 @@ public:
U32 probeCount();
U32 probeMemory();
+ // glDeleteQueries is expensive, so we maintain a pool of queries
+ GLuint allocateQuery();
+ void recycleQuery(GLuint query);
+
private:
friend class LLPipeline;
friend class LLHeroProbeManager;
@@ -190,6 +195,8 @@ private:
// bind UBO used for rendering
void setUniforms();
+ std::deque<GLuint> mQueryPool;
+
// render target for cube snapshots
// used to generate mipmaps without doing a copy-to-texture
LLRenderTarget mRenderTarget;
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index f89afd38ab..c1b33f313b 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -84,6 +84,7 @@ void LLRemoteParcelInfoProcessor::removeObserver(const LLUUID& parcel_id, LLRemo
//static
void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLParcelData parcel_data;
msg->getUUID ("Data", "ParcelID", parcel_data.parcel_id);
diff --git a/indra/newview/llscriptruntimeperms.h b/indra/newview/llscriptruntimeperms.h
index 300304c21b..6350b61d08 100644
--- a/indra/newview/llscriptruntimeperms.h
+++ b/indra/newview/llscriptruntimeperms.h
@@ -24,10 +24,7 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLSCRIPTRUNTIME_PERMS_H
-#define LL_LLSCRIPTRUNTIME_PERMS_H
-
-#include <boost/array.hpp>
+#pragma once
typedef struct _script_perm {
std::string question;
@@ -37,12 +34,12 @@ typedef struct _script_perm {
question(q), permbit(b), caution(c) {}
} script_perm_t;
-const U32 NUM_SCRIPT_PERMISSIONS = 18;
+const U32 NUM_SCRIPT_PERMISSIONS = 19;
const S32 SCRIPT_PERMISSION_DEBIT = 0;
const S32 SCRIPT_PERMISSION_TRIGGER_ANIMATION = 3;
const S32 SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS = 14;
-static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{
+static const std::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{
_script_perm("ScriptTakeMoney", (0x1 << 1), true),
_script_perm("ActOnControlInputs", (0x1 << 2), false),
_script_perm("RemapControlInputs", (0x1 << 3), false),
@@ -60,7 +57,7 @@ static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSI
_script_perm("OverrideYourAnimations", (0x1 << 15), false),
_script_perm("ScriptReturnObjects", (0x1 << 16), false),
_script_perm("ForceSitAvatar", (0x1 << 17), false),
- _script_perm("ChangeEnvSettings", (0x1 << 18), false)
+ _script_perm("ChangeEnvSettings", (0x1 << 18), false),
+ _script_perm("PrivilegedLandAccess",(0x1 << 19), true)
} };
-#endif // LL_LLSCRIPTRUNTIME_PERMS_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 758e91f6c9..32cf1f3ca1 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3054,7 +3054,6 @@ void LLSelectMgr::logNoOp(LLSelectNode* node, void *)
// static
void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *)
{
- LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID);
}
// static
@@ -6193,6 +6192,15 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
node->mCategory = category;
node->mName.assign(name);
node->mDescription.assign(desc);
+
+ LLViewerObject* obj = node->getObject();
+ if (obj && LLViewerObject::isObjectInPendingUpdate(owner_id, obj))
+ {
+ // current response doesn't return modify permissions flags,
+ // so we should request it separately if needed
+ obj->requestObjectUpdate();
+ }
+
}
dialog_refresh_all();
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index b48417bd71..623db82939 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -402,8 +402,6 @@ void LLSidepanelInventory::onOpen(const LLSD& key)
gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", (U32)time_corrected());
}
#endif
-
- gAgent.showLatestFeatureNotification("inventory");
}
void LLSidepanelInventory::performActionOnSelection(const std::string &action)
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index a147cb4657..d2c7c5e5ce 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -135,9 +135,13 @@ void LLSpatialGroup::clearDrawMap()
mDrawMap.clear();
}
-bool LLSpatialGroup::isHUDGroup()
+bool LLSpatialGroup::isHUDGroup() const
{
- return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ;
+ if (hasState(DEAD))
+ return false;
+
+ LLSpatialPartition* part = (LLSpatialPartition*)mSpatialPartition;
+ return part && part->isHUDPartition();
}
void LLSpatialGroup::validate()
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index d8a94c8835..4b312b1597 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -264,7 +264,7 @@ public:
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
- bool isHUDGroup() ;
+ bool isHUDGroup() const;
void clearDrawMap();
void validate();
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index f079c70c6c..c75314825c 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -438,7 +438,7 @@ void LLSpeakerMgr::update(bool resort_ok)
{
if(speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL)
{
- // external speakers should be timed out when they leave the voice channel (since they only exist via SLVoice)
+ // external speakers should be timed out when they leave the voice channel
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
}
else
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 937b680515..494a1b3378 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -207,6 +207,7 @@
#include "llstartuplistener.h"
#include "lltoolbarview.h"
#include "llexperiencelog.h"
+#include "llgroupcolormap.h" // group-based nameplate tinting
#include "llcleanup.h"
#include "llenvironment.h"
@@ -1380,6 +1381,10 @@ bool idle_startup()
{
set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
do_startup_frame();
+
+ // close login UI before world UI is initialized, if it is still visible
+ LLPanelLogin::closePanel();
+
// We should have an agent id by this point.
llassert(!(gAgentID == LLUUID::null));
@@ -2659,8 +2664,9 @@ void uninstall_nsis_if_required()
S32 found_minor = 0;
S32 found_patch = 0;
U64 found_build = 0;
+ std::string nsis_path;
- if (!get_nsis_version(found_major, found_minor, found_patch, found_build))
+ if (!get_nsis_version(found_major, found_minor, found_patch, found_build, nsis_path))
{
return;
}
@@ -2692,7 +2698,7 @@ void uninstall_nsis_if_required()
// so there is no point to check build.
LL_INFOS() << "Found NSIS install " << found_major << "." << found_minor << "." << found_patch << "." << found_build << LL_ENDL;
- clear_nsis_links();
+ clear_nsis_links(nsis_path);
LLSD args;
args["VERSION"] = llformat("%d.%d.%d", found_major, found_minor, found_patch);
@@ -3268,14 +3274,22 @@ void reset_login()
if ( gViewerWindow )
{ // Hide menus and normal buttons
gViewerWindow->setNormalControlsVisible( false );
- gLoginMenuBarView->setVisible( true );
- gLoginMenuBarView->setEnabled( true );
+
+ if (gLoginMenuBarView)
+ {
+ gLoginMenuBarView->setVisible(true);
+ gLoginMenuBarView->setEnabled(true);
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "gLoginMenuBarView not initialized" << LL_ENDL;
+ }
}
// Hide any other stuff
LLFloaterReg::hideVisibleInstances();
- if (LLStartUp::getStartupState() > STATE_WORLD_INIT)
+ if (LLStartUp::getStartupState() > STATE_WORLD_INIT && gViewerWindow)
{
gViewerWindow->resetStatusBarContainer();
}
@@ -3343,6 +3357,9 @@ void LLStartUp::initExperiences()
boost::bind(&LLAgent::getRegionCapability, &gAgent, _1));
LLExperienceLog::instance().initialize();
+
+ // Load per-group nameplate colors for this account
+ LLGroupColorMap::getInstance()->loadFromDisk();
}
void LLStartUp::cleanupNameCache()
diff --git a/indra/newview/llstatslistener.cpp b/indra/newview/llstatslistener.cpp
new file mode 100644
index 0000000000..b0f8d54231
--- /dev/null
+++ b/indra/newview/llstatslistener.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file llstatslistener.cpp
+ * @brief EventAPI interface for querying performance statistics
+ *
+ * $LicenseInfo:firstyear=2026&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2026, 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 "llstatslistener.h"
+
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llimagegl.h"
+#include "llviewerstats.h"
+
+namespace
+{
+template <typename STAT, typename EXTRACTOR>
+LLSD collectPeriodArray(LLTrace::PeriodicRecording& recording,
+ size_t num_periods,
+ const STAT& stat,
+ EXTRACTOR extractor)
+{
+ LLSD values = LLSD::emptyArray();
+ for (size_t i = 1; i <= num_periods; ++i)
+ {
+ LLTrace::Recording& period = recording.getPrevRecording(i);
+ if (period.hasValue(stat))
+ {
+ values.append((F64)extractor(period, stat));
+ }
+ }
+ return values;
+}
+
+template <typename STAT, typename EXTRACTOR>
+void setPeriodArray(LLSD& out,
+ const char* key,
+ LLTrace::Recording& last,
+ LLTrace::PeriodicRecording& recording,
+ size_t num_periods,
+ const STAT& stat,
+ EXTRACTOR extractor)
+{
+ if (last.hasValue(stat))
+ {
+ out[key] = collectPeriodArray(recording, num_periods, stat, extractor);
+ }
+}
+}
+
+LLStatsListener::LLStatsListener()
+ : LLEventAPI("LLStats", "Query performance statistics")
+{
+ add("getPerfData",
+ "Get performance data from the frame recording buffer, plus texture memory\n"
+ "and inventory loading timing information.\n"
+ "Reply contains [\"stats\"] with nested group maps.",
+ &LLStatsListener::getPerfData,
+ llsd::map("reply", LLSD()));
+}
+
+void LLStatsListener::getPerfData(LLSD const & evt)
+{
+ LLEventAPI::Response response(LLSD(), evt);
+
+ // get_frame_recording() is a PeriodicRecording with 200 periods
+ LLTrace::PeriodicRecording& recording = LLTrace::get_frame_recording();
+ LLTrace::Recording& last = recording.getLastRecording();
+
+ size_t num_periods = recording.getNumRecordedPeriods();
+ F64 total_duration = recording.getDuration().value();
+
+ LLSD stats;
+ stats["total_periods_duration"] = total_duration;
+ stats["num_periods"] = (LLSD::Integer)num_periods;
+
+ LLSD frametime;
+
+ setPeriodArray(frametime, "fps", last, recording, num_periods, LLStatViewer::FPS,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getPerSec(stat); });
+
+ setPeriodArray(frametime, "frame_time_ms", last, recording, num_periods, LLStatViewer::FRAMETIME,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ setPeriodArray(frametime, "do_frame_time_us", last, recording, num_periods, LLStatViewer::DOFRAME_TIME_US,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ setPeriodArray(frametime, "frame_time_jitter_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ // Normalized jitter - scalar samples updated per frame
+ // report the current (last) value since they are session/period rolling stats
+ if (last.hasValue(LLStatViewer::NOTRMALIZED_FRAMETIME_JITTER_SESSION))
+ {
+ frametime["normalized_jitter_session"] = last.getLastValue(LLStatViewer::NOTRMALIZED_FRAMETIME_JITTER_SESSION);
+ }
+ if (last.hasValue(LLStatViewer::NORMALIZED_FRAMTIME_JITTER_PERIOD))
+ {
+ frametime["normalized_jitter_period"] = last.getLastValue(LLStatViewer::NORMALIZED_FRAMTIME_JITTER_PERIOD);
+ }
+ if (last.hasValue(LLStatViewer::NFTV))
+ {
+ frametime["normalized_frametime_variation"] = last.getLastValue(LLStatViewer::NFTV);
+ }
+
+ // Jitter event minute counters: running avg per minute and count in last completed minute
+ // These are already minute-window aggregates, so sending single value, not arrays
+ if (last.hasValue(LLStatViewer::FRAMETIME_JITTER_EVENTS_PER_MINUTE))
+ {
+ frametime["frame_time_jitter_events_per_minute"] = (F64)last.getLastValue(LLStatViewer::FRAMETIME_JITTER_EVENTS_PER_MINUTE);
+ }
+ if (last.hasValue(LLStatViewer::FRAMETIME_JITTER_EVENTS_LAST_MINUTE))
+ {
+ frametime["frame_time_jitter_events_last_minute"] = (F64)last.getLastValue(LLStatViewer::FRAMETIME_JITTER_EVENTS_LAST_MINUTE);
+ }
+
+ // Jitter percentiles / cumulative
+ setPeriodArray(frametime, "jitter_cumulative_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER_CUMULATIVE,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(frametime, "jitter_99th_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER_99TH,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(frametime, "jitter_95th_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER_95TH,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(frametime, "jitter_stddev_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER_STDDEV,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ // Frame time percentiles
+ setPeriodArray(frametime, "frametime_99th_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_99TH,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(frametime, "frametime_95th_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_95TH,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(frametime, "frametime_stddev_ms", last, recording, num_periods, LLStatViewer::FRAMETIME_STDDEV,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ // Frametime jitter event count
+ setPeriodArray(frametime, "frametime_jitter_events", last, recording, num_periods, LLStatViewer::FRAMETIME_JITTER_EVENTS,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ stats["frametime"] = frametime;
+
+ LLSD other;
+
+ // Packet loss
+ setPeriodArray(other, "packet_loss_percent", last, recording, num_periods, LLStatViewer::PACKETS_LOST_PERCENT,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ // Sim ping
+ setPeriodArray(other, "sim_ping_ms", last, recording, num_periods, LLStatViewer::SIM_PING,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ // Triangle rendering
+ setPeriodArray(other, "ktris_per_frame", last, recording, num_periods, LLStatViewer::TRIANGLES_DRAWN,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getSum(stat); });
+ setPeriodArray(other, "ktris_per_sec", last, recording, num_periods, LLStatViewer::TRIANGLES_DRAWN,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getPerSec(stat); });
+
+ // Object counts
+ setPeriodArray(other, "num_objects", last, recording, num_periods, LLStatViewer::NUM_OBJECTS,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+ setPeriodArray(other, "num_active_objects", last, recording, num_periods, LLStatViewer::NUM_ACTIVE_OBJECTS,
+ [](LLTrace::Recording& period, const auto& stat) { return period.getMean(stat); });
+
+ stats["other"] = other;
+
+ // texture memory usage
+ LLSD memory;
+ memory["texture_bytes_alloc_mb"] = (F64)LLImageGL::getTextureBytesAllocated() / 1024.0 / 512.0;
+ stats["memory"] = memory;
+
+ LLSD inventory;
+ // library skeleton cache load duration
+ inventory["skeleton_load_time_library_seconds"] = gInventory.getLibrarySkeletonLoadTime();
+ // agent skeleton cache load duration
+ inventory["skeleton_load_time_agent_seconds"] = gInventory.getAgentSkeletonLoadTime();
+ // initial recursive inventory/library background fetch duration
+ inventory["initial_fetch_time_seconds"] = LLInventoryModelBackgroundFetch::instance().getInitialFetchDuration();
+ inventory["fetch_completed"] = LLInventoryModelBackgroundFetch::instance().isEverythingFetched();
+ stats["inventory"] = inventory;
+
+ response["stats"] = stats;
+}
diff --git a/indra/newview/llfloatersounddevices.h b/indra/newview/llstatslistener.h
index 9b21b62747..77777034c7 100644
--- a/indra/newview/llfloatersounddevices.h
+++ b/indra/newview/llstatslistener.h
@@ -1,11 +1,10 @@
/**
- * @file llfloatersounddevices.h
- * @author Leyla Farazha
- * @brief Sound Preferences used for minimal skin
+ * @file llstatslistener.h
+ * @brief EventAPI interface for querying performance statistics
*
-* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2026&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2026, 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
@@ -25,25 +24,18 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLFLOATERSOUNDDEVICES_H
-#define LL_LLFLOATERSOUNDDEVICES_H
+#ifndef LL_LLSTATSLISTENER_H
+#define LL_LLSTATSLISTENER_H
-#include "lltransientdockablefloater.h"
+#include "lleventapi.h"
-class LLFloaterSoundDevices : public LLTransientDockableFloater
+class LLStatsListener : public LLEventAPI
{
public:
+ LLStatsListener();
- LOG_CLASS(LLFloaterSoundDevices);
-
- LLFloaterSoundDevices(const LLSD& key);
- ~LLFloaterSoundDevices();
-
- bool postBuild() override;
- void setDocked(bool docked, bool pop_on_undock = true) override;
- void setFocus(bool b) override;
+private:
+ void getPerfData(LLSD const & evt);
};
-
-#endif //LL_LLFLOATERSOUNDDEVICES_H
-
+#endif // LL_LLSTATSLISTENER_H
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 1a7ce74ccc..8c8734b52f 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -875,7 +875,7 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id)
//debug
bool LLTextureCache::isInCache(const LLUUID& id)
{
- LLMutexLock lock(&mHeaderMutex);
+ LLMutexLock lock(&mHeaderIDMapMutex);
id_map_t::const_iterator iter = mHeaderIDMap.find(id);
return (iter != mHeaderIDMap.end()) ;
@@ -991,6 +991,8 @@ void LLTextureCache::setReadOnly(bool read_only)
// Returns the unused amount of max_size if any
S64 LLTextureCache::initCache(ELLPath location, S64 max_size, bool texture_cache_mismatch)
{
+ LL_PROFILE_ZONE_SCOPED;
+
llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
S64 entries_size = (max_size * 36) / 100; //0.36 * max_size
@@ -1115,10 +1117,13 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create
{
S32 idx = -1;
- id_map_t::iterator iter1 = mHeaderIDMap.find(id);
- if (iter1 != mHeaderIDMap.end())
{
- idx = iter1->second;
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ id_map_t::iterator iter1 = mHeaderIDMap.find(id);
+ if (iter1 != mHeaderIDMap.end())
+ {
+ idx = iter1->second;
+ }
}
if (idx < 0)
@@ -1146,10 +1151,19 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create
// Erase entry from LRU regardless
mLRU.erase(curiter2);
// Look up entry and use it if it is valid
- id_map_t::iterator iter3 = mHeaderIDMap.find(oldid);
- if (iter3 != mHeaderIDMap.end() && iter3->second >= 0)
+
+ S32 found_idx = -1;
{
- idx = iter3->second;
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ id_map_t::iterator iter3 = mHeaderIDMap.find(oldid);
+ if (iter3 != mHeaderIDMap.end() && iter3->second >= 0)
+ {
+ found_idx = iter3->second;
+ }
+ }
+ if (found_idx >= 0)
+ {
+ idx = found_idx;
removeCachedTexture(oldid) ;//remove the existing cached texture to release the entry index.
break;
}
@@ -1285,7 +1299,10 @@ bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32
bool update_header = false ;
if(entry.mImageSize < 0) //is a brand-new entry
{
- mHeaderIDMap[entry.mID] = idx;
+ {
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ mHeaderIDMap[entry.mID] = idx;
+ }
mTexturesSizeMap[entry.mID] = new_body_size ;
mTexturesSizeTotal += new_body_size ;
@@ -1323,8 +1340,8 @@ bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32
U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
{
+ LLMutexLock lock(&mHeaderIDMapMutex);
U32 num_entries = mHeaderEntriesInfo.mEntries;
-
mHeaderIDMap.clear();
mTexturesSizeMap.clear();
mFreeList.clear();
@@ -1618,7 +1635,10 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
LLFile::rmdir(mTexturesDirName);
}
}
- mHeaderIDMap.clear();
+ {
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ mHeaderIDMap.clear();
+ }
mTexturesSizeMap.clear();
mTexturesSizeTotal = 0;
mFreeList.clear();
@@ -1665,6 +1685,7 @@ void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec)
{
if (iter1->second > 0)
{
+ LLMutexLock lock(&mHeaderIDMapMutex);
id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
if (iter2 != mHeaderIDMap.end())
{
@@ -1706,8 +1727,13 @@ void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec)
Entry entry = mPurgeEntryList.back().second;
mPurgeEntryList.pop_back();
// make sure record is still valid
- id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID);
- if (iter_header != mHeaderIDMap.end() && iter_header->second == idx)
+ bool remove_entry = false;
+ {
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID);
+ remove_entry = (iter_header != mHeaderIDMap.end() && iter_header->second == idx);
+ }
+ if (remove_entry)
{
std::string tex_filename = getTextureFileName(entry.mID);
removeEntry(idx, entry, tex_filename);
@@ -1750,6 +1776,7 @@ void LLTextureCache::purgeTextures(bool validate)
{
if (iter1->second > 0)
{
+ LLMutexLock lock(&mHeaderIDMapMutex);
id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
if (iter2 != mHeaderIDMap.end())
{
@@ -2004,7 +2031,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
{
U32 offset;
{
- LLMutexLock lock(&mHeaderMutex);
+ LLMutexLock lock(&mHeaderIDMapMutex);
id_map_t::const_iterator iter = mHeaderIDMap.find(id);
if(iter == mHeaderIDMap.end())
{
@@ -2018,9 +2045,10 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
U8* data;
S32 head[4];
{
+ LL_PROFILE_ZONE_NAMED("Read fast cache");
LLMutexLock lock(&mFastCacheMutex);
- openFastCache();
+ openFastCache(); // only reopens if needed, lasts 10 seconds
mFastCachep->seek(APR_SET, offset);
@@ -2051,7 +2079,9 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
closeFastCache();
}
- LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true);
+
+ // directly construct image from new buffer.
+ LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true /*take ownership*/);
return raw;
}
@@ -2229,7 +2259,10 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
mTexturesSizeTotal -= mTexturesSizeMap[id] ;
mTexturesSizeMap.erase(id);
}
- mHeaderIDMap.erase(id);
+ {
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ mHeaderIDMap.erase(id);
+ }
// We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
// but getLocalAPRFilePool() is not safe, it might be in use by worker
LLAPRFile::remove(getTextureFileName(id), mHeaderAPRFilePoolp);
@@ -2260,7 +2293,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
entry.mImageSize = -1;
entry.mBodySize = 0;
- mHeaderIDMap.erase(entry.mID);
+ {
+ LLMutexLock lock(&mHeaderIDMapMutex);
+ mHeaderIDMap.erase(entry.mID);
+ }
mTexturesSizeMap.erase(entry.mID);
mFreeList.insert(idx);
}
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index faf722dc8f..a09bcc1572 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -148,7 +148,7 @@ public:
U32 getMaxEntries() { return sCacheMaxEntries; };
bool isInCache(const LLUUID& id) ;
bool isInLocal(const LLUUID& id) ; //not thread safe at the moment
-
+ LLMutex* getFastCacheMutex() { return &mFastCacheMutex; }
protected:
// Accessed by LLTextureCacheWorker
std::string getLocalFileName(const LLUUID& id);
@@ -194,6 +194,7 @@ private:
// Internal
LLMutex mWorkersMutex;
LLMutex mHeaderMutex;
+ LLMutex mHeaderIDMapMutex; // To avoid deadlocks, never lock mFastCacheMutex after mHeaderIDMapMutex.
LLMutex mListMutex;
LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile;
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 52ec8c17c1..001c4a0449 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -285,7 +285,7 @@ void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bo
void LLFloaterTexturePicker::setActive( bool active )
{
- if (!active && getChild<LLUICtrl>("Pipette")->getValue().asBoolean())
+ if (!active && mPipetteBtn->getValue().asBoolean())
{
stopUsingPipette();
}
@@ -658,7 +658,10 @@ bool LLFloaterTexturePicker::postBuild()
mSavedFolderState.setApply(false);
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
+ mPipetteConnection = LLToolPipette::getInstance()->setToolSelectCallback([this](LLPointer<LLViewerObject> object, S32 te_index)
+ {
+ onPipetteSelect(object, te_index);
+ });
getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
@@ -1069,7 +1072,7 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)
void LLFloaterTexturePicker::onBtnPipette()
{
- bool pipette_active = getChild<LLUICtrl>("Pipette")->getValue().asBoolean();
+ bool pipette_active = mPipetteBtn->getValue().asBoolean();
pipette_active = !pipette_active;
if (pipette_active)
{
@@ -1419,8 +1422,7 @@ void LLFloaterTexturePicker::changeMode()
getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(index == PICKER_BAKE);
getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(false);// index == 2);
- bool pipette_visible = (index == PICKER_INVENTORY)
- && (mInventoryPickType != PICK_MATERIAL);
+ bool pipette_visible = (index == PICKER_INVENTORY);
mPipetteBtn->setVisible(pipette_visible);
if (index == PICKER_BAKE)
@@ -1560,15 +1562,8 @@ void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type)
refreshLocalList();
refreshInventoryFilter();
- if (mInventoryPickType == PICK_MATERIAL)
- {
- getChild<LLButton>("Pipette")->setVisible(false);
- }
- else
- {
- S32 index = mModeSelector->getValue().asInteger();
- getChild<LLButton>("Pipette")->setVisible(index == 0);
- }
+ S32 index = mModeSelector->getValue().asInteger();
+ mPipetteBtn->setVisible(index == 0);
if (!mLabel.empty())
{
@@ -1640,39 +1635,88 @@ void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& fi
}
}
-void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
+void LLFloaterTexturePicker::onPipetteSelect(LLPointer<LLViewerObject>& object, S32 te_index)
{
- LLUUID inventory_item_id = findItemID(te.getID(), true);
- if (inventory_item_id.notNull())
+ if (mInventoryPickType == PICK_MATERIAL)
{
- LLToolPipette::getInstance()->setResult(true, "");
- if (mInventoryPickType == PICK_MATERIAL)
- {
- // tes have no data about material ids
- // Plus gltf materials are layered with overrides,
- // which mean that end result might have no id.
- LL_WARNS() << "tes have no data about material ids" << LL_ENDL;
- }
- else
+ // Note: does not copy overrides!
+ LLUUID mat_id = object->getRenderMaterialID(te_index);
+ if (mat_id == BLANK_MATERIAL_ASSET_ID)
{
- setImageID(te.getID());
+ // It's fine if blank material isn't in inventory, just set it
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(mat_id);
setTentative(false);
- }
- mNoCopyTextureSelected = false;
- LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+ mNoCopyTextureSelected = false;
- if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ commitIfImmediateSet();
+ }
+ else if (mat_id.isNull())
{
- // no copy texture
- mNoCopyTextureSelected = true;
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoMaterial"));
}
+ else
+ {
+ LLUUID inventory_item_id = findItemID(mat_id, true);
+ if (inventory_item_id.notNull())
+ {
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(mat_id);
+ setTentative(false);
+
+ mNoCopyTextureSelected = false;
+ LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ mNoCopyTextureSelected = true;
+ }
- commitIfImmediateSet();
+ commitIfImmediateSet();
+ }
+ else
+ {
+ // Not in inventory, can't apply
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoMaterial"));
+ }
+ }
}
else
{
- LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
+ const LLTextureEntry* entry = object->getTE(te_index);
+ if (!entry)
+ {
+ // Whatever was selected is not a face/TE,
+ // no texture to check, so do nothing.
+ // Should not be reachable, if you hit this,
+ // check what happens in pipette tool.
+ llassert(false);
+ return;
+ }
+ LLUUID inventory_item_id = findItemID(entry->getID(), true);
+ if (inventory_item_id.notNull())
+ {
+ LLToolPipette::getInstance()->setResult(true, "");
+ setImageID(entry->getID());
+ setTentative(false);
+
+ mNoCopyTextureSelected = false;
+ LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ mNoCopyTextureSelected = true;
+ }
+
+ commitIfImmediateSet();
+ }
+ else
+ {
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
+ }
}
}
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index e0060474ce..759711ebf7 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -374,7 +374,7 @@ public:
static void onBtnNone(void* userdata);
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, bool user_action);
static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
- void onTextureSelect(const LLTextureEntry& te);
+ void onPipetteSelect(LLPointer<LLViewerObject>& object, S32 te_index);
static void onModeSelect(LLUICtrl* ctrl, void *userdata);
static void onBtnAdd(void* userdata);
@@ -457,6 +457,8 @@ private:
set_image_asset_id_callback mSetImageAssetIDCallback;
set_on_update_image_stats_callback mOnUpdateImageStatsCallback;
+ boost::signals2::scoped_connection mPipetteConnection;
+
bool mBakeTextureEnabled;
bool mLocalTextureEnabled;
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 8cbede8303..cbe2dac52a 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -250,7 +250,7 @@ void LLTextureBar::draw()
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// Draw the progress bar.
- S32 bar_width = 100;
+ S32 bar_width = 110;
S32 bar_left = 260;
left = bar_left;
right = left + bar_width;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 6c0b3bfa13..e905a879cb 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -38,6 +38,7 @@
#include "llnotifications.h"
#include "lluiconstants.h"
#include "llrect.h"
+#include "llstring.h"
#include "lltrans.h"
#include "llnotificationsutil.h"
#include "llviewermessage.h"
@@ -46,7 +47,7 @@
const S32 BOTTOM_PAD = VPAD * 3;
const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding
-S32 BUTTON_WIDTH = 90;
+const S32 BUTTON_WIDTH = 90;
//static
@@ -58,7 +59,8 @@ LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal
LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)
: LLCheckBoxToastPanel(notification)
, LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID())
-, mTextBox(NULL)
+, mTextBox(NULL),
+ mButtonWidth(BUTTON_WIDTH)
{
init(rect, show_images);
}
@@ -69,9 +71,9 @@ void LLToastNotifyPanel::addDefaultButton()
LLButton* ok_btn = createButton(form_element, false);
LLRect new_btn_rect(ok_btn->getRect());
- new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - BUTTON_WIDTH)/ 2, BOTTOM_PAD,
+ new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - mButtonWidth) / 2, BOTTOM_PAD,
//auto_size for ok button makes it very small, so let's make it wider
- BUTTON_WIDTH, new_btn_rect.getHeight());
+ mButtonWidth, new_btn_rect.getHeight());
ok_btn->setRect(new_btn_rect);
addChild(ok_btn, -1);
mNumButtons = 1;
@@ -90,15 +92,31 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, bool is_opt
std::string name = form_element["name"].asString();
std::string text = form_element["text"].asString();
bool make_small_btn = index == -1 || index == -2; // for block and ignore buttons in script dialog
+
+ // Use Emoji font as exception if text contains red heart emoji (10084 U+2764) to ensure proper rendering
+ std::string font_name = mIsScriptDialog ? sFontScript : sFontDefault;
+ if (mIsScriptDialog)
+ {
+ LLWString wtext = utf8str_to_wstring(text);
+ for (llwchar ch : wtext)
+ {
+ if (ch == 0x2764)
+ {
+ font_name = "Emoji";
+ break;
+ }
+ }
+ }
+
const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor(
- mIsScriptDialog ? sFontScript : sFontDefault, make_small_btn ? "Small" : "Medium", 0));
+ font_name, make_small_btn ? "Small" : "Medium", 0));
p.name = name;
p.label = text;
p.tool_tip = text;
p.font = font;
p.rect.height = BTN_HEIGHT;
p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
- p.rect.width = BUTTON_WIDTH;
+ p.rect.width = mButtonWidth;
p.auto_resize = false;
p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();
@@ -108,7 +126,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, bool is_opt
p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
}
// for the scriptdialog buttons we use fixed button size. This is a limit!
- if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (BUTTON_WIDTH-2*HPAD))
+ if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (mButtonWidth - 2 * HPAD))
{
p.rect.width = 1;
p.auto_resize = true;
@@ -273,7 +291,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
mInfoPanel = getChild<LLPanel>("info_panel");
mControlPanel = getChild<LLPanel>("control_panel");
- BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
+
// customize panel's attributes
// is it intended for displaying a tip?
mIsTip = mNotification->getType() == "notifytip";
@@ -282,6 +300,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
// is it a script dialog?
mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup");
+ static LLCachedControl<S32> btn_width(gSavedSettings, "ToastButtonWidth", 90);
+ static LLCachedControl<S32> script_button_width(gSavedSettings, "ScriptToastButtonWidth", 127);
+ mButtonWidth = mIsScriptDialog ? script_button_width : btn_width;
+
bool is_content_trusted = (notif_name != "LoadWebPage");
// is it a caution?
//
@@ -362,8 +384,21 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
}
else
{
- const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel
+ S32 button_panel_width = mControlPanel->getRect().getWidth();// get initial width from XML
S32 button_panel_height = mControlPanel->getRect().getHeight();
+
+ // Script dialog has wider buttons so it requires wider layout to ensure proper spacing
+ if (mIsScriptDialog)
+ {
+ // width for 3 columns: 3 buttons + 2 gaps
+ S32 min_width_required = 3 * mButtonWidth + 2 * (2 * HPAD);
+ if (min_width_required > button_panel_width)
+ {
+ button_panel_width = min_width_required;
+ S32 width_increase = button_panel_width - mControlPanel->getRect().getWidth();
+ reshape(getRect().getWidth() + width_increase, getRect().getHeight());
+ }
+ }
//try get an average h_pad to spread out buttons
S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size()));
if(h_pad < 2*HPAD)
@@ -373,8 +408,8 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons.
* In last case set default h_pad to avoid heaping of buttons
*/
- S32 button_per_row = button_panel_width / BUTTON_WIDTH;
- h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row
+ S32 button_per_row = button_panel_width / mButtonWidth;
+ h_pad = (button_panel_width % mButtonWidth) / (button_per_row - 1);// -1 because we do not need space after last button in a row
if(h_pad < 2*HPAD) // still not enough space between buttons ?
{
h_pad = 2*HPAD;
@@ -385,7 +420,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
// we are using default width for script buttons so we can determinate button_rows
// to get a number of rows we divide the required width of the buttons to button_panel_width
// buttons.size() is reduced by -2 due to presence of ignore button which is calculated independently a bit lower
- S32 button_rows = llceil(F32(buttons.size() - 2) * (BUTTON_WIDTH + h_pad) / (button_panel_width + h_pad));
+ S32 button_rows = llceil(F32(buttons.size() - 2) * (mButtonWidth + h_pad) / (button_panel_width + h_pad));
//reserve one row for the ignore_btn
button_rows++;
//calculate required panel height for scripdialog notification.
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index d694513aba..71b9eaf8f5 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -134,6 +134,8 @@ protected:
S32 mNumOptions { 0 };
S32 mNumButtons { 0 };
+ S32 mButtonWidth;
+
static const std::string sFontDefault;
static const std::string sFontScript;
};
diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp
index 25dc0982b8..55e178e084 100644
--- a/indra/newview/lltoastscriptquestion.cpp
+++ b/indra/newview/lltoastscriptquestion.cpp
@@ -48,7 +48,12 @@ bool LLToastScriptQuestion::postBuild()
LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message");
mMessage->setValue(mNotification->getMessage());
- mFooter->setValue(mNotification->getFooter());
+ std::string footer = mNotification->getFooter();
+ mFooter->setValue(footer);
+ if (footer.empty())
+ {
+ mFooter->setVisible(false);
+ }
snapToMessageHeight();
@@ -78,21 +83,69 @@ void LLToastScriptQuestion::snapToMessageHeight()
if (mMessage->getVisible() && mFooter->getVisible())
{
- S32 heightDelta = 0;
- S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT)
+ S32 height_delta = 0;
+ S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT)
+ (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT);
- LLRect messageRect = mMessage->getRect();
- LLRect footerRect = mFooter->getRect();
+ LLRect message_rect = mMessage->getRect();
+
+ S32 old_message_height = message_rect.getHeight();
+ S32 new_message_height = mMessage->getTextBoundingRect().getHeight();
+ S32 new_footer_height = mFooter->getTextBoundingRect().getHeight();
+
+ constexpr S32 FOOTER_PADDING = 8; // new height should include padding for newly added footer
+ S32 required_text_height = new_message_height + new_footer_height + FOOTER_PADDING;
+ S32 new_text_height = llmin(required_text_height, max_text_height);
+
+ // Footer was invisible, so use old_message_height for old height
+ height_delta = new_text_height - old_message_height;
+
+ reshape( getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT));
+
+ // Floater was resized, now resize and shift children
+ // Message follows top, so it's top is in a correct position, but needs to be resized down
+ S32 message_delta = new_message_height - old_message_height;
+ message_rect = mMessage->getRect(); // refresh since it might have changed after reshape
+ message_rect.mBottom = message_rect.mBottom - message_delta;
+ mMessage->setRect(message_rect);
+ mMessage->needsReflow();
+ // Button panel should stay the same size, just translate it
+ LLPanel* panel = getChild<LLPanel>("buttons_panel");
+ panel->translate(0, -message_delta);
+ // Footer should be both moved and resized
+ LLRect footer_rect = mFooter->getRect();
+ footer_rect.mTop = footer_rect.mTop - message_delta;
+ footer_rect.mBottom = footer_rect.mTop - new_footer_height;
+ mFooter->setRect(footer_rect);
+ mFooter->needsReflow();
+ }
+ else if (mMessage->getVisible())
+ {
+ S32 height_delta = 0;
+ S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT);
+
+ LLRect message_rect = mMessage->getRect();
+
+ S32 old_message_height = message_rect.getHeight();
+ S32 new_message_height = mMessage->getTextBoundingRect().getHeight();
- S32 oldTextHeight = messageRect.getHeight() + footerRect.getHeight();
+ S32 new_text_height = llmin(new_message_height, max_text_height);
- S32 requiredTextHeight = mMessage->getTextBoundingRect().getHeight() + mFooter->getTextBoundingRect().getHeight();
- S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
+ // Footer was invisible, so use old_message_height for old height
+ height_delta = new_text_height - old_message_height;
- heightDelta = newTextHeight - oldTextHeight - heightDelta;
+ reshape(getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT));
- reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));
+ // Floater was resized, now resize and shift children
+ // Message follows top, so it's top is in a correct position, but needs to be resized down
+ S32 message_delta = new_message_height - old_message_height;
+ message_rect = mMessage->getRect(); // refresh since it might have changed after reshape
+ message_rect.mBottom = message_rect.mBottom - message_delta;
+ mMessage->setRect(message_rect);
+ mMessage->needsReflow();
+ // Button panel should stay the same size, just translate it
+ LLPanel* panel = getChild<LLPanel>("buttons_panel");
+ panel->translate(0, -message_delta);
}
}
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index c6e59a81c9..ff6c692699 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -52,6 +52,7 @@
#include "llagentcamera.h"
#include "llfloatertools.h"
#include "llviewercontrol.h"
+#include "llviewercamera.h" // NaCl: mouselook right-click zoom
extern LLControlGroup gSavedSettings;
@@ -791,10 +792,42 @@ bool LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
return false;
*/
+ // NaCl: Right-click + scroll wheel zoom in mouselook (ported from Firestorm).
+ // When right mouse is pressed without Alt, record the current FOV as the
+ // pre-zoom value (VX) and swap in the stored zoom target (VY).
+ // VZ == 1.0 means "currently zoomed", 0.0 means "not zoomed".
+ if (!(gKeyboard->currentMask(true) & MASK_ALT))
+ {
+ LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues");
+ F32 cameraAngle = gSavedSettings.getF32("CameraAngle");
+ mlFovValues.mV[VX] = cameraAngle; // save normal FOV
+ mlFovValues.mV[VZ] = 1.0f; // mark as zoomed
+ gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues);
+ gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VY]); // apply zoom FOV
+ }
+ // NaCl End
+
// Returning true will suppress the context menu
return true;
}
+// NaCl: Right-click + scroll wheel zoom in mouselook (ported from Firestorm).
+// Restore the pre-zoom FOV when the right mouse button is released.
+bool LLToolCompGun::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues");
+ F32 cameraAngle = gSavedSettings.getF32("CameraAngle");
+ if (mlFovValues.mV[VZ] == 1.0f) // only restore if we entered zoom
+ {
+ mlFovValues.mV[VY] = cameraAngle; // save last zoomed FOV for next right-click
+ mlFovValues.mV[VZ] = 0.0f; // mark as not zoomed
+ gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues);
+ gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VX]); // restore normal FOV
+ }
+ return true;
+}
+// NaCl End
+
bool LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
{
@@ -831,10 +864,28 @@ void LLToolCompGun::handleDeselect()
bool LLToolCompGun::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- if (clicks > 0)
+ // NaCl: Right-click + scroll wheel zoom in mouselook (ported from Firestorm).
+ // If currently zoomed (right mouse held, VZ == 1.0), adjust the zoom level
+ // with the scroll wheel. Otherwise fall through to the original behaviour.
+ LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues");
+ F32 cameraAngle = gSavedSettings.getF32("CameraAngle");
+ mlFovValues.mV[VY] = cameraAngle;
+ if (mlFovValues.mV[VZ] > 0.0f)
+ {
+ // Scroll up (clicks > 0) = narrower FOV (zoom in); scroll down = wider (zoom out).
+ mlFovValues.mV[VY] = llclamp(
+ mlFovValues.mV[VY] + (F32)(clicks * 0.1f),
+ LLViewerCamera::getInstance()->getMinView(),
+ LLViewerCamera::getInstance()->getMaxView());
+ gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues);
+ gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VY]);
+ }
+ else if (clicks > 0 && gSavedSettings.getBOOL("FSScrollWheelExitsMouselook"))
{
+ // Not zoomed: scroll up exits mouselook (original behaviour, now gated by setting).
gAgentCamera.changeCameraToDefault();
-
}
+ // NaCl End
+
return true;
}
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index 4b945967d1..d868b2e9bf 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -53,6 +53,7 @@ public:
virtual bool handleHover(S32 x, S32 y, MASK mask) { return mCur->handleHover( x, y, mask ); }
virtual bool handleScrollWheel(S32 x, S32 y, S32 clicks) { return mCur->handleScrollWheel( x, y, clicks ); }
virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask) { return mCur->handleRightMouseDown( x, y, mask ); }
+ virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask) { return mCur->handleRightMouseUp( x, y, mask ); } // NaCl: mouselook zoom
virtual LLViewerObject* getEditingObject() { return mCur->getEditingObject(); }
virtual LLVector3d getEditingPointGlobal() { return mCur->getEditingPointGlobal(); }
@@ -228,6 +229,7 @@ public:
virtual bool handleMouseDown(S32 x, S32 y, MASK mask) override;
virtual bool handleDoubleClick(S32 x, S32 y, MASK mask) override;
virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask) override; // NaCl: mouselook zoom
virtual bool handleMouseUp(S32 x, S32 y, MASK mask) override;
virtual bool handleScrollWheel(S32 x, S32 y, S32 clicks) override;
virtual void onMouseCaptureLost() override;
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index f78ff2226c..5e2d91d31e 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -775,7 +775,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, bool drop,
if (!handled)
{
// Disallow drag and drop to 3D from the marketplace
- const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.notNull())
{
for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 07963a7bed..c7e6f774dc 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -57,6 +57,7 @@
#include "llviewerjoystick.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
+#include "lleventapi.h"
// Used when app not active to avoid processing hover.
@@ -69,6 +70,67 @@ LLToolset* gMouselookToolset = NULL;
LLToolset* gFaceEditToolset = NULL;
/////////////////////////////////////////////////////
+// LLToolMgrListener
+
+class LLToolMgrListener: public LLEventAPI
+{
+public:
+ LLToolMgrListener():
+ LLEventAPI("LLToolMgr",
+ "LLToolMgr listener for tool management operations")
+ {
+ add("openBuildFloater",
+ "Open the build floater by toggling build mode",
+ &LLToolMgrListener::openFloater);
+ add("selectTool",
+ "Select the specified tool by [\"tool_name\"]. Valid tool names: Focus, Move, Edit, Create, Land",
+ &LLToolMgrListener::selectTool);
+ }
+
+private:
+ void openFloater(const LLSD& event) const
+ {
+ LLToolMgr::getInstance()->toggleBuildMode(LLSD("build"));
+ }
+
+ void selectTool(const LLSD& event) const
+ {
+ if (!event.has("tool_name"))
+ {
+ LL_WARNS() << "selectTool: called without tool_name" << LL_ENDL;
+ return;
+ }
+
+ static const std::unordered_map<std::string, S32> tool_indices = {
+ {"focus", 1},
+ {"move", 2},
+ {"edit", 3},
+ {"create", 4},
+ {"land", 5}
+ };
+
+ const std::string tool_name = utf8str_tolower(event["tool_name"].asString());
+ const auto it = tool_indices.find(tool_name);
+ if (it == tool_indices.end())
+ {
+ LL_WARNS() << "selectTool: unknown tool_name: " << std::quoted(tool_name) << LL_ENDL;
+ return;
+ }
+
+ LLToolset* current_toolset = LLToolMgr::getInstance()->getCurrentToolset();
+ if (!current_toolset)
+ {
+ LL_WARNS() << "selectTool: no current toolset available" << LL_ENDL;
+ return;
+ }
+
+ current_toolset->selectToolByIndex(it->second);
+ }
+};
+
+static LLToolMgrListener sToolMgrListener;
+
+/////////////////////////////////////////////////////
// LLToolMgr
LLToolMgr::LLToolMgr()
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 0a69be528f..a2122d0da5 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -237,6 +237,7 @@ bool LLToolPie::handleScrollHWheel(S32 x, S32 y, S32 clicks)
// True if you selected an object.
bool LLToolPie::handleLeftClickPick()
{
+ static LLCachedControl<bool> prevent_click_to_sit(gSavedSettings, "PreventClickToSit");
S32 x = mPick.mMousePt.mX;
S32 y = mPick.mMousePt.mY;
MASK mask = mPick.mKeyMask;
@@ -303,7 +304,7 @@ bool LLToolPie::handleLeftClickPick()
break;
case CLICK_ACTION_SIT:
{
- if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting
+ if (!prevent_click_to_sit && isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting
{
handle_object_sit_or_stand();
// put focus in world when sitting on an object
@@ -498,6 +499,7 @@ U8 final_click_action(LLViewerObject* obj)
ECursorType LLToolPie::cursorFromObject(LLViewerObject* object)
{
+ static LLCachedControl<bool> prevent_click_to_sit(gSavedSettings, "PreventClickToSit");
LLViewerObject* parent = NULL;
if (object)
{
@@ -509,7 +511,7 @@ ECursorType LLToolPie::cursorFromObject(LLViewerObject* object)
{
case CLICK_ACTION_SIT:
{
- if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // not already sitting?
+ if (!prevent_click_to_sit && isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // not already sitting?
{
cursor = UI_CURSOR_TOOLSIT;
}
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 9e3d435688..6ec25e9512 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -47,8 +47,8 @@
//
LLToolPipette::LLToolPipette()
-: LLTool(std::string("Pipette")),
- mSuccess(true)
+: LLTool(std::string("Pipette"))
+, mSuccess(true)
{
}
@@ -103,15 +103,6 @@ bool LLToolPipette::handleToolTip(S32 x, S32 y, MASK mask)
return true;
}
-void LLToolPipette::setTextureEntry(const LLTextureEntry* entry)
-{
- if (entry)
- {
- mTextureEntry = *entry;
- mSignal(mTextureEntry);
- }
-}
-
void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
{
LLViewerObject* hit_obj = pick_info.getObject();
@@ -120,12 +111,14 @@ void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
// if we clicked on a face of a valid prim, save off texture entry data
if (hit_obj &&
hit_obj->getPCode() == LL_PCODE_VOLUME &&
- pick_info.mObjectFace != -1)
+ pick_info.mObjectFace != -1 &&
+ hit_obj->getNumTEs() > pick_info.mObjectFace)
{
//TODO: this should highlight the selected face only
LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj);
- const LLTextureEntry* entry = hit_obj->getTE(pick_info.mObjectFace);
- LLToolPipette::getInstance()->setTextureEntry(entry);
+
+ LLPointer<LLViewerObject> hit_obj_ptr = hit_obj;
+ LLToolPipette::getInstance()->mSignal(hit_obj_ptr, pick_info.mObjectFace);
}
}
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 6c79674d76..7771f467e5 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -51,16 +51,13 @@ public:
virtual bool handleHover(S32 x, S32 y, MASK mask) override;
virtual bool handleToolTip(S32 x, S32 y, MASK mask) override;
- // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
- typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
- void setToolSelectCallback(const signal_t::slot_type& cb) { mSignal.connect(cb); }
+ typedef boost::signals2::signal<void (LLPointer<LLViewerObject> obj, S32 te_index)> signal_t;
+ boost::signals2::connection setToolSelectCallback(const signal_t::slot_type& cb) { return mSignal.connect(cb); }
void setResult(bool success, const std::string& msg);
- void setTextureEntry(const LLTextureEntry* entry);
static void pickCallback(const LLPickInfo& pick_info);
protected:
- LLTextureEntry mTextureEntry;
signal_t mSignal;
bool mSuccess;
std::string mTooltipMsg;
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index 5ccda7d4eb..3bd459f5b0 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -55,17 +55,17 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite )
: LLTool( std::string("Select"), composite ),
mIgnoreGroup( false )
{
- }
+}
// True if you selected an object.
bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
{
// do immediate pick query
bool pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick");
- bool pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects");
- bool pick_reflection_probe = gSavedSettings.getBOOL("SelectReflectionProbes");
+ static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects");
+ static LLCachedControl<bool> select_reflection_probes(gSavedSettings, "SelectReflectionProbes");
- mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged, false, true, pick_reflection_probe);
+ mPick = gViewerWindow->pickImmediate(x, y, select_invisible_objects, pick_rigged, false, true, select_reflection_probes);
// Pass mousedown to agent
LLTool::handleMouseDown(x, y, mask);
@@ -73,7 +73,6 @@ bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
return mPick.getObject().notNull();
}
-
// static
LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, bool ignore_group, bool temp_select, bool select_root)
{
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
index beae71e7bf..d95560b306 100644
--- a/indra/newview/lluilistener.cpp
+++ b/indra/newview/lluilistener.cpp
@@ -37,6 +37,7 @@
#include "llui.h" // getRootView(), resolvePath()
#include "lluictrl.h"
#include "llerror.h"
+#include "llcombobox.h"
LLUIListener::LLUIListener():
@@ -55,6 +56,12 @@ LLUIListener::LLUIListener():
"current value as [\"value\"] reply.",
&LLUIListener::getValue,
LLSDMap("path", LLSD())("reply", LLSD()));
+
+ add("setSelectedByValue",
+ "For the combobox identified by the path in [\"path\"] set selection by [\"value\"],\n"
+ "and return result as [\"reply\"]",
+ &LLUIListener::setSelectedByValue,
+ llsd::map("path", LLSD(), "value", LLSD(), "reply", LLSD()));
}
void LLUIListener::call(const LLSD& event) const
@@ -99,3 +106,20 @@ void LLUIListener::getValue(const LLSD&event) const
sendReply(reply, event);
}
+
+void LLUIListener::setSelectedByValue(const LLSD& event) const
+{
+ Response response(LLSD(), event);
+ std::string path(event["path"]);
+ LLComboBox* combo_ctrl = dynamic_cast<LLComboBox*>(LLUI::getInstance()->resolvePath(LLUI::getInstance()->getRootView(), path));
+ if (combo_ctrl)
+ {
+ response.setResponse(combo_ctrl->setSelectedByValue(event["value"], true));
+ return;
+ }
+ else
+ {
+ LL_WARNS() << "Specified combobox doesn't exist: " << path << LL_ENDL;
+ }
+ response.setResponse(false);
+}
diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h
index 70455c2c68..228e67ae26 100644
--- a/indra/newview/lluilistener.h
+++ b/indra/newview/lluilistener.h
@@ -42,6 +42,7 @@ public:
private:
void call(const LLSD& event) const;
void getValue(const LLSD&event) const;
+ void setSelectedByValue(const LLSD& event) const;
};
#endif /* ! defined(LL_LLUILISTENER_H) */
diff --git a/indra/newview/llvelopack.cpp b/indra/newview/llvelopack.cpp
index 28e989c4ba..90eb977bba 100644
--- a/indra/newview/llvelopack.cpp
+++ b/indra/newview/llvelopack.cpp
@@ -330,14 +330,14 @@ static std::wstring get_desktop_path()
return L"";
}
-static bool create_shortcut(const std::wstring& shortcut_path,
+static HRESULT create_shortcut(const std::wstring& shortcut_path,
const std::wstring& target_path,
const std::wstring& arguments,
const std::wstring& description,
const std::wstring& icon_path)
{
HRESULT hr = CoInitialize(NULL);
- if (FAILED(hr)) return false;
+ if (FAILED(hr)) return hr;
IShellLinkW* shell_link = nullptr;
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
@@ -365,7 +365,7 @@ static bool create_shortcut(const std::wstring& shortcut_path,
}
CoUninitialize();
- return SUCCEEDED(hr);
+ return hr;
}
static void register_protocol_handler(const std::wstring& protocol,
@@ -405,9 +405,172 @@ static void register_protocol_handler(const std::wstring& protocol,
}
}
-void clear_nsis_links()
+static bool get_shortcut_target(const std::wstring& lnk_path, std::wstring& target_path_str)
+{
+ // Resolve the shortcut to check its target
+ wchar_t target_path[MAX_PATH] = { 0 };
+ HRESULT hr = CoInitialize(NULL);
+ bool res = false;
+ if (SUCCEEDED(hr))
+ {
+ IShellLinkW* psl = nullptr;
+ hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&psl);
+ if (SUCCEEDED(hr))
+ {
+ IPersistFile* ppf = nullptr;
+ hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+ if (SUCCEEDED(hr))
+ {
+ hr = ppf->Load(lnk_path.c_str(), STGM_READ);
+ if (SUCCEEDED(hr))
+ {
+ // Resolve() in theory may retarget to a different executable,
+ // but we should be fine as long as folder stays the same,
+ // otherwise we shouldn't clear it.
+ hr = psl->Resolve(NULL, SLR_NO_UI | SLR_NOUPDATE | SLR_ANY_MATCH);
+ if (SUCCEEDED(hr))
+ {
+ hr = psl->GetPath(target_path, MAX_PATH, nullptr, 0);
+ if (SUCCEEDED(hr))
+ {
+ target_path_str = std::wstring(target_path);
+ res = true;
+ }
+ }
+ }
+ ppf->Release();
+ }
+ psl->Release();
+ }
+ CoUninitialize();
+ }
+ return res;
+}
+
+static bool paths_are_equal(const std::wstring& path1, const std::wstring& path2)
+{
+ try
+ {
+ std::error_code ec1, ec2;
+ std::filesystem::path p1(path1);
+ std::filesystem::path p2(path2);
+
+ // Get canonical (absolute, normalized) paths
+ auto canonical1 = std::filesystem::canonical(p1, ec1);
+ auto canonical2 = std::filesystem::canonical(p2, ec2);
+
+ // If either path doesn't exist, fall back to string comparison
+ if (ec1 || ec2)
+ {
+ // Normalize case for comparison
+ std::wstring lower1 = path1;
+ std::wstring lower2 = path2;
+ std::transform(lower1.begin(), lower1.end(), lower1.begin(), ::towlower);
+ std::transform(lower2.begin(), lower2.end(), lower2.begin(), ::towlower);
+ while (!lower1.empty() && (lower1.back() == L'\\' || lower1.back() == L'/'))
+ {
+ lower1.pop_back();
+ }
+ while (!lower2.empty() && (lower2.back() == L'\\' || lower2.back() == L'/'))
+ {
+ lower2.pop_back();
+ }
+ return lower1 == lower2;
+ }
+
+ // Use filesystem::equivalent which handles all path variations
+ return std::filesystem::equivalent(canonical1, canonical2, ec1);
+ }
+ catch (const std::filesystem::filesystem_error&)
+ {
+ // Fallback to case-insensitive string comparison
+ std::wstring lower1 = path1;
+ std::wstring lower2 = path2;
+ std::transform(lower1.begin(), lower1.end(), lower1.begin(), ::towlower);
+ std::transform(lower2.begin(), lower2.end(), lower2.begin(), ::towlower);
+ while (!lower1.empty() && (lower1.back() == L'\\' || lower1.back() == L'/'))
+ {
+ lower1.pop_back();
+ }
+ while (!lower2.empty() && (lower2.back() == L'\\' || lower2.back() == L'/'))
+ {
+ lower2.pop_back();
+ }
+ return lower1 == lower2;
+ }
+}
+
+static void update_taskbar_shortcut(const std::string& nsis_folder_path, const std::wstring& appdata_path, const std::wstring& app_name, const std::wstring& link_name)
+{
+ std::wstring taskbar_path = appdata_path;
+ taskbar_path += L"\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar\\";
+ taskbar_path += link_name;
+
+ if (!PathFileExistsW(taskbar_path.c_str()))
+ {
+ // User didn't create one
+ return;
+ }
+
+ // Verify we are removing or updating the right thing.
+ // It is not warranteed that the shortcut points to NSIS.
+ std::wstring target_path;
+ if (get_shortcut_target(taskbar_path, target_path))
+ {
+ // Strip the filename part to get just the folder path
+ std::filesystem::path trim_path(target_path);
+ if (trim_path.has_filename())
+ {
+ target_path = trim_path.parent_path().wstring();
+ }
+ std::wstring nsis_path_w = ll_convert<std::wstring>(nsis_folder_path);
+ if (!paths_are_equal(nsis_path_w, target_path))
+ {
+ // Shortcut points to something else, don't mess with it
+ LL_INFOS("Velopack") << "Found a matching shortcut, but it points to a different channel. Expected: "
+ << ll_convert_wide_to_string(nsis_path_w)
+ << ", actual: " << ll_convert_wide_to_string(target_path)
+ << LL_ENDL;
+ return;
+ }
+ }
+
+ // First try to overwrite shortcut
+ std::wstring current_exe = ll_convert<std::wstring>(gDirUtilp->getExecutablePathAndName());
+ HRESULT hr = create_shortcut(taskbar_path, current_exe, L"", app_name, current_exe);
+ if (SUCCEEDED(hr))
+ {
+ LL_INFOS("Velopack") << "Successfully updated taskbar shortcut to point to current exe" << LL_ENDL;
+ return;
+ }
+
+ // Try deleting and if possible, recreating separately. We should not leave hanging shortcuts behind.
+ if (!DeleteFileW(taskbar_path.c_str()))
+ {
+ DWORD error = GetLastError();
+ if (error != ERROR_FILE_NOT_FOUND)
+ {
+ LL_WARNS("Velopack") << "Failed to delete NSIS taskbar shortcut: "
+ << ll_convert_wide_to_string(taskbar_path)
+ << " (error: " << error << ")" << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Deleted user created link, recreate it with new target if possible.
+ LL_INFOS("Velopack") << "Updating taskbar shortcut to point to current exe" << LL_ENDL;
+ HRESULT hr = create_shortcut(taskbar_path, current_exe, L"", app_name, current_exe);
+ if (FAILED(hr))
+ {
+ LL_WARNS("Velopack") << "Failed to re-create taskbar shortcut, error: " << std::hex << hr << ", NSIS shortcut was removed" << LL_ENDL;
+ }
+ }
+}
+
+void clear_nsis_links(const std::string& nsis_folder_path)
{
wchar_t path[MAX_PATH];
+ std::wstring app_name = get_app_name();
// 1. The 'start' shortcuts set by nsis would be global, like app shortcut:
// C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Second Life Viewer\Second Life Viewer.lnk
@@ -415,7 +578,7 @@ void clear_nsis_links()
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, path)))
{
std::wstring start_menu_path = path;
- std::wstring folder_path = start_menu_path + L"\\" + get_app_name();
+ std::wstring folder_path = start_menu_path + L"\\" + app_name;
std::error_code ec;
std::filesystem::path dir(folder_path);
@@ -431,11 +594,11 @@ void clear_nsis_links()
}
// 2. Desktop link, also a global one.
- // C:\Users\Public\Desktop
+ // C:\Users\Public\Desktop\Second Life Viewer.lnk
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, path)))
{
std::wstring desktop_path = path;
- std::wstring shortcut_path = desktop_path + L"\\" + get_app_name() + L".lnk";
+ std::wstring shortcut_path = desktop_path + L"\\" + app_name + L".lnk";
if (!DeleteFileW(shortcut_path.c_str()))
{
DWORD error = GetLastError();
@@ -447,6 +610,19 @@ void clear_nsis_links()
}
}
}
+
+ // 3. Taskbar links, which are user-specific and located at:
+ // %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\
+ // Note that it can be a link to velopack already or to a different NSIS viewer.
+ // Name might also be different based on method of creation.
+ if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path)))
+ {
+ update_taskbar_shortcut(nsis_folder_path, path, app_name, L"Second Life.lnk"); // Window class name
+ update_taskbar_shortcut(nsis_folder_path, path, app_name, L"Second Life(1).lnk"); // Just in case user somehow did it twice and removed first
+ update_taskbar_shortcut(nsis_folder_path, path, app_name, L"SecondLifeViewer.lnk"); // Executable name
+ update_taskbar_shortcut(nsis_folder_path, path, app_name, L"secondlife-bin.lnk"); // Debug builds
+ update_taskbar_shortcut(nsis_folder_path, path, app_name, app_name + L".lnk"); // Default name
+ }
}
static void parse_version(const wchar_t* version_str, int& major, int& minor, int& patch, uint64_t& build)
@@ -462,7 +638,8 @@ bool get_nsis_version(
int& nsis_major,
int& nsis_minor,
int& nsis_patch,
- uint64_t& nsis_build)
+ uint64_t& nsis_build,
+ std::string& nsis_path)
{
// Test for presence of NSIS viewer registration, then
// attempt to read uninstall info
@@ -515,12 +692,21 @@ bool get_nsis_version(
}
std::error_code ec;
std::filesystem::path path(path_buffer);
+ // check if uninstaller exists
if (!std::filesystem::exists(path, ec))
{
return false;
}
- // Todo: check codesigning?
+ // We found a valid NSIS installation, trim the path to get the folder
+ wchar_t* pos = wcsstr(path_buffer, L"uninst.exe");
+ if (pos)
+ {
+ // Trim uninst.exe from the path by setting null terminator before it
+ *pos = L'\0';
+ }
+ // Note that it has a trailing backslash.
+ nsis_path = ll_convert_wide_to_string(path_buffer);
return true;
}
@@ -647,6 +833,32 @@ static void on_first_run(void* p_user_data, const char* app_version)
MultiByteToWideChar(CP_UTF8, 0, app_version, -1, &version[0], len);
register_uninstall_info(install_dir, app_name, version);
+ // Drop install related settings
+ // Unfortunately gDirUtilp is not initialized yet and it's shouldn't
+ // be possible to change location of the settings. For now it's simpler
+ // to hardcode the location.
+ std::optional<std::string> app_data = LLStringUtil::getoptenv("APPDATA");
+ if (app_data)
+ {
+ // Strip trailing delimiter if present
+ std::string app_data_path = *app_data;
+ if (!app_data_path.empty() && (app_data_path.back() == '\\' || app_data_path.back() == '/'))
+ {
+ app_data_path.pop_back();
+ }
+
+ std::string user_settings_path = app_data_path + "\\SecondLife\\user_settings\\settings.xml";
+ LLControlGroup settings("global");
+ if (settings.loadFromFile(user_settings_path))
+ {
+ // If user reinstalls or updates, we want to recheck for nsis leftovers.
+ if (settings.controlExists("PreviousInstallChecked"))
+ {
+ settings.setBOOL("PreviousInstallChecked", false);
+ }
+ settings.saveToFile(user_settings_path, true);
+ }
+ }
}
static void on_after_install(void* user_data, const char* app_version)
diff --git a/indra/newview/llvelopack.h b/indra/newview/llvelopack.h
index d04d0db7dc..449330f68d 100644
--- a/indra/newview/llvelopack.h
+++ b/indra/newview/llvelopack.h
@@ -46,12 +46,13 @@ void velopack_set_progress_callback(std::function<void(int)> callback);
void velopack_cleanup();
#if LL_WINDOWS
-void clear_nsis_links();
+void clear_nsis_links(const std::string& nsis_folder_path);
bool get_nsis_version(
int& nsis_major,
int& nsis_minor,
int& nsis_patch,
- uint64_t& nsis_build);
+ uint64_t& nsis_build,
+ std::string& nsis_folder_path);
#endif
#endif // LL_VELOPACK
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 65a69acc88..46c76e2953 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -881,6 +881,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
if (uploadInfo->showUploadDialog())
{
+ // todo: localize this string
std::string uploadMessage = "Uploading...\n\n";
uploadMessage.append(uploadInfo->getDisplayName());
LLUploadDialog::modalUploadDialog(uploadMessage);
@@ -888,66 +889,90 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
LLSD body = uploadInfo->generatePostBody();
- result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOptions);
+ // Retry stage-2 upload by re-requesting a fresh one-time uploader capability (up to 3 attempts total)
+ const S32 MAX_UPLOAD_RETRIES = 2;
+ S32 upload_retry_count = 0;
+ LLCore::HttpStatus status;
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if ((!status) || (result.has("error")))
+ while (upload_retry_count <= MAX_UPLOAD_RETRIES)
{
- HandleUploadError(status, result, uploadInfo);
- if (uploadInfo->showUploadDialog())
- LLUploadDialog::modalUploadFinished();
- return;
- }
+ // Stage 1: Request uploader URL
+ result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOptions);
- std::string uploader = result["uploader"].asString();
-
- bool success = false;
- if (!uploader.empty() && uploadInfo->getAssetId().notNull())
- {
- result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType(), httpOptions);
- httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- std::string ulstate = result["state"].asString();
-
- if ((!status) || (ulstate != "complete"))
+ if ((!status) || (result.has("error")))
{
HandleUploadError(status, result, uploadInfo);
if (uploadInfo->showUploadDialog())
LLUploadDialog::modalUploadFinished();
return;
}
- if (!result.has("success"))
+
+ std::string uploader = result["uploader"].asString();
+ if (uploader.empty() || uploadInfo->getAssetId().isNull())
{
- result["success"] = LLSD::Boolean((ulstate == "complete") && status);
+ LL_WARNS() << "No upload url provided. Nothing uploaded, responding with previous result." << LL_ENDL;
+ break;
}
- S32 uploadPrice = result["upload_price"].asInteger();
+ // Stage 2: Upload to the uploader URL
+ result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType(), httpOptions);
+ httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- if (uploadPrice > 0)
- {
- // this upload costed us L$, update our balance
- // and display something saying that it cost L$
- LLStatusBar::sendMoneyBalanceRequest();
+ std::string ulstate = result["state"].asString();
- LLSD args;
- args["AMOUNT"] = llformat("%d", uploadPrice);
- LLNotificationsUtil::add("UploadPayment", args);
+ if ((!status) || (ulstate != "complete"))
+ {
+ if (upload_retry_count < MAX_UPLOAD_RETRIES)
+ {
+ upload_retry_count++;
+ LL_WARNS() << "Upload to uploader failed (attempt " << upload_retry_count
+ << " of " << (MAX_UPLOAD_RETRIES + 1) << "), re-requesting uploader..." << LL_ENDL;
+ llcoro::suspendUntilTimeout(1.0f);
+ continue;
+ }
+ else
+ {
+ HandleUploadError(status, result, uploadInfo);
+ if (uploadInfo->showUploadDialog())
+ LLUploadDialog::modalUploadFinished();
+ return;
+ }
}
+
+ // Success!
+ break;
}
- else
+
+ if (!result.has("success"))
+ {
+ result["success"] = LLSD::Boolean((result["state"].asString() == "complete") && status);
+ }
+
+ S32 uploadPrice = result["upload_price"].asInteger();
+
+ if (uploadPrice > 0)
{
- LL_WARNS() << "No upload url provided. Nothing uploaded, responding with previous result." << LL_ENDL;
+ // this upload costed us L$, update our balance
+ // and display something saying that it cost L$
+ LLStatusBar::sendMoneyBalanceRequest();
+
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", uploadPrice);
+ LLNotificationsUtil::add("UploadPayment", args);
}
+
LLUUID serverInventoryItem = uploadInfo->finishUpload(result);
+ bool succeeded = false;
if (uploadInfo->showInventoryPanel())
{
if (serverInventoryItem.notNull())
{
- success = true;
+ succeeded = true;
LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
@@ -973,7 +998,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
{
- floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", succeeded).with("msg", "inventory")));
}
}
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index aa0cbac91f..a7441febd9 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -398,18 +398,12 @@ void init_audio()
void audio_update_volume(bool force_update)
{
- F32 master_volume = gSavedSettings.getF32("AudioLevelMaster");
- bool mute_audio = gSavedSettings.getBOOL("MuteAudio");
-
- LLProgressView* progress = gViewerWindow->getProgressView();
- bool progress_view_visible = false;
-
- if (progress)
- {
- progress_view_visible = progress->getVisible();
- }
+ static LLCachedControl<F32> master_volume(gSavedSettings, "AudioLevelMaster");
+ static LLCachedControl<bool> mute_audio_setting(gSavedSettings, "MuteAudio");
+ static LLCachedControl<bool> mute_when_minimized(gSavedSettings, "MuteWhenMinimized");
+ bool mute_audio = mute_audio_setting();
- if (!gViewerWindow->getActive() && gSavedSettings.getBOOL("MuteWhenMinimized"))
+ if (!gViewerWindow->getActive() && mute_when_minimized())
{
mute_audio = true;
}
@@ -419,7 +413,7 @@ void audio_update_volume(bool force_update)
{
// Sound Effects
- gAudiop->setMasterGain ( master_volume );
+ gAudiop->setMasterGain (master_volume());
const F32 AUDIO_LEVEL_DOPPLER = 1.f;
gAudiop->setDopplerFactor(AUDIO_LEVEL_DOPPLER);
@@ -435,6 +429,7 @@ void audio_update_volume(bool force_update)
gAudiop->setRolloffFactor(AUDIO_LEVEL_UNDERWATER_ROLLOFF);
}
+ bool progress_view_visible = gViewerWindow->getShowProgress();
gAudiop->setMuted(mute_audio || progress_view_visible);
//Play any deferred sounds when unmuted
@@ -448,13 +443,21 @@ void audio_update_volume(bool force_update)
audio_update_wind(true);
}
+ static LLCachedControl<bool> mute_sounds(gSavedSettings, "MuteSounds");
+ static LLCachedControl<bool> mute_ui(gSavedSettings, "MuteUI");
+ static LLCachedControl<bool> mute_ambient(gSavedSettings, "MuteAmbient");
+ static LLCachedControl<bool> mute_music(gSavedSettings, "MuteMusic");
+ static LLCachedControl<F32> al_sfx(gSavedSettings, "AudioLevelSFX");
+ static LLCachedControl<F32> al_ui(gSavedSettings, "AudioLevelUI");
+ static LLCachedControl<F32> al_ambient(gSavedSettings, "AudioLevelAmbient");
+ static LLCachedControl<F32> al_music(gSavedSettings, "AudioLevelMusic");
// handle secondary gains
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX,
- gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX"));
+ mute_sounds() ? 0.f : al_sfx());
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_UI,
- gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"));
+ mute_ui() ? 0.f : al_ui());
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT,
- gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient"));
+ mute_ambient() ? 0.f : al_ambient());
// Streaming Music
@@ -464,31 +467,29 @@ void audio_update_volume(bool force_update)
LLViewerAudio::getInstance()->setForcedTeleportFade(false);
}
- F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
- bool music_muted = gSavedSettings.getBOOL("MuteMusic");
F32 fade_volume = LLViewerAudio::getInstance()->getFadeVolume();
- music_volume = mute_volume * master_volume * music_volume * fade_volume;
- gAudiop->setInternetStreamGain (music_muted ? 0.f : music_volume);
+ F32 music_volume = mute_volume * master_volume * al_music() * fade_volume;
+ gAudiop->setInternetStreamGain (mute_music() ? 0.f : music_volume);
}
// Streaming Media
- F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
- bool media_muted = gSavedSettings.getBOOL("MuteMedia");
- media_volume = mute_volume * master_volume * media_volume;
- LLViewerMedia::getInstance()->setVolume( media_muted ? 0.0f : media_volume );
+ static LLCachedControl<bool> media_muted(gSavedSettings, "MuteMedia");
+ static LLCachedControl<F32> media_volume(gSavedSettings, "AudioLevelMedia");
+ LLViewerMedia::getInstance()->setVolume( media_muted() ? 0.0f : (mute_volume * master_volume() * media_volume()));
// Voice, this is parametric singleton, it gets initialized when ready
if (LLVoiceClient::instanceExists())
{
- F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
- voice_volume = mute_volume * master_volume * voice_volume;
- bool voice_mute = gSavedSettings.getBOOL("MuteVoice");
+ static LLCachedControl<bool> voice_mute(gSavedSettings, "MuteVoice");
+ static LLCachedControl<F32> voice_volume_setting(gSavedSettings, "AudioLevelVoice");
+ static LLCachedControl<F32> voice_mic_setting(gSavedSettings, "AudioLevelMic");
+ F32 voice_volume = mute_volume * master_volume() * voice_volume_setting();
LLVoiceClient *voice_inst = LLVoiceClient::getInstance();
- voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume);
- voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
+ voice_inst->setVoiceVolume(voice_mute() ? 0.f : voice_volume);
+ voice_inst->setMicGain(voice_mute() ? 0.f : voice_mic_setting());
- if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
+ if (!gViewerWindow->getActive() && mute_when_minimized())
{
voice_inst->setMuteMic(true);
}
diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp
index 2ca2c5c07d..a9aa63e68f 100644
--- a/indra/newview/llviewerchat.cpp
+++ b/indra/newview/llviewerchat.cpp
@@ -200,7 +200,7 @@ LLFontGL* LLViewerChat::getChatFont()
break;
default:
case 1:
- fontp = LLFontGL::getFontSansSerif();
+ fontp = LLFontGL::getFontSansSerifMedium();
break;
case 2:
fontp = LLFontGL::getFontSansSerifBig();
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 1c6a7a3e79..6d42cf2347 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -814,6 +814,7 @@ void setting_setup_signal_listener(LLControlGroup& group, const std::string& set
void settings_setup_listeners()
{
+ LL_PROFILE_ZONE_SCOPED;
setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged);
setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index e8516ab5a7..1b690fda9b 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -217,9 +217,10 @@ void display_update_camera()
{
final_far *= 0.5f;
}
- else if (LLViewerTexture::sDesiredDiscardBias > 2.f)
+ // When system memory is critically low or recovering, shrink draw distance.
+ else if (const F32 mem_factor = LLMemory::getSystemMemoryBudgetFactor(); mem_factor > 1.f)
{
- final_far = llmax(32.f, final_far / (LLViewerTexture::sDesiredDiscardBias - 1.f));
+ final_far = llmax(32.f, final_far / mem_factor);
}
LLViewerCamera::getInstance()->setFar(final_far);
LLVOAvatar::sRenderDistance = llclamp(final_far, 16.f, 256.f);
@@ -280,6 +281,12 @@ static void update_tp_display(bool minimized)
F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
+
+ // Reuse the minimized-window path to suppress the teleport progress screen.
+ if (gSavedSettings.getBOOL("DisableTeleportScreens"))
+ {
+ minimized = true;
+ }
if (gAgent.getTeleportState() != LLAgent::TELEPORT_START && teleport_percent > 100.f)
{
// Give up. Don't keep the UI locked forever.
@@ -316,6 +323,24 @@ static void update_tp_display(bool minimized)
{
// Transition to REQUESTED. Viewer has sent some kind
// of TeleportRequest to the source simulator
+
+ // NaCl: Right-click + scroll wheel zoom in mouselook (ported from Firestorm).
+ // Reset the mouselook zoom state on teleport so we don't get stuck at
+ // the zoomed FOV after arriving at the destination.
+ if (gAgentCamera.cameraMouselook())
+ {
+ LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues");
+ bool wasZoomed = (mlFovValues.mV[VZ] > 0.0f);
+ mlFovValues.mV[VZ] = 0.0f; // clear "currently zoomed" flag
+ gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues);
+ if (wasZoomed)
+ {
+ // Restore the normal (pre-zoom) FOV
+ gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VX]);
+ }
+ }
+ // NaCl End
+
gTeleportDisplayTimer.reset();
const std::string& msg = LLAgent::sTeleportProgressMessages["requesting"];
LL_INFOS("Teleport") << "A teleport request has been sent, setting state to TELEPORT_REQUESTED" << LL_ENDL;
@@ -576,9 +601,9 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
LLImageGL::updateStats(gFrameTimeSeconds);
static LLCachedControl<S32> avatar_name_tag_mode(gSavedSettings, "AvatarNameTagMode", 1);
- static LLCachedControl<bool> name_tag_show_group_titles(gSavedSettings, "NameTagShowGroupTitles", true);
+ static LLCachedControl<S32> name_tag_show_group_titles(gSavedSettings, "GroupTitlesTagMode", 2 /*all group tags*/);
LLVOAvatar::sRenderName = avatar_name_tag_mode;
- LLVOAvatar::sRenderGroupTitles = name_tag_show_group_titles && avatar_name_tag_mode > 0;
+ LLVOAvatar::sRenderGroupTitles = avatar_name_tag_mode > 0 ? name_tag_show_group_titles : 0;
gPipeline.mBackfaceCull = true;
gFrameCount++;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index fca15d2e79..2a2542ff57 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -44,7 +44,6 @@
#include "llfloateravatarrendersettings.h"
#include "llfloateravatartextures.h"
#include "llfloaterbanduration.h"
-#include "llfloaterbigpreview.h"
#include "llfloaterbeacons.h"
#include "llfloaterbuildoptions.h"
#include "llfloaterbulkpermission.h"
@@ -86,6 +85,7 @@
#include "llfloatergroups.h"
#include "llfloaterhelpbrowser.h"
#include "llfloaterhoverheight.h"
+#include "llquickprefs.h" // Quick Preferences floater (Firestorm port)
#include "mpfloatertuning.h"
#include "llfloaterhowto.h"
#include "llfloaterhud.h"
@@ -121,7 +121,6 @@
#include "llfloaterpay.h"
#include "llfloaterperformance.h"
#include "llfloaterperms.h"
-#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
#include "llfloaterpreferencesgraphicsadvanced.h"
#include "llfloaterpreferenceviewadvanced.h"
@@ -144,7 +143,6 @@
#include "llfloatersidepanelcontainer.h"
#include "llfloaterslapptest.h"
#include "llfloatersnapshot.h"
-#include "llfloatersounddevices.h"
#include "llfloaterspellchecksettings.h"
#include "llfloatertelehub.h"
#include "llfloatertestinspectors.h"
@@ -155,7 +153,6 @@
#include "llfloatertoybox.h"
#include "llfloatertranslationsettings.h"
#include "llfloateruipreview.h"
-#include "llfloatervoiceeffect.h"
#include "llfloaterwebcontent.h"
#include "llfloatervoicevolume.h"
#include "llfloaterwhitelistentry.h"
@@ -372,7 +369,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>);
LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>);
- LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
@@ -398,6 +394,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>);
+ LLFloaterReg::add("quick_prefs", "floater_quick_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterQuickPrefs>); // Firestorm port
LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
LLFloaterReg::add("mpv_performance", "floater_mp_performance.xml", (LLFloaterBuildFunc)&
@@ -505,7 +502,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
LLFloaterReg::add("settings_color", "floater_settings_color.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsColor>);
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
- LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
@@ -518,8 +514,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSLappTest>);
- LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
-
LLFloaterUIPreviewUtil::registerFloater();
LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
@@ -528,8 +522,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload");
LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
- LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
-
LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
LLFloaterReg::add("window_size", "floater_window_size.xml", &LLFloaterReg::build<LLFloaterWindowSize>);
diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp
index fd894a5997..f3a0f026b8 100644
--- a/indra/newview/llviewergenericmessage.cpp
+++ b/indra/newview/llviewergenericmessage.cpp
@@ -73,6 +73,7 @@ void send_generic_message(const std::string& method,
void process_generic_message(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID agent_id;
msg->getUUID("AgentData", "AgentID", agent_id);
if (agent_id != gAgent.getID())
@@ -95,6 +96,7 @@ void process_generic_message(LLMessageSystem* msg, void**)
void process_generic_streaming_message(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLGenericStreamingMessage data;
data.unpack(msg);
switch (data.mMethod)
@@ -110,6 +112,7 @@ void process_generic_streaming_message(LLMessageSystem* msg, void**)
void process_large_generic_message(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID agent_id;
msg->getUUID("AgentData", "AgentID", agent_id);
if (agent_id != gAgent.getID())
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index e5cf1bcb69..7942f7c4ea 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -171,7 +171,6 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
//-----------------------------------------------------------------------------
bool LLViewerJointAttachment::addObject(LLViewerObject* object)
{
-// object->extractAttachmentItemID();
// Same object reattached
if (isObjectAttached(object))
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 330aa7c368..92bfc9e0f5 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -663,9 +663,10 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE);
llassert(!gCubeSnapshot);
+ static LLCachedControl<bool> use_read_thread(gSavedSettings, "PluginUseReadThread", true);
// Enable/disable the plugin read thread
- LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
+ LLPluginProcessParent::setUseReadThread(use_read_thread());
// SL-16418 We can't call LLViewerMediaImpl->update() if we are in the state of shutting down.
if(LLApp::isExiting())
@@ -1757,6 +1758,7 @@ void LLViewerMediaImpl::createMediaSource()
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::destroyMediaSource()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;
mNeedsNewTexture = true;
// Tell the viewer media texture it's no longer active
@@ -1825,7 +1827,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
if (plugin_basename == "media_plugin_cef")
{
launcher_name = "/compat/linux/usr/libexec/megapahit/SLPlugin";
- plugin_name = "/compat/linux/usr/lib/x86_64-linux-gnu/libmedia_plugin_cef.so";
+ plugin_name = "/compat/linux/usr/lib/x86_64-linux-gnu/megapahit/libmedia_plugin_cef.so";
}
#endif
@@ -1872,7 +1874,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser);
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
bool media_plugin_pipewire_volume_catcher = gSavedSettings.getBOOL("MediaPluginPipeWireVolumeCatcher");
media_source->enablePipeWireVolumeCatcher( media_plugin_pipewire_volume_catcher );
#endif
@@ -1890,8 +1892,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
std::string plugin_dir = gDirUtilp->getLLPluginDir();
if (plugin_basename == "media_plugin_cef")
{
- plugin_dir = "/compat/linux/usr/lib/x86_64-linux-gnu";
- plugin_name = "/usr/lib/x86_64-linux-gnu/libmedia_plugin_cef.so";
+ plugin_dir = "/compat/linux/usr/lib/x86_64-linux-gnu/megapahit";
+ plugin_name = "/usr/lib/x86_64-linux-gnu/megapahit/libmedia_plugin_cef.so";
}
#else
const std::string plugin_dir = gDirUtilp->getLLPluginDir();
@@ -2206,16 +2208,19 @@ void LLViewerMediaImpl::updateVolume()
if (mProximityCamera > 0)
{
- if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax"))
+ static LLCachedControl<F32> media_rolloff_min(gSavedSettings, "MediaRollOffMin");
+ static LLCachedControl<F32> media_rolloff_max(gSavedSettings, "MediaRollOffMax");
+ static LLCachedControl<F32> media_rolloff_rate(gSavedSettings, "MediaRollOffRate");
+ if (mProximityCamera > media_rolloff_max())
{
volume = 0;
}
- else if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMin"))
+ else if (mProximityCamera > media_rolloff_min())
{
// attenuated_volume = 1 / (roll_off_rate * (d - min))^2
// the +1 is there so that for distance 0 the volume stays the same
- F64 adjusted_distance = mProximityCamera - gSavedSettings.getF32("MediaRollOffMin");
- F64 attenuation = 1.0 + (gSavedSettings.getF32("MediaRollOffRate") * adjusted_distance);
+ F64 adjusted_distance = mProximityCamera - media_rolloff_min();
+ F64 attenuation = 1.0 + (media_rolloff_rate() * adjusted_distance);
attenuation = 1.0 / (attenuation * attenuation);
// the attenuation multiplier should never be more than one since that would increase volume
volume = volume * (F32)llmin(1.0, attenuation);
@@ -2641,19 +2646,30 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateInternal()
+void LLViewerMediaImpl::navigateInternal(bool should_log)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;
// Helpful to have media urls in log file. Shouldn't be spammy.
{
// Do not log the query parts
LLURI u(mMediaURL);
std::string sanitized_url = (u.query().empty() ? mMediaURL : u.scheme() + "://" + u.authority() + u.path());
- LL_INFOS() << "media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mMimeType << LL_ENDL;
+ if (should_log)
+ {
+ LL_INFOS("Media") << "media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mMimeType << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Media") << "media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mMimeType << LL_ENDL;
+ }
}
if(mNavigateSuspended)
{
- LL_WARNS() << "Deferring navigate." << LL_ENDL;
+ if (should_log || !mNavigateSuspendedDeferred)
+ {
+ LL_WARNS() << "Deferring navigate." << LL_ENDL;
+ }
mNavigateSuspendedDeferred = true;
return;
}
@@ -2661,7 +2677,13 @@ void LLViewerMediaImpl::navigateInternal()
if (!mMimeProbe.expired())
{
- LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;
+ if (should_log)
+ {
+ // media periodically suspends and unsuspends (should_log == false),
+ // unsuspend calls this function, it's epxected that sometimes
+ // unsuspend will be attempted while a probe is in flight.
+ LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;
+ }
return;
}
@@ -2722,10 +2744,14 @@ void LLViewerMediaImpl::navigateInternal()
{
loadURI();
}
- else
+ else if (should_log)
{
LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
}
+ else
+ {
+ LL_DEBUGS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
+ }
}
void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url)
@@ -3991,7 +4017,7 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
if(mNavigateSuspendedDeferred)
{
mNavigateSuspendedDeferred = false;
- navigateInternal();
+ navigateInternal(false /*suspend happens periodically, don't log*/);
}
}
}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 1fc5bbc9e0..c840fbb72c 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -251,7 +251,7 @@ public:
void navigateHome();
void unload();
void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false);
- void navigateInternal();
+ void navigateInternal(bool should_log = true);
void navigateStop();
bool handleKeyHere(KEY key, MASK mask);
bool handleKeyUpHere(KEY key, MASK mask);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 5ea64a7824..6dc87e9aa3 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -131,7 +131,6 @@
#include "llviewerstatsrecorder.h"
#include "llvlcomposition.h"
#include "llvoavatarself.h"
-#include "llvoicevivox.h"
#include "llworld.h"
#include "llworldmap.h"
#include "pipeline.h"
@@ -144,7 +143,7 @@
#include "llwindow.h"
#include "llpathfindingmanager.h"
#include "llstartup.h"
-#include "boost/unordered_map.hpp"
+#include <unordered_map>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/json.hpp>
@@ -158,7 +157,7 @@ using namespace LLAvatarAppearanceDefines;
typedef LLPointer<LLViewerObject> LLViewerObjectPtr;
-static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
+static std::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
LLVOAvatar* find_avatar_from_object(LLViewerObject* object);
LLVOAvatar* find_avatar_from_object(const LLUUID& object_id);
@@ -418,7 +417,23 @@ static LLSLMMenuUpdater* gSLMMenuUpdater = NULL;
LLSLMMenuUpdater::LLSLMMenuUpdater()
{
- mMarketplaceListingsItem = gMenuHolder->getChild<LLView>("MarketplaceListings")->getHandle();
+ LLView* me_menu = gMenuHolder->findChild<LLView>("Me");
+ if (!me_menu)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find 'Me' menu in 'menu_viewer'" << LL_ENDL;
+ return;
+ }
+
+ LLView* marketplace_listings = me_menu->findChild<LLView>("MarketplaceListings");
+ if (!marketplace_listings)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find 'MarketplaceListings' in 'Me' menu" << LL_ENDL;
+ return;
+ }
+
+ mMarketplaceListingsItem = marketplace_listings->getHandle();
}
void LLSLMMenuUpdater::setMerchantMenu()
{
@@ -430,7 +445,7 @@ void LLSLMMenuUpdater::setMerchantMenu()
LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
gToolBarView->enableCommand(command->id(), true);
- const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID();
if (marketplacelistings_id.isNull())
{
U32 mkt_status = LLMarketplaceData::instance().getSLMStatus();
@@ -478,6 +493,8 @@ void check_merchant_status(bool force)
void init_menus()
{
+ LL_PROFILE_ZONE_SCOPED;
+
// Initialize actions
initialize_menus();
@@ -554,7 +571,29 @@ void init_menus()
color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
}
- LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
+ LLView* menu_stack = gViewerWindow->getMainView()->findChildView("menu_stack");
+ if (!menu_stack)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find menu_stack in main_view" << LL_ENDL;
+ return;
+ }
+
+ LLView* status_bar_container = menu_stack->findChildView("status_bar_container");
+ if (!status_bar_container)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL;
+ return;
+ }
+
+ LLView* menu_bar_holder = status_bar_container->findChildView("menu_bar_holder");
+ if (!menu_bar_holder)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL;
+ return;
+ }
gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT));
@@ -568,8 +607,33 @@ void init_menus()
// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
- gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str);
- gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str);
+
+ LLView* main_upload_menu = gMenuHolder->findChild<LLView>("Upload");
+ if (!main_upload_menu)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find 'Upload' menu in 'menu_viewer'" << LL_ENDL;
+ return;
+ }
+
+ LLView* upload_sound = main_upload_menu->findChild<LLView>("Upload Sound");
+ if (!upload_sound)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find 'Upload Sound' menu item in 'Upload' menu" << LL_ENDL;
+ return;
+ }
+ upload_sound->setLabelArg("[COST]", sound_upload_cost_str);
+
+ LLView* upload_anim = main_upload_menu->findChild<LLView>("Upload Animation");
+ if (!upload_anim)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Can't find 'Upload Animation' menu item in 'Upload' menu" << LL_ENDL;
+ return;
+ }
+ upload_anim->setLabelArg("[COST]", animation_upload_cost_str);
+
gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", true);
gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", true);
@@ -577,13 +641,6 @@ void init_menus()
gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true);
gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true);
- // Don't display the Memory console menu if the feature is turned off
- LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", true);
- if (memoryMenu)
- {
- memoryMenu->setVisible(false);
- }
-
gMenuBarView->createJumpKeys();
// Let land based option enable when parcel changes
@@ -596,7 +653,7 @@ void init_menus()
LLRect menuBarRect = gLoginMenuBarView->getRect();
menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight());
gLoginMenuBarView->setRect(menuBarRect);
- gLoginMenuBarView->setBackgroundColor( color );
+ gLoginMenuBarView->setBackgroundColor(LLColor4::black);
menu_bar_holder->addChild(gLoginMenuBarView);
// tooltips are on top of EVERYTHING, including menus
@@ -2971,11 +3028,45 @@ void handle_object_show_original()
show_item_original(object->getAttachmentItemID());
}
+void handle_object_set_favorite(const LLSD& userdata)
+{
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object)
+ {
+ return;
+ }
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ while (parent)
+ {
+ if(parent->isAvatar())
+ {
+ break;
+ }
+ object = parent;
+ parent = (LLViewerObject*)parent->getParent();
+ }
+ if (!object || object->isAvatar())
+ {
+ return;
+ }
+
+ LLUUID item_id = gInventory.getLinkedItemID(object->getAttachmentItemID());
+
+ std::string action = userdata.asString();
+ if (action == "Add")
+ {
+ set_favorite(item_id, true);
+ }
+ if (action == "Remove")
+ {
+ set_favorite(item_id, false);
+ }
+}
static void init_default_item_label(LLUICtrl* ctrl)
{
const std::string& item_name = ctrl->getName();
- boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+ std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
if (it == sDefaultItemLabels.end())
{
// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
@@ -2991,7 +3082,7 @@ static void init_default_item_label(LLUICtrl* ctrl)
static LLStringExplicit get_default_item_label(const std::string& item_name)
{
LLStringExplicit res("");
- boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+ std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
if (it != sDefaultItemLabels.end())
{
res = it->second;
@@ -3027,6 +3118,41 @@ bool enable_object_touch(LLUICtrl* ctrl)
return new_value;
};
+bool enable_object_favorite(const LLSD& userdata)
+{
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object)
+ {
+ return false;
+ }
+ LLViewerObject* parent = (LLViewerObject*)object->getParent();
+ while (parent)
+ {
+ if (parent->isAvatar())
+ {
+ break;
+ }
+ object = parent;
+ parent = (LLViewerObject*)parent->getParent();
+ }
+ if (!object || object->isAvatar())
+ {
+ return false;
+ }
+
+ std::string action = userdata.asString();
+ LLUUID item_id = gInventory.getLinkedItemID(object->getAttachmentItemID());
+ if (action == "Add")
+ {
+ return !get_is_favorite(item_id);
+ }
+ if (action == "Remove")
+ {
+ return get_is_favorite(item_id);
+ }
+ return false;
+}
+
//void label_touch(std::string& label, void*)
//{
// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
@@ -3938,6 +4064,44 @@ void handle_avatar_eject(const LLSD& avatar_id)
}
}
+void handle_avatar_estate_kick(const LLSD& avatar_id)
+{
+ LLUUID id = avatar_id.asUUID();
+ if (id.isNull())
+ {
+ LLVOAvatar* avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ if (avatar) id = avatar->getID();
+ }
+ if (id.notNull())
+ {
+ LLAvatarActions::estateKickAvatar(id);
+ }
+}
+
+void handle_avatar_estate_ban(const LLSD& avatar_id)
+{
+ LLUUID id = avatar_id.asUUID();
+ if (id.isNull())
+ {
+ LLVOAvatar* avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ if (avatar) id = avatar->getID();
+ }
+ if (id.notNull())
+ {
+ LLAvatarActions::estateBanAvatar(id);
+ }
+}
+
+bool enable_estate_eject_ban(const LLSD& avatar_id)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return false;
+ if (gAgent.isGodlike()) return true;
+ return region->getOwner() == gAgent.getID() || region->isEstateManager();
+}
+
bool my_profile_visible()
{
LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID);
@@ -4651,12 +4815,37 @@ class LLViewMouselook : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+ // When OTS is enabled M toggles OTS mode (shoulder cam).
+ // When disabled M toggles normal first-person mouselook.
+ if (gSavedSettings.getBOOL("OTSEnabled"))
+ {
+ if (!gAgentCamera.cameraOTS())
+ {
+ gAgentCamera.changeCameraToOTS();
+ }
+ else
+ {
+ gAgentCamera.changeCameraFromOTS();
+ }
+ return true;
+ }
+
if (!gAgentCamera.cameraMouselook())
{
gAgentCamera.changeCameraToMouselook();
}
else
{
+ // NaCl: restore FOV on mouselook exit
+ LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues");
+ F32 cameraAngle = gSavedSettings.getF32("CameraAngle");
+ if (mlFovValues.mV[VZ] > 0.0f)
+ {
+ mlFovValues.mV[VY] = cameraAngle;
+ mlFovValues.mV[VZ] = 0.0f;
+ gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues);
+ gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VX]);
+ }
gAgentCamera.changeCameraToDefault();
}
return true;
@@ -7027,6 +7216,13 @@ void handle_hover_height()
LLFloaterReg::showInstance("edit_hover_height");
}
+// Firestorm port: Quick Preferences floater (hover height, bandwidth)
+void handle_quick_prefs()
+{
+ LLFloaterReg::toggleInstance("quick_prefs");
+}
+// End Firestorm port
+
void handle_edit_physics()
{
LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics"));
@@ -9616,17 +9812,6 @@ class LLWorldEnableEnvPreset : public view_listener_t
}
};
-
-/// Post-Process callbacks
-class LLWorldPostProcess : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::showInstance("env_post_process");
- return true;
- }
-};
-
class LLWorldCheckBanLines : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -9809,6 +9994,8 @@ void initialize_spellcheck_menu()
void initialize_menus()
{
+ LL_PROFILE_ZONE_SCOPED;
+
// A parameterized event handler used as ctrl-8/9/0 zoom controls below.
class LLZoomer : public view_listener_t
{
@@ -9865,6 +10052,7 @@ void initialize_menus()
commit.add("EditShape", boost::bind(&handle_edit_shape));
commit.add("HoverHeight", boost::bind(&handle_hover_height));
commit.add("EditPhysics", boost::bind(&handle_edit_physics));
+ commit.add("QuickPrefs", boost::bind(&handle_quick_prefs)); // Firestorm port
// View menu
view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
@@ -9918,7 +10106,6 @@ void initialize_menus()
view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings");
view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset");
view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset");
- view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines");
view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines");
@@ -10208,6 +10395,9 @@ void initialize_menus()
view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
+ commit.add("Avatar.EstateKick", boost::bind(&handle_avatar_estate_kick, _2));
+ commit.add("Avatar.EstateBan", boost::bind(&handle_avatar_estate_ban, _2));
+ enable.add("Avatar.EnableEstateEjectBan", boost::bind(&enable_estate_eject_ban, _2));
commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
@@ -10234,6 +10424,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
commit.add("Object.Touch", boost::bind(&handle_object_touch));
commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original));
+ commit.add("Object.SetFavorite", boost::bind(&handle_object_set_favorite, _2));
commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
commit.add("Object.Delete", boost::bind(&handle_object_delete));
view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
@@ -10262,6 +10453,7 @@ void initialize_menus()
enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));
enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
+ enable.add("Object.EnableFavorites", boost::bind(&enable_object_favorite, _2));
enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
enable.add("Object.EnableWear", boost::bind(&object_is_wearable));
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 494a11d94f..26d40436e9 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -40,6 +40,7 @@
#include "llinventorydefines.h"
#include "lllslconstants.h"
#include "llmaterialtable.h"
+#include "llmemory.h"
#include "llregionhandle.h"
#include "llsd.h"
#include "llsdserialize.h"
@@ -3391,11 +3392,12 @@ void send_agent_update(bool force_send, bool send_reliable)
static F32 last_draw_disatance_step = 1024;
F32 memory_limited_draw_distance = gAgentCamera.mDrawDistance;
-
- if (LLViewerTexture::isSystemMemoryCritical())
+ const F32 mem_factor = LLMemory::getSystemMemoryBudgetFactor();
+ if (mem_factor > 1.f)
{
- // If we are low on memory, reduce requested draw distance
- memory_limited_draw_distance = llmax(gAgentCamera.mDrawDistance / LLViewerTexture::getSystemMemoryBudgetFactor(), gAgentCamera.mDrawDistance / 2.f);
+ // We are critically low on memory or recovering,
+ // limit requested draw distance
+ memory_limited_draw_distance = llmax(gAgentCamera.mDrawDistance / mem_factor, gAgentCamera.mDrawDistance / 2.f);
}
if (tp_state == LLAgent::TELEPORT_ARRIVING || LLStartUp::getStartupState() < STATE_MISC)
@@ -3574,6 +3576,7 @@ extern U32Bits gObjectData;
void process_object_update(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -3595,6 +3598,7 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data)
void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -3616,6 +3620,7 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Update the data counters
if (mesgsys->getReceiveCompressedSize())
{
@@ -3633,6 +3638,7 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (mesgsys->getReceiveCompressedSize())
{
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
@@ -3992,6 +3998,7 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID animation_id;
LLUUID uuid;
S32 anim_sequence_id;
@@ -4103,6 +4110,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID animation_id;
LLUUID uuid;
S32 anim_sequence_id;
@@ -4168,6 +4176,7 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID uuid;
mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid);
@@ -5701,6 +5710,7 @@ void process_script_experience_details(const LLSD& experience_details, LLSD args
void process_script_question(LLMessageSystem *msg, void **user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// *TODO: Translate owner name -> [FIRST] [LAST]
LLHost sender = msg->getSender();
@@ -5771,28 +5781,40 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
args["NAME"] = clean_owner_name;
S32 known_questions = 0;
bool has_not_only_debit = questions ^ SCRIPT_PERMISSIONS[SCRIPT_PERMISSION_DEBIT].permbit;
+ bool caution_enabled = gSavedSettings.getBOOL("PermissionsCautionEnabled");
// check the received permission flags against each permission
+ std::string warning_msg;
for (const script_perm_t& script_perm : SCRIPT_PERMISSIONS)
{
if (questions & script_perm.permbit)
{
- count++;
known_questions |= script_perm.permbit;
// check whether permission question should cause special caution dialog
caution |= (script_perm.caution);
- if (("ScriptTakeMoney" == script_perm.question) && has_not_only_debit)
+ // Cautions go into top part of the dialog, questions go into the footer
+ if (caution_enabled && script_perm.caution)
+ {
+ warning_msg += "\n" + LLTrans::getString(script_perm.question + "Caution") + "\n";
continue;
+ }
if (LLTrans::getString(script_perm.question).empty())
{
continue;
}
- script_question += " " + LLTrans::getString(script_perm.question) + "\n";
+ count++;
+ script_question += "\n " + LLTrans::getString(script_perm.question);
}
}
+ if (!warning_msg.empty())
+ {
+ LLStringUtil::format(warning_msg, args);
+ args["WARNINGS"] = warning_msg;
+ }
+
args["QUESTIONS"] = script_question;
if (known_questions != questions)
@@ -5817,12 +5839,12 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
// check whether cautions are even enabled or not
const char* notification = "ScriptQuestion";
- if(caution && gSavedSettings.getBOOL("PermissionsCautionEnabled"))
+ if(caution && caution_enabled)
{
- args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : "";
+ args["FOOTERTEXT"] = (count > 0) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n" + script_question : "";
notification = "ScriptQuestionCaution";
}
- else if(experienceid.notNull())
+ else if (experienceid.notNull())
{
payload["experience"]=experienceid;
LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
@@ -6108,11 +6130,18 @@ void process_teleport_local(LLMessageSystem *msg,void**)
}
gAgent.setPositionAgent(pos);
- gAgentCamera.slamLookAt(look_at);
+
+ bool keep_camera_local_tp = gSavedSettings.getBOOL("KeepCameraOnLocalTeleport");
+
+ if (!keep_camera_local_tp)
+ {
+ gAgentCamera.slamLookAt(look_at);
+ }
if ( !(gAgent.getTeleportKeepsLookAt() && LLViewerJoystick::getInstance()->getOverrideCamera()) )
{
- gAgentCamera.resetView(true, true);
+ // resetView still runs (cleanup); the false args just leave the camera alone.
+ gAgentCamera.resetView(!keep_camera_local_tp, !keep_camera_local_tp);
}
// send camera update to new region
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 6cb3aee20c..8ec2a6d661 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -63,7 +63,7 @@ const std::string GRID_LOGIN_IDENTIFIER_TYPES = "login_identifier_types";
const std::string GRID_SLURL_BASE = "slurl_base";
const std::string GRID_APP_SLURL_BASE = "app_slurl_base";
-const std::string DEFAULT_LOGIN_PAGE = "https://viewer-splash.secondlife.com/";
+const std::string DEFAULT_LOGIN_PAGE = "https://viewer-splash-v2.secondlife.com/";
const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
@@ -125,7 +125,7 @@ void LLGridManager::initialize(const std::string& grid_file)
MAIN_GRID_WEB_PROFILE_URL,
"Agni");
addSystemGrid(LLTrans::getString("AditiGridLabel"),
- "util.aditi.lindenlab.com",
+ BETAGRID,
"https://login.aditi.lindenlab.com/cgi-bin/login.cgi",
"https://secondlife.aditi.lindenlab.com/helpers/",
DEFAULT_LOGIN_PAGE,
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 2ed663e038..0937425a18 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -30,6 +30,7 @@
// @TODO this really should be private, but is used in llslurl
#define MAINGRID "util.agni.lindenlab.com"
+#define BETAGRID "util.aditi.lindenlab.com"
/// Exception thrown when a grid is not valid
class LLInvalidGridName
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f7b1fb004f..7f51ad1065 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -130,6 +130,7 @@ F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motio
F64Seconds LLViewerObject::sMaxRegionCrossingInterpolationTime(1.0);// For motion interpolation: don't interpolate over this time on region crossing
std::map<std::string, U32> LLViewerObject::sObjectDataMap;
+std::unordered_map<LLUUID, std::vector<LLViewerObject*>> LLViewerObject::sPendingUpdatesByOwner;
// The maximum size of an object extra parameters binary (packed) block
#define MAX_OBJECT_PARAMS_SIZE 1024
@@ -311,6 +312,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mLastUpdateType(OUT_UNKNOWN),
mLastUpdateCached(false),
mLocked(false),
+ mExtraParameterList(LLNetworkData::PARAMS_MAX >> 4),
mCachedMuteListUpdateTime(0),
mCachedOwnerInMuteList(false),
mRiggedAttachedWarned(false)
@@ -368,15 +370,6 @@ LLViewerObject::~LLViewerObject()
}
// Delete memory associated with extra parameters.
- std::unordered_map<U16, ExtraParameter*>::iterator iter;
- for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
- {
- if(iter->second != NULL)
- {
- delete iter->second->data;
- delete iter->second;
- }
- }
mExtraParameterList.clear();
for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
@@ -530,6 +523,8 @@ void LLViewerObject::markDead()
mReflectionProbe = nullptr;
}
+ removeObjectFromPendingUpdate(this);
+
sNumZombieObjects++;
}
}
@@ -1509,10 +1504,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
unpackParticleSource(block_num, owner_id);
// Mark all extra parameters not used
- std::unordered_map<U16, ExtraParameter*>::iterator iter;
- for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ for (auto& entry : mExtraParameterList)
{
- iter->second->in_use = false;
+ if (entry.in_use) *entry.in_use = false;
}
// Unpack extra parameters
@@ -1536,7 +1530,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16 param_type;
S32 param_size;
dp.unpackU16(param_type, "param_type");
- dp.unpackBinaryData(param_block, param_size, "param_data");
+ dp.unpackBinaryData(param_block, MAX_OBJECT_PARAMS_SIZE, param_size, "param_data");
//LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL;
LLDataPackerBinaryBuffer dp2(param_block, param_size);
unpackParameterEntry(param_type, &dp2);
@@ -1544,12 +1538,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
delete[] buffer;
}
- for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ for (size_t i = 0; i < mExtraParameterList.size(); ++i)
{
- if (!iter->second->in_use)
+ auto& entry = mExtraParameterList[i];
+ if (entry.in_use && !*entry.in_use)
{
// Send an update message in case it was formerly in use
- parameterChanged(iter->first, iter->second->data, false, false);
+ parameterChanged(((U16)i + 1) << 4, entry.data, false, false);
}
}
@@ -1792,7 +1787,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
dp->unpackU32(size, "ScratchPadSize");
delete [] mData;
mData = new U8[size];
- dp->unpackBinaryData((U8 *)mData, sp_size, "PartData");
+ dp->unpackBinaryData((U8 *)mData, size, sp_size, "PartData");
}
else
{
@@ -1851,10 +1846,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
// Mark all extra parameters not used
- std::unordered_map<U16, ExtraParameter*>::iterator iter;
- for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ for (auto& entry : mExtraParameterList)
{
- iter->second->in_use = false;
+ if (entry.in_use) *entry.in_use = false;
}
// Unpack extra params
@@ -1866,18 +1860,19 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16 param_type;
S32 param_size;
dp->unpackU16(param_type, "param_type");
- dp->unpackBinaryData(param_block, param_size, "param_data");
+ dp->unpackBinaryData(param_block, MAX_OBJECT_PARAMS_SIZE, param_size, "param_data");
//LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL;
LLDataPackerBinaryBuffer dp2(param_block, param_size);
unpackParameterEntry(param_type, &dp2);
}
- for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ for (size_t i = 0; i < mExtraParameterList.size(); ++i)
{
- if (!iter->second->in_use)
+ auto& entry = mExtraParameterList[i];
+ if (entry.in_use && !*entry.in_use)
{
// Send an update message in case it was formerly in use
- parameterChanged(iter->first, iter->second->data, false, false);
+ parameterChanged(((U16)i + 1) << 4, entry.data, false, false);
}
}
@@ -3216,6 +3211,7 @@ S32 LLFilenameAndTask::sCount = 0;
// static
void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLUUID task_id;
msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
LLViewerObject* object = gObjectList.findObject(task_id);
@@ -4184,7 +4180,7 @@ void LLViewerObject::boostTexturePriority(bool boost_children /* = true */)
if (isSculpted() && !isMesh())
{
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = getSculptParams();
if (sculpt_params)
{
LLUUID sculpt_id = sculpt_params->getSculptTexture();
@@ -4656,9 +4652,10 @@ const LLQuaternion LLViewerObject::getRenderRotation() const
}
else
{
- if (!mDrawable->isRoot())
+ LLDrawable* parent = mDrawable->getParent();
+ if (!mDrawable->isRoot() && parent)
{
- ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix());
+ ret = getRotation() * LLQuaternion(parent->getWorldMatrix());
}
else
{
@@ -6495,7 +6492,7 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)
if (param)
{
param->data->unpack(*dp);
- param->in_use = true;
+ *param->in_use = true;
parameterChanged(param_type, param->data, true, false);
return true;
}
@@ -6507,108 +6504,79 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)
LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type)
{
- LLNetworkData* new_block = NULL;
+ LLNetworkData* new_block = nullptr;
+ bool* in_use = NULL;
switch (param_type)
{
case LLNetworkData::PARAMS_FLEXIBLE:
{
- new_block = new LLFlexibleObjectData();
+ mFlexibleObjectData = std::make_unique<LLFlexibleObjectData>();
+ new_block = mFlexibleObjectData.get();
+ in_use = &mFlexibleObjectDataInUse;
break;
}
case LLNetworkData::PARAMS_LIGHT:
{
- new_block = new LLLightParams();
+ mLightParams = std::make_unique<LLLightParams>();
+ new_block = mLightParams.get();
+ in_use = &mLightParamsInUse;
break;
}
case LLNetworkData::PARAMS_SCULPT:
{
- new_block = new LLSculptParams();
+ mSculptParams = std::make_unique<LLSculptParams>();
+ new_block = mSculptParams.get();
+ in_use = &mSculptParamsInUse;
break;
}
case LLNetworkData::PARAMS_LIGHT_IMAGE:
{
- new_block = new LLLightImageParams();
+ mLightImageParams = std::make_unique<LLLightImageParams>();
+ new_block = mLightImageParams.get();
+ in_use = &mLightImageParamsInUse;
break;
}
case LLNetworkData::PARAMS_EXTENDED_MESH:
{
- new_block = new LLExtendedMeshParams();
+ mExtendedMeshParams = std::make_unique<LLExtendedMeshParams>();
+ new_block = mExtendedMeshParams.get();
+ in_use = &mExtendedMeshParamsInUse;
break;
}
case LLNetworkData::PARAMS_RENDER_MATERIAL:
{
- new_block = new LLRenderMaterialParams();
+ mRenderMaterialParams = std::make_unique<LLRenderMaterialParams>();
+ new_block = mRenderMaterialParams.get();
+ in_use = &mRenderMaterialParamsInUse;
break;
}
case LLNetworkData::PARAMS_REFLECTION_PROBE:
{
- new_block = new LLReflectionProbeParams();
+ mReflectionProbeParams = std::make_unique<LLReflectionProbeParams>();
+ new_block = mReflectionProbeParams.get();
+ in_use = &mReflectionProbeParamsInUse;
break;
}
default:
{
- LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL;
+ LL_INFOS_ONCE() << "Unknown param type. (" << llformat("0x%2x", param_type) << ")" << LL_ENDL;
break;
}
};
+ ExtraParameter& entry = mExtraParameterList[U32(param_type >> 4) - 1];
if (new_block)
{
- ExtraParameter* new_entry = new ExtraParameter;
- new_entry->data = new_block;
- new_entry->in_use = false; // not in use yet
- llassert(mExtraParameterList[param_type] == nullptr); // leak -- redundantly allocated parameter entry
- mExtraParameterList[param_type] = new_entry;
- return new_entry;
- }
- return NULL;
-}
-
-LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VIEWER;
- std::unordered_map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type);
- if (itor != mExtraParameterList.end())
- {
- return itor->second;
- }
- return NULL;
-}
-
-LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type)
-{
- ExtraParameter* param = getExtraParameterEntry(param_type);
- if (!param)
- {
- param = createNewParameterEntry(param_type);
- }
- return param;
-}
-
-LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const
-{
- ExtraParameter* param = getExtraParameterEntry(param_type);
- if (param)
- {
- return param->data;
+ entry.in_use = in_use;
+ *entry.in_use = false; // not in use yet
+ entry.data = new_block;
+ return &entry;
}
else
{
- return NULL;
- }
-}
-
-bool LLViewerObject::getParameterEntryInUse(U16 param_type) const
-{
- ExtraParameter* param = getExtraParameterEntry(param_type);
- if (param)
- {
- return param->in_use;
- }
- else
- {
- return false;
+ entry.is_invalid = true;
}
+ return nullptr;
}
bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin)
@@ -6616,11 +6584,11 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_
ExtraParameter* param = getExtraParameterEntryCreate(param_type);
if (param)
{
- if (param->in_use && new_value == *(param->data))
+ if (*(param->in_use) && new_value == *(param->data))
{
return false;
}
- param->in_use = true;
+ *param->in_use = true;
param->data->copy(new_value);
parameterChanged(param_type, param->data, true, local_origin);
return true;
@@ -6636,22 +6604,28 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_
// Should always return true.
bool LLViewerObject::setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin)
{
- ExtraParameter* param = getExtraParameterEntryCreate(param_type);
- if (param && param->in_use != in_use)
+ if (param_type <= LLNetworkData::PARAMS_MAX)
{
- param->in_use = in_use;
- parameterChanged(param_type, param->data, in_use, local_origin);
- return true;
+ ExtraParameter* param = (in_use ? getExtraParameterEntryCreate(param_type) : &getExtraParameterEntry(param_type));
+ if (param && param->data && *param->in_use != in_use)
+ {
+ *param->in_use = in_use;
+ parameterChanged(param_type, param->data, in_use, local_origin);
+ return true;
+ }
}
return false;
}
void LLViewerObject::parameterChanged(U16 param_type, bool local_origin)
{
- ExtraParameter* param = getExtraParameterEntry(param_type);
- if (param)
+ if (param_type <= LLNetworkData::PARAMS_MAX)
{
- parameterChanged(param_type, param->data, param->in_use, local_origin);
+ const ExtraParameter& param = getExtraParameterEntry(param_type);
+ if (param.data)
+ {
+ parameterChanged(param_type, param.data, *param.in_use, local_origin);
+ }
}
}
@@ -6699,7 +6673,7 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, bool
{
if (param_type == LLNetworkData::PARAMS_RENDER_MATERIAL)
{
- const LLRenderMaterialParams* params = in_use ? (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL) : nullptr;
+ const LLRenderMaterialParams* params = in_use ? getRenderMaterialParams() : nullptr;
setRenderMaterialIDs(params, local_origin);
}
}
@@ -7470,9 +7444,10 @@ const std::string& LLViewerObject::getAttachmentItemName() const
LLVOAvatar* LLViewerObject::getAvatar() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
- if (getControlAvatar())
+ LLControlAvatar* ca = getControlAvatar();
+ if (ca)
{
- return getControlAvatar();
+ return ca;
}
if (isAttachment())
{
@@ -7491,7 +7466,7 @@ LLVOAvatar* LLViewerObject::getAvatar() const
bool LLViewerObject::hasRenderMaterialParams() const
{
- return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ return mRenderMaterialParamsInUse;
}
void LLViewerObject::setHasRenderMaterialParams(bool has_materials)
@@ -7513,7 +7488,7 @@ void LLViewerObject::setHasRenderMaterialParams(bool has_materials)
const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const
{
- LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ const LLRenderMaterialParams* param_block = getRenderMaterialParams();
if (param_block)
{
return param_block->getMaterial(te);
@@ -7554,7 +7529,7 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat
start_idx = llmax(start_idx, 0);
end_idx = llmin(end_idx, (S32) getNumTEs());
- LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ LLRenderMaterialParams* param_block = getRenderMaterialParams();
if (!param_block && id.notNull())
{ // block doesn't exist, but it will need to
param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data;
@@ -7782,6 +7757,61 @@ bool LLViewerObject::isReachable()
return false;
}
+void LLViewerObject::markObjectsForUpdate(const LLUUID& owner_id)
+{
+ sPendingUpdatesByOwner.erase(owner_id);
+ for (S32 i = 0; i < gObjectList.getNumObjects(); ++i)
+ {
+ LLViewerObject* obj = gObjectList.getObject(i);
+ if (!obj || obj->isDead() || obj->isAvatar() || obj->permYouOwner())
+ {
+ continue;
+ }
+ sPendingUpdatesByOwner[owner_id].push_back(obj);
+ }
+}
+
+void LLViewerObject::removeObjectFromPendingUpdate(LLViewerObject* obj)
+{
+ for (auto& [owner_id, objects] : sPendingUpdatesByOwner)
+ {
+ objects.erase(std::remove(objects.begin(), objects.end(), obj), objects.end());
+ }
+}
+
+bool LLViewerObject::isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj)
+{
+ if (!obj)
+ {
+ return false;
+ }
+ auto it = sPendingUpdatesByOwner.find(owner_id);
+ if (it != sPendingUpdatesByOwner.end())
+ {
+ const auto& objects = it->second;
+ return std::find(objects.begin(), objects.end(), obj) != objects.end();
+ }
+ return false;
+}
+
+void LLViewerObject::requestObjectUpdate()
+{
+ if (LLViewerRegion* regionp = getRegion())
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestMultipleObjects);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU8Fast(_PREHASH_CacheMissType, 0);
+ msg->addU32Fast(_PREHASH_ID, getLocalID());
+ msg->sendReliable(regionp->getHost());
+
+ removeObjectFromPendingUpdate(this);
+ }
+}
+
class ObjectPhysicsProperties : public LLHTTPNode
{
public:
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 6e26da74e7..8f23563c28 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -126,13 +126,15 @@ class LLViewerObject
protected:
virtual ~LLViewerObject(); // use unref()
+private:
// TomY: Provide for a list of extra parameter structures, mapped by structure name
struct ExtraParameter
{
- bool in_use;
- LLNetworkData *data;
+ bool is_invalid = false;
+ bool* in_use = nullptr;
+ LLNetworkData* data = nullptr;
};
- std::unordered_map<U16, ExtraParameter*> mExtraParameterList;
+ std::vector<ExtraParameter> mExtraParameterList;
public:
typedef std::list<LLPointer<LLViewerObject> > child_list_t;
@@ -620,6 +622,11 @@ public:
void setPhysicsDensity(F32 density);
void setPhysicsRestitution(F32 restitution);
+ static void markObjectsForUpdate(const LLUUID& owner_id);
+ static void removeObjectFromPendingUpdate(LLViewerObject* obj);
+ static bool isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj);
+ void requestObjectUpdate();
+
virtual void dump() const;
static U32 getNumZombieObjects() { return sNumZombieObjects; }
@@ -630,10 +637,16 @@ public:
void dirtySpatialGroup() const;
virtual void dirtyMesh();
- virtual LLNetworkData* getParameterEntry(U16 param_type) const;
- virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin);
- virtual bool getParameterEntryInUse(U16 param_type) const;
- virtual bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin);
+ LLFlexibleObjectData* getFlexibleObjectData() const { return mFlexibleObjectDataInUse ? mFlexibleObjectData.get() : nullptr; }
+ LLLightParams* getLightParams() const { return mLightParamsInUse ? mLightParams.get() : nullptr; }
+ LLSculptParams* getSculptParams() const { return mSculptParamsInUse ? mSculptParams.get() : nullptr; }
+ LLLightImageParams* getLightImageParams() const { return mLightImageParamsInUse ? mLightImageParams.get() : nullptr; }
+ LLExtendedMeshParams* getExtendedMeshParams() const { return mExtendedMeshParamsInUse ? mExtendedMeshParams.get() : nullptr; }
+ LLRenderMaterialParams* getRenderMaterialParams() const { return mRenderMaterialParamsInUse ? mRenderMaterialParams.get() : nullptr; }
+ LLReflectionProbeParams* getReflectionProbeParams() const { return mReflectionProbeParamsInUse ? mReflectionProbeParams.get() : nullptr; }
+
+ bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin);
+ bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin);
// Called when a parameter is changed
virtual void parameterChanged(U16 param_type, bool local_origin);
virtual void parameterChanged(U16 param_type, LLNetworkData* data, bool in_use, bool local_origin);
@@ -675,8 +688,31 @@ private:
bool isAssetInInventory(LLViewerInventoryItem* item, LLAssetType::EType type);
ExtraParameter* createNewParameterEntry(U16 param_type);
- ExtraParameter* getExtraParameterEntry(U16 param_type) const;
- ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
+ const ExtraParameter& getExtraParameterEntry(U16 param_type) const
+ {
+ return mExtraParameterList[U32(param_type >> 4) - 1];
+ }
+ ExtraParameter& getExtraParameterEntry(U16 param_type)
+ {
+ return mExtraParameterList[U32(param_type >> 4) - 1];
+ }
+ ExtraParameter* getExtraParameterEntryCreate(U16 param_type)
+ {
+ if (param_type <= LLNetworkData::PARAMS_MAX)
+ {
+ ExtraParameter& param = getExtraParameterEntry(param_type);
+ if (!param.is_invalid)
+ {
+ if (!param.data)
+ {
+ ExtraParameter* new_entry = createNewParameterEntry(param_type);
+ return new_entry;
+ }
+ return &param;
+ }
+ }
+ return nullptr;
+ }
bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
// This function checks to see if the given media URL has changed its version
@@ -749,7 +785,23 @@ private:
// Grabbed from UPDATE_FLAGS
U32 mFlags;
+ bool mFlexibleObjectDataInUse = false,
+ mLightParamsInUse = false,
+ mSculptParamsInUse = false,
+ mLightImageParamsInUse = false,
+ mExtendedMeshParamsInUse = false,
+ mRenderMaterialParamsInUse = false,
+ mReflectionProbeParamsInUse = false;
+ std::unique_ptr<LLFlexibleObjectData> mFlexibleObjectData;
+ std::unique_ptr<LLLightParams> mLightParams;
+ std::unique_ptr<LLSculptParams> mSculptParams;
+ std::unique_ptr<LLLightImageParams> mLightImageParams;
+ std::unique_ptr<LLExtendedMeshParams> mExtendedMeshParams;
+ std::unique_ptr<LLRenderMaterialParams> mRenderMaterialParams;
+ std::unique_ptr<LLReflectionProbeParams> mReflectionProbeParams;
+
static std::map<std::string, U32> sObjectDataMap;
+ static std::unordered_map<LLUUID, std::vector<LLViewerObject*>> sPendingUpdatesByOwner;
public:
// Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties
U8 mPhysicsShapeType;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index e41f5bc206..caabd66780 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -65,6 +65,7 @@
#include "lltoolmgr.h"
#include "lltoolpie.h"
#include "llkeyboard.h"
+#include "llmeshrepository.h"
#include "u64.h"
#include "llviewertexturelist.h"
#include "lldatapacker.h"
@@ -173,7 +174,7 @@ bool LLViewerObjectList::removeFromLocalIDTable(LLViewerObject* objectp)
U32 local_id = objectp->mLocalID;
U64 indexid = (((U64)objectp->mRegionIndex) << 32) | (U64)local_id;
- std::map<U64, LLUUID>::iterator iter = mIndexAndLocalIDToUUID.find(indexid);
+ auto iter = mIndexAndLocalIDToUUID.find(indexid);
if (iter == mIndexAndLocalIDToUUID.end())
{
return false;
@@ -1398,6 +1399,8 @@ void LLViewerObjectList::killAllObjects()
llassert((objectp == gAgentAvatarp) || objectp->isDead());
}
+ gMeshRepo.unregisterAllMeshes();
+
cleanDeadObjects(false);
if(!mObjects.empty())
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 547ef9fb2d..adc90a0483 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -204,7 +204,7 @@ protected:
uuid_set_t mDeadObjects;
- std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
+ std::unordered_map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
//set of objects that need to update their cost
uuid_set_t mStaleObjectCost;
@@ -221,7 +221,7 @@ protected:
static U32 sSimulatorMachineIndex;
std::map<U64, U32> mIPAndPortToIndex;
- std::map<U64, LLUUID> mIndexAndLocalIDToUUID;
+ std::unordered_map<U64, LLUUID> mIndexAndLocalIDToUUID;
friend class LLViewerObject;
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index a1c2e0f9ff..a43e4b99f9 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -1143,6 +1143,8 @@ void LLOcclusionCullingGroup::checkOcclusion()
GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query result");
+ // Ping watchdog before a blocking GL_QUERY_RESULT GPU call
+ LLAppViewer::instance()->pingMainloopTimeout("Display:CullQueryResult");
glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT, &query_result);
}
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 60e17a6f58..adfe709b04 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -316,7 +316,6 @@ public:
//virtual
bool isRecentlyVisible() const;
- LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;}
bool isAnyRecentlyVisible() const;
static U32 getNewOcclusionQueryObjectName();
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 432da2e990..b794047135 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -702,6 +702,16 @@ bool LLViewerParcelMgr::allowAgentVoice() const
return allowAgentVoice(gAgent.getRegion(), mAgentParcel);
}
+bool LLViewerParcelMgr::isVoiceRestricted() const
+{
+ return mAgentParcel && !mAgentParcel->getParcelFlagUseEstateVoiceChannel();
+}
+
+bool LLViewerParcelMgr::allowVoiceModeration() const
+{
+ return isVoiceRestricted() && isParcelOwnedByAgent(mAgentParcel, GP_SESSION_MODERATOR);
+}
+
bool LLViewerParcelMgr::allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const
{
return region && region->isVoiceEnabled()
@@ -881,7 +891,8 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const
void LLViewerParcelMgr::render()
{
- if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection") && !gDisconnected)
+ static LLCachedControl<bool> render_parcel_selection(gSavedSettings, "RenderParcelSelection");
+ if (mSelected && mRenderSelection && render_parcel_selection() && !gDisconnected)
{
// Rendering is done in agent-coordinates, so need to supply
// an appropriate offset to the render code.
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 8439283eb0..0d79496ccc 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -174,6 +174,12 @@ public:
bool allowAgentVoice() const;
bool allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const;
+ // Returns true if this parcel is using private voice channel
+ bool isVoiceRestricted() const;
+
+ // Can this agent moderate Nearby voice chat on this parcel?
+ bool allowVoiceModeration() const;
+
// Can this agent start flying on this parcel?
// Used for parcel property icons in nav bar.
bool allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const;
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index f6ee00cb25..d33d426769 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -126,8 +126,6 @@
#include "llfloater.h"
#include <boost/signals2.hpp>
-#include <boost/unordered_set.hpp>
-#include <boost/unordered_map.hpp>
#include <boost/json.hpp>
#include "glm/glm.hpp"
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index cd70f8f9b9..dd02cca50a 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -104,7 +104,7 @@ S32 LLViewerRegion::sLastCameraUpdated = 0;
S32 LLViewerRegion::sNewObjectCreationThrottle = -1;
LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup;
-typedef std::map<std::string, std::string> CapabilityMap;
+typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> CapabilityMap;
static void log_capabilities(const CapabilityMap &capmap);
@@ -1768,6 +1768,11 @@ void LLViewerRegion::killInvisibleObjects(F32 max_time)
if(iter == mImpl->mActiveSet.end())
{
iter = mImpl->mActiveSet.begin();
+ if (iter == mImpl->mActiveSet.end())
+ {
+ // Set became empty
+ break;
+ }
}
if((*iter)->getParentID() > 0)
{
@@ -3300,6 +3305,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("SetDisplayName");
capabilityNames.append("SimConsoleAsync");
capabilityNames.append("SimulatorFeatures");
+ capabilityNames.append("SpatialVoiceModerationRequest");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TerrainNavMeshProperties");
capabilityNames.append("TextureStats");
@@ -3437,7 +3443,7 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri
}
}
-std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const
+std::string LLViewerRegion::getCapabilityDebug(std::string_view name) const
{
CapabilityMap::const_iterator iter = mImpl->mSecondCapabilitiesTracker.find(name);
if (iter == mImpl->mSecondCapabilitiesTracker.end())
@@ -3448,15 +3454,14 @@ std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const
return iter->second;
}
-
-bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
+bool LLViewerRegion::isSpecialCapabilityName(std::string_view name)
{
return name == "EventQueueGet" || name == "UntrustedSimulatorMessage";
}
-std::string LLViewerRegion::getCapability(const std::string& name) const
+std::string LLViewerRegion::getCapability(std::string_view name) const
{
- if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
+ if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia"))
{
LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL;
}
@@ -3464,21 +3469,20 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
if(iter == mImpl->mCapabilities.end())
{
- return "";
+ return {};
}
return iter->second;
}
-bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const
+bool LLViewerRegion::isCapabilityAvailable(std::string_view name) const
{
- if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
+ if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia"))
{
LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL;
}
- CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
- if(iter == mImpl->mCapabilities.end())
+ if (!mImpl->mCapabilities.contains(name))
{
return false;
}
@@ -3734,9 +3738,14 @@ bool LLViewerRegion::avatarHoverHeightEnabled() const
void log_capabilities(const CapabilityMap &capmap)
{
+ // Copy into sorted map for ordered output
+ using SortedCapabilityMap = std::map<std::string, std::string>;
+ SortedCapabilityMap sorted_capmap;
+ sorted_capmap.insert(capmap.begin(), capmap.end());
+
S32 count = 0;
- CapabilityMap::const_iterator iter;
- for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count)
+ SortedCapabilityMap::const_iterator iter;
+ for (iter = sorted_capmap.begin(); iter != sorted_capmap.end(); ++iter, ++count)
{
if (!iter->second.empty())
{
@@ -3797,6 +3806,16 @@ std::string LLViewerRegion::getSimHostName()
return std::string("...");
}
+
+bool LLViewerRegion::isRegionWebRTCEnabled()
+{
+ if (mSimulatorFeaturesReceived && mSimulatorFeatures.has("VoiceServerType"))
+ {
+ return mSimulatorFeatures["VoiceServerType"].asString() == "webrtc";
+ }
+ return false;
+}
+
void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 9c5a63e23a..a086d45ec1 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -275,10 +275,10 @@ public:
S32 getNumSeedCapRetries();
void setCapability(const std::string& name, const std::string& url);
void setCapabilityDebug(const std::string& name, const std::string& url);
- bool isCapabilityAvailable(const std::string& name) const;
+ bool isCapabilityAvailable(std::string_view name) const;
// implements LLCapabilityProvider
- virtual std::string getCapability(const std::string& name) const;
- std::string getCapabilityDebug(const std::string& name) const;
+ virtual std::string getCapability(std::string_view name) const;
+ std::string getCapabilityDebug(std::string_view name) const;
// has region received its final (not seed) capability list?
@@ -288,7 +288,7 @@ public:
void setCapabilitiesError();
boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb);
- static bool isSpecialCapabilityName(const std::string &name);
+ static bool isSpecialCapabilityName(std::string_view name);
void logActiveCapabilities() const;
// Utilities to post and get via
@@ -425,6 +425,8 @@ public:
std::string getSimHostName();
+ bool isRegionWebRTCEnabled();
+
static bool isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;}
// rebuild reflection probe list
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 3b2f68bb3b..f84c2b8530 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -62,7 +62,6 @@
#include "llsdserialize.h"
#include "llsdutil.h"
#include "llcorehttputil.h"
-#include "llvoicevivox.h"
#include "llinventorymodel.h"
#include "lluiusage.h"
#include "lltranslate.h"
@@ -233,6 +232,8 @@ LLTrace::SampleStatHandle<U32> FRAMETIME_JITTER_EVENTS("frametimeevents", "Numbe
FRAMETIME_JITTER_EVENTS_PER_MINUTE("frametimeeventspm", "Average number of frametime events per minute."),
FRAMETIME_JITTER_EVENTS_LAST_MINUTE("frametimeeventslastmin", "Number of frametime events in the last minute.");
+LLTrace::SampleStatHandle<U64> DOFRAME_TIME_US("doframetimeus", "doFrame wall time in microseconds.");
+
LLTrace::SampleStatHandle<F64> NOTRMALIZED_FRAMETIME_JITTER_SESSION("normalizedframetimejitter", "Normalized frametime jitter over the session.");
LLTrace::SampleStatHandle<F64> NFTV("nftv", "Normalized frametime variation.");
LLTrace::SampleStatHandle<F64> NORMALIZED_FRAMTIME_JITTER_PERIOD("normalizedframetimejitterperiod", "Normalized frametime jitter over the last 5 seconds.");
@@ -263,6 +264,20 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > HUDS_FRAME_PCT("huds_
LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > UI_FRAME_PCT("ui_frame_pct");
LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > SWAP_FRAME_PCT("swap_frame_pct");
LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > IDLE_FRAME_PCT("idle_frame_pct");
+
+
+
+LLTrace::SampleStatHandle<U32> WEBRTC_PACKETS_IN_LOST("webrtc_packets_in_lost", "Lost incoming packets"),
+ WEBRTC_PACKETS_IN_RECEIVED("webrtc_packets_in_recv", "Incoming packets received"),
+ WEBRTC_PACKETS_OUT_SENT("webrtc_packets_out_sent", "Outgoing packets sent"),
+ WEBRTC_PACKETS_OUT_LOST("webrtc_packets_out_lost", "Lost outgoing packets");
+
+LLTrace::SampleStatHandle<F32> WEBRTC_JITTER_OUT("webrtc_jitter_out", "Timing variation of outgoing audio"),
+ WEBRTC_JITTER_IN("webrtc_jitter_in", "Timing variation of incoming audio"),
+ WEBRTC_LATENCY("webrtc_latency", "Round-trip audio delay"),
+ WEBRTC_UPLOAD_BANDWIDTH("webrtc_upload_bandwidth", "Estimated upload bandwidth"),
+ WEBRTC_JITTER_BUFFER("webrtc_jitter_buffer", "Average delay added to smooth incoming audio");
+
}
LLViewerStats::LLViewerStats()
@@ -796,8 +811,6 @@ void send_viewer_stats(bool include_preferences)
body["ui"] = LLUIUsage::instance().asLLSD();
- body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read();
-
// Misc stats, two strings and two ints
// These are not expecticed to persist across multiple releases
// Comment any changes with your name and the expected release revision
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 1ac8b2f66b..7da74e716b 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -209,28 +209,46 @@ extern SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM;
extern LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER,
- SIM_PING;
+ FRAMETIME,
+ SIM_PING,
+ FRAMETIME_JITTER_99TH,
+ FRAMETIME_JITTER_95TH,
+ FRAMETIME_99TH,
+ FRAMETIME_95TH,
+ FRAMETIME_JITTER_CUMULATIVE,
+ FRAMETIME_JITTER_STDDEV,
+ FRAMETIME_STDDEV;
+
+extern LLTrace::SampleStatHandle<U32> FRAMETIME_JITTER_EVENTS,
+ FRAMETIME_JITTER_EVENTS_PER_MINUTE,
+ FRAMETIME_JITTER_EVENTS_LAST_MINUTE;
+
+extern LLTrace::SampleStatHandle<U64> DOFRAME_TIME_US;
+
+extern LLTrace::SampleStatHandle<F64> NOTRMALIZED_FRAMETIME_JITTER_SESSION;
+extern LLTrace::SampleStatHandle<F64> NFTV;
+extern LLTrace::SampleStatHandle<F64> NORMALIZED_FRAMTIME_JITTER_PERIOD;
extern LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP;
extern LLTrace::EventStatHandle<> LOADING_WEARABLES_LONG_DELAY;
extern LLTrace::EventStatHandle<F64Milliseconds > REGION_CROSSING_TIME,
- FRAME_STACKTIME,
- UPDATE_STACKTIME,
- NETWORK_STACKTIME,
- IMAGE_STACKTIME,
- REBUILD_STACKTIME,
- RENDER_STACKTIME;
+ FRAME_STACKTIME,
+ UPDATE_STACKTIME,
+ NETWORK_STACKTIME,
+ IMAGE_STACKTIME,
+ REBUILD_STACKTIME,
+ RENDER_STACKTIME;
extern LLTrace::EventStatHandle<F64Seconds > AVATAR_EDIT_TIME,
- TOOLBOX_TIME,
- MOUSELOOK_TIME;
+ TOOLBOX_TIME,
+ MOUSELOOK_TIME;
extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT_RATE;
-extern LLTrace::SampleStatHandle<F64> NOTRMALIZED_FRAMETIME_JITTER_SESSION;
-extern LLTrace::SampleStatHandle<F64> NORMALIZED_FRAMTIME_JITTER_PERIOD;
+extern LLTrace::SampleStatHandle<U32> WEBRTC_PACKETS_IN_LOST, WEBRTC_PACKETS_IN_RECEIVED, WEBRTC_PACKETS_OUT_SENT, WEBRTC_PACKETS_OUT_LOST;
+extern LLTrace::SampleStatHandle<F32> WEBRTC_JITTER_OUT, WEBRTC_JITTER_IN, WEBRTC_LATENCY, WEBRTC_UPLOAD_BANDWIDTH, WEBRTC_JITTER_BUFFER;
}
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 210cd62d6f..95e34b4df1 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -189,7 +189,12 @@ public:
return new LLEmbeddedItemSegment(mStart, mImage, mItem, *editor);
}
- /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height)
+ {
+ return getSegmentDimensionsF32(first_char, num_chars, width, height);
+ }
+
+ inline bool getSegmentDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
if (num_chars == 0)
{
@@ -213,8 +218,9 @@ public:
}
else
{
- S32 width, height;
- getDimensions(mStart, 1, width, height);
+ F32 width;
+ S32 height;
+ getSegmentDimensionsF32(mStart, 1, width, height);
if (width > num_pixels)
{
return 0;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c7513ded62..f31aa8e6c5 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -533,7 +533,7 @@ void LLViewerTexture::updateClass()
if (is_sys_low)
{
// Not having system memory is more serious, so discard harder
- sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f * getSystemMemoryBudgetFactor());
+ sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f * LLMemory::getSystemMemoryBudgetFactor());
}
else
{
@@ -679,20 +679,6 @@ bool LLViewerTexture::isSystemMemoryCritical()
return getFreeSystemMemory() < get_render_free_main_memory_treshold() / 2;
}
-F32 LLViewerTexture::getSystemMemoryBudgetFactor()
-{
- const S32Megabytes MIN_FREE_MAIN_MEMORY(get_render_free_main_memory_treshold() / 2);
- S32 free_budget = (S32Megabytes)getFreeSystemMemory() - MIN_FREE_MAIN_MEMORY;
- if (free_budget < 0)
- {
- // Leave some padding, otherwise we will crash out of memory before hitting factor 2.
- const S32Megabytes PAD_BUFFER(32);
- // Result should range from 1 at 0 free budget to 2 at -224 free budget, 2.14 at -256MB
- return 1.f - free_budget / (MIN_FREE_MAIN_MEMORY - PAD_BUFFER);
- }
- return 1.f;
-}
-
//end of static functions
//-------------------------------------------------------------------------------------------
const U32 LLViewerTexture::sCurrentFileVersion = 1;
@@ -1488,7 +1474,9 @@ bool LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/)
// from local images, but this might become unsafe in case of changes to fetcher
if (mBoostLevel == BOOST_PREVIEW)
{
- mRawImage->biasedScaleToPowerOfTwo(1024);
+ // A local file with a preview flag likely means mesh's texture upload
+ // which should follow normal upload scaling rules
+ mRawImage->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
}
else
{ // leave black border, do not scale image content
@@ -1896,13 +1884,11 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre
mRawDiscardLevel = INVALID_DISCARD_LEVEL;
mIsFetching = false;
mLastPacketTimer.reset();
- }
- else
- {
- mIsRawImageValid = true;
- addToCreateTexture();
+ return false;
}
+ mIsRawImageValid = true;
+
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
@@ -1914,7 +1900,11 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre
//
// BOOST_ICON gets scaling because profile icons can have a bunch of different formats, not just j2c
// Might need another pass to use discard for j2c and scaling for everything else.
- mRawImage = mRawImage->scaled(expected_width, expected_height);
+ LLPointer<LLImageRaw> scaled = mRawImage->scaled(expected_width, expected_height);
+ if (scaled.notNull())
+ {
+ mRawImage = scaled;
+ }
}
}
@@ -1929,10 +1919,16 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre
//
// Todo: probably needs to be remade to use discard, all thumbnails are supposed to be j2c,
// so no need to scale, should be posible to use discard to scale image down.
- mRawImage = mRawImage->scaled(expected_width, expected_height);
+ LLPointer<LLImageRaw> scaled = mRawImage->scaled(expected_width, expected_height);
+ if (scaled.notNull())
+ {
+ mRawImage = scaled;
+ }
}
}
+ addToCreateTexture();
+
return true;
}
else
@@ -2574,14 +2570,31 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
S32 best_raw_discard = gl_discard; // Current GL quality level
S32 current_aux_discard = MAX_DISCARD_LEVEL + 1;
S32 best_aux_discard = MAX_DISCARD_LEVEL + 1;
+ LLImageRaw *current_raw_image = nullptr;
if (mIsRawImageValid)
{
- // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels.
+ // If we have an existing raw image, we have a baseline for the raw
+ // and auxiliary quality levels.
+ // Note: we call updateImagesCreateTextures before callbacks, which
+ // leads to destroyRawImage and deletes raw image. So this case
+ // might be rare or even never trigger as there is never a raw image,
+ // only a saved one.
current_raw_discard = mRawDiscardLevel;
best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel);
best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw
current_aux_discard = llmin(current_aux_discard, best_aux_discard);
+ current_raw_image = mRawImage;
+ }
+ else if (mSavedRawImage.notNull())
+ {
+ // We have a saved raw image, we can use that as our baseline for
+ // raw and auxiliary quality levels.
+ current_raw_discard = mSavedRawDiscardLevel;
+ best_raw_discard = llmin(best_raw_discard, mSavedRawDiscardLevel);
+ best_aux_discard = llmin(best_aux_discard, mSavedRawDiscardLevel); // We always decode the aux when we decode the base raw
+ current_aux_discard = llmin(current_aux_discard, best_aux_discard);
+ current_raw_image = mSavedRawImage;
}
else
{
@@ -2646,12 +2659,17 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
if (need_readback)
{
readbackRawImage();
+ if (mIsRawImageValid)
+ {
+ current_raw_discard = mRawDiscardLevel;
+ current_raw_image = mRawImage;
+ }
}
//
// Run raw/auxiliary data callbacks
//
- if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel()))
+ if (run_raw_callbacks && current_raw_image != nullptr && (current_raw_discard <= getMaxDiscardLevel()))
{
// Do callbacks which require raw image data.
//LL_INFOS() << "doLoadedCallbacks raw for " << getID() << LL_ENDL;
@@ -2662,7 +2680,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
{
callback_list_t::iterator curiter = iter++;
LLLoadedCallbackEntry *entryp = *curiter;
- if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel))
+ if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > current_raw_discard))
{
// If we've loaded all the data there is to load or we've loaded enough
// to satisfy the interested party, then this is the last time that
@@ -2673,11 +2691,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
{
LL_WARNS() << "Raw Image with no Aux Data for callback" << LL_ENDL;
}
- bool final = mRawDiscardLevel <= entryp->mDesiredDiscard;
+ bool final = current_raw_discard <= entryp->mDesiredDiscard;
//LL_INFOS() << "Running callback for " << getID() << LL_ENDL;
- //LL_INFOS() << mRawImage->getWidth() << "x" << mRawImage->getHeight() << LL_ENDL;
- entryp->mLastUsedDiscard = mRawDiscardLevel;
- entryp->mCallback(true, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData);
+ //LL_INFOS() << current_raw_image->getWidth() << "x" << current_raw_image->getHeight() << LL_ENDL;
+ entryp->mLastUsedDiscard = current_raw_discard;
+ entryp->mCallback(true, this, current_raw_image, mAuxRawImage, current_raw_discard, final, entryp->mUserData);
if (final)
{
iter = mLoadedCallbackList.erase(curiter);
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 2937651995..20aaa8a058 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -116,7 +116,6 @@ public:
static void updateClass();
static bool isSystemMemoryLow();
static bool isSystemMemoryCritical();
- static F32 getSystemMemoryBudgetFactor();
LLViewerTexture(bool usemipmaps = true);
LLViewerTexture(const LLUUID& id, bool usemipmaps) ;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 6f62d13d51..e77c14a53d 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1106,7 +1106,17 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
while (!mCreateTextureList.empty())
{
- LLViewerFetchedTexture* imagep = mCreateTextureList.front();
+ // Hold a smart pointer to keep the texture alive throughout processing,
+ // even if side effects (e.g. pipeline rebuilds, GL operations) indirectly
+ // cause other references to be released. (see: #5426)
+ LLPointer<LLViewerFetchedTexture> imagep = mCreateTextureList.front();
+ mCreateTextureList.pop();
+
+ if (!imagep)
+ {
+ continue;
+ }
+
llassert(imagep->mCreatePending);
// desired discard may change while an image is being decoded. If the texture in VRAM is sufficient
@@ -1132,8 +1142,6 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
imagep->scaleDown();
}
- mCreateTextureList.pop();
-
if (create_timer.getElapsedTimeF32() > max_time)
{
break;
@@ -1155,10 +1163,11 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
// give time to downscaling first -- if mDownScaleQueue is not empty, we're running out of memory and need
// to free up memory by discarding off screen textures quickly
+ S32 min_count = (S32)mCreateTextureList.size() / 20 + 3;
// do at least 5 and make sure we don't get too far behind even if it violates
// the time limit. If we don't downscale quickly the viewer will hit swap and may
// freeze.
- S32 min_count = (S32)mCreateTextureList.size() / 20 + 3;
+ //S32 min_count = (S32)mCreateTextureList.size() / 20 + 5;
create_timer.reset();
while (!mDownScaleQueue.empty())
@@ -1203,15 +1212,29 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
LLTimer timer;
image_list_t::iterator enditer = mFastCacheList.begin();
- for (image_list_t::iterator iter = mFastCacheList.begin();
- iter != mFastCacheList.end();)
{
- image_list_t::iterator curiter = iter++;
- enditer = iter;
- LLViewerFetchedTexture *imagep = *curiter;
- imagep->loadFromFastCache();
- if (timer.getElapsedTimeF32() > max_time)
- break;
+ // Prelock fast cache mutex to avoid waiting multiple times.
+ LLMutexTrylock fast_cache_lock(LLAppViewer::getTextureCache()->getFastCacheMutex());
+ if (!fast_cache_lock.isLocked())
+ {
+ // Cache is busy, skip this update cycle to avoid blocking the main thread.
+ //
+ // Generally fast cache operations are brief and rare in comparison to writing
+ // main texture body, but if disk is busy, it can get stuck for multiple
+ // seconds, waiting for that long is not practical.
+ // But some variant of a timed try lock for 0.1ms or less might be optimal.
+ return 0.0f;
+ }
+ for (image_list_t::iterator iter = mFastCacheList.begin();
+ iter != mFastCacheList.end();)
+ {
+ image_list_t::iterator curiter = iter++;
+ enditer = iter;
+ LLViewerFetchedTexture* imagep = *curiter;
+ imagep->loadFromFastCache();
+ if (timer.getElapsedTimeF32() > max_time)
+ break;
+ }
}
mFastCacheList.erase(mFastCacheList.begin(), enditer);
return timer.getElapsedTimeF32();
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index 583fb25330..50af9756a3 100644
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -96,6 +96,7 @@ LLViewerWearable::~LLViewerWearable()
// virtual
LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp )
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
// suppress texlayerset updates while wearables are being imported. Layersets will be updated
// when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed.
LLOverrideBakedTextureUpdate stop_bakes(false);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 9788fc5f4d..1183cc70ef 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -34,7 +34,6 @@
#include <fstream>
#include <algorithm>
#include <boost/filesystem.hpp>
-#include <boost/lambda/core.hpp>
#include <boost/regex.hpp>
#include "llagent.h"
@@ -204,6 +203,7 @@
#include "llwindowlistener.h"
#include "llviewerwindowlistener.h"
+#include "llstatslistener.h"
#include "llcleanup.h"
#if LL_WINDOWS
@@ -1336,7 +1336,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
// Check the whitelist, if there's media (otherwise just show it)
if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
{
- if ( obj != mDragHoveredObject.get())
+ if (obj != mDragHoveredObject)
{
// Highlight the dragged object
LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
@@ -1777,7 +1777,7 @@ bool LLViewerWindow::handleTimerEvent(LLWindow *window)
return false;
}
-bool LLViewerWindow::handleDeviceChange(LLWindow *window)
+bool LLViewerWindow::handleDeviceChange(LLWindow *window, const std::string& change_type)
{
// give a chance to use a joystick after startup (hot-plugging)
if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
@@ -1785,6 +1785,10 @@ bool LLViewerWindow::handleDeviceChange(LLWindow *window)
LLViewerJoystick::getInstance()->init(true);
return true;
}
+ else
+ {
+ LL_INFOS("Window") << "Device change event: " << change_type << LL_ENDL;
+ }
return false;
}
@@ -1806,6 +1810,7 @@ bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32
bool LLViewerWindow::handleDisplayChanged()
{
+ LL_INFOS("Window") << "Display change event" << LL_ENDL;
LLFontGL::sResolutionGeneration++;
return false;
}
@@ -1876,8 +1881,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mToolStored( NULL ),
mHideCursorPermanent( false ),
mCursorHidden(false),
- mResDirty(false),
- mStatesDirty(false),
+ mResDirty(true),
+ mStatesDirty(true),
mProgressView(NULL)
{
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
@@ -1887,6 +1892,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)
LLWindowListener::KeyboardGetter getter = [](){ return gKeyboard; };
mWindowListener = std::make_unique<LLWindowListener>(this, getter);
mViewerWindowListener = std::make_unique<LLViewerWindowListener>(this);
+ mStatsListener = std::make_unique<LLStatsListener>();
mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything));
mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible"));
@@ -2078,10 +2084,6 @@ void LLViewerWindow::initGLDefaults()
gBox.prerender();
}
-struct MainPanel : public LLPanel
-{
-};
-
void LLViewerWindow::initBase()
{
S32 height = getWindowHeightScaled();
@@ -2120,6 +2122,8 @@ void LLViewerWindow::initBase()
main_view->setShape(full_window);
getRootView()->addChild(main_view);
+ mMainView = main_view;
+
// placeholder widget that controls where "world" is rendered
mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
mPopupView = main_view->getChild<LLPopupView>("popup_holder");
@@ -2335,14 +2339,22 @@ void LLViewerWindow::initWorldUI()
physical_mem = LLMemory::getMaxMemKB();
}
- if (!gNonInteractive && physical_mem > MIN_PHYSICAL_MEMORY)
+ if (!gNonInteractive)
{
- LL_INFOS() << "Preloading cef instances" << LL_ENDL;
+ if (physical_mem > MIN_PHYSICAL_MEMORY)
+ {
+ LL_INFOS() << "Preloading cef instances" << LL_ENDL;
- LLFloaterReg::getInstance("destinations");
- LLFloaterReg::getInstance("avatar_welcome_pack");
- LLFloaterReg::getInstance("search");
- LLFloaterReg::getInstance("marketplace");
+ LLFloaterReg::getInstance("destinations");
+ LLFloaterReg::getInstance("avatar_welcome_pack");
+ LLFloaterReg::getInstance("search");
+ LLFloaterReg::getInstance("marketplace");
+ }
+ else if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ {
+ // Preload the welcome pack for first-time login even on low end hardware
+ LLFloaterReg::getInstance("avatar_welcome_pack");
+ }
}
}
@@ -3332,7 +3344,7 @@ void LLViewerWindow::clearPopups()
void LLViewerWindow::moveCursorToCenter()
{
bool mouse_warp = false;
- LLCachedControl<S32> mouse_warp_mode(gSavedSettings, "MouseWarpMode", 1);
+ static LLCachedControl<S32> mouse_warp_mode(gSavedSettings, "MouseWarpMode", 1);
switch (mouse_warp_mode())
{
@@ -3405,13 +3417,11 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
}
}
-static LLTrace::BlockTimerStatHandle ftm("Update UI");
-
// Update UI based on stored mouse position from mouse-move
// event processing.
void LLViewerWindow::updateUI()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
static std::string last_handle_msg;
@@ -3429,12 +3439,15 @@ void LLViewerWindow::updateUI()
}
}
- LLConsole::updateClass();
+ {
+ LL_PROFILE_ZONE_NAMED("UI updateClass");
+ LLConsole::updateClass();
- // execute postponed arrange calls
- LLAccordionCtrl::updateClass();
- // animate layout stacks so we have up to date rect for world view
- LLLayoutStack::updateClass();
+ // execute postponed arrange calls
+ LLAccordionCtrl::updateClass();
+ // animate layout stacks so we have up to date rect for world view
+ LLLayoutStack::updateClass();
+ }
// use full window for world view when not rendering UI
bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
@@ -3863,6 +3876,7 @@ void LLViewerWindow::updateUI()
void LLViewerWindow::updateLayout()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
if (gFloaterTools != NULL
&& tool != NULL
@@ -4342,15 +4356,15 @@ void LLViewerWindow::pickAsync( S32 x,
bool pick_unselectable,
bool pick_reflection_probes)
{
+ static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects");
// "Show Debug Alpha" means no object actually transparent
bool in_build_mode = LLFloaterReg::instanceVisible("build");
- if (LLDrawPoolAlpha::sShowDebugAlpha
- || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")))
+ if (LLDrawPoolAlpha::sShowDebugAlpha || (in_build_mode && select_invisible_objects))
{
pick_transparent = true;
}
- LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, pick_unselectable, true, callback);
+ LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, true, pick_unselectable, callback);
schedulePick(pick_info);
}
@@ -4374,7 +4388,6 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
mWindow->delayInputProcessing();
}
-
void LLViewerWindow::performPick()
{
if (!mPicks.empty())
@@ -4408,8 +4421,9 @@ void LLViewerWindow::returnEmptyPicks()
// Performs the GL object/land pick.
LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transparent, bool pick_rigged, bool pick_particle, bool pick_unselectable, bool pick_reflection_probe)
{
+ static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects");
bool in_build_mode = LLFloaterReg::instanceVisible("build");
- if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha)
+ if ((in_build_mode && select_invisible_objects) || LLDrawPoolAlpha::sShowDebugAlpha)
{
// build mode allows interaction with all transparent objects
// "Show Debug Alpha" means no object actually transparent
@@ -4417,7 +4431,7 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transp
}
// shortcut queueing in mPicks and just update mLastPick in place
- MASK key_mask = gKeyboard->currentMask(true);
+ MASK key_mask = gKeyboard->currentMask(true);
mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, true, false, NULL);
mLastPick.fetchResults();
@@ -4929,6 +4943,19 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
if (image->save(filepath))
{
playSnapshotAnimAndSound();
+
+ // Show clickable notification with filepath
+ LLSD args;
+ args["FILEPATH"] = filepath;
+
+ LLSD payload;
+ payload["filepath"] = filepath;
+
+ LLNotificationsUtil::add("SnapshotSavedToComputer",
+ args,
+ payload.with("respond_on_mousedown", true),
+ boost::bind(&LLViewerWindow::onSnapshotNotificationClick, _1, _2));
+
success_cb();
}
else
@@ -4943,6 +4970,16 @@ void LLViewerWindow::resetSnapshotLoc()
}
// static
+void LLViewerWindow::onSnapshotNotificationClick(const LLSD& notification, const LLSD& response)
+{
+ std::string filepath = notification["payload"]["filepath"].asString();
+ if (!filepath.empty())
+ {
+ gDirUtilp->openDir(filepath);
+ }
+}
+
+// static
void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
{
LLCoordWindow size;
@@ -5986,6 +6023,11 @@ void LLViewerWindow::checkSettings()
// We want to update the resolution AFTER the states getting refreshed not before.
if (mResDirty)
{
+ LLCoordWindow size;
+ mWindow->getSize(&size);
+ mWindowRectRaw.set(0, size.mY, size.mX, 0);
+ mWindowRectScaled.set(0, ll_round((F32)size.mY / mDisplayScale.mV[VY]), ll_round((F32)size.mX / mDisplayScale.mV[VX]), 0);
+
reshape(getWindowWidthRaw(), getWindowHeightRaw());
mResDirty = false;
}
@@ -6164,14 +6206,14 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
bool pick_rigged,
bool pick_particle,
bool pick_reflection_probe,
- bool pick_uv_coords,
+ bool pick_surface_info,
bool pick_unselectable,
void (*pick_callback)(const LLPickInfo& pick_info))
: mMousePt(mouse_pos),
mKeyMask(keyboard_mask),
mPickCallback(pick_callback),
mPickType(PICK_INVALID),
- mWantSurfaceInfo(pick_uv_coords),
+ mWantSurfaceInfo(pick_surface_info),
mObjectFace(-1),
mUVCoords(-1.f, -1.f),
mSTCoords(-1.f, -1.f),
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index f3c7ef3289..c748f051dd 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -66,6 +66,7 @@ class LLWindow;
class LLRootView;
class LLWindowListener;
class LLViewerWindowListener;
+class LLStatsListener;
class LLVOPartGroup;
class LLPopupView;
class LLCubeMap;
@@ -144,6 +145,10 @@ private:
};
+struct MainPanel : public LLPanel
+{
+};
+
static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 * 7680 UHDTV2
class LLViewerWindow : public LLWindowCallbacks
@@ -226,7 +231,7 @@ public:
/*virtual*/ void handleWindowUnblock(LLWindow *window);
/*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data);
/*virtual*/ bool handleTimerEvent(LLWindow *window);
- /*virtual*/ bool handleDeviceChange(LLWindow *window);
+ /*virtual*/ bool handleDeviceChange(LLWindow *window, const std::string& change_type);
/*virtual*/ bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
/*virtual*/ bool handleDisplayChanged();
/*virtual*/ bool handleWindowDidChangeScreen(LLWindow *window);
@@ -248,6 +253,7 @@ public:
// ACCESSORS
//
LLRootView* getRootView() const;
+ MainPanel* getMainView() const { return mMainView; }
// 3D world area in scaled pixels (via UI scale), use for most UI computations
LLRect getWorldViewRectScaled() const;
@@ -405,6 +411,7 @@ public:
void resetSnapshotLoc();
void playSnapshotAnimAndSound();
+ static void onSnapshotNotificationClick(const LLSD& notification, const LLSD& response);
// draws selection boxes around selected objects, must call displayObjects first
void renderSelections( bool for_gl_pick, bool pick_parcel_walls, bool for_hud );
@@ -501,6 +508,7 @@ private:
LLRect mWorldViewRectRaw; // area of screen for 3D world
LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size
LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views
+ MainPanel* mMainView; // a view of size mWindowRectRaw, directly containing the base elements of the ui tree
LLView* mFloaterSnapRegion = nullptr;
LLView* mNavBarContainer = nullptr;
LLPanel* mStatusBarContainer = nullptr;
@@ -556,6 +564,7 @@ private:
std::unique_ptr<LLWindowListener> mWindowListener;
std::unique_ptr<LLViewerWindowListener> mViewerWindowListener;
+ std::unique_ptr<LLStatsListener> mStatsListener;
// Object temporarily hovered over while dragging
LLPointer<LLViewerObject> mDragHoveredObject;
diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp
index c2bcd32921..f4c2c27cee 100644
--- a/indra/newview/llvlmanager.cpp
+++ b/indra/newview/llvlmanager.cpp
@@ -68,7 +68,11 @@ void LLVLManager::addLayerData(LLVLData *vl_datap, const S32Bytes mesg_size)
}
else
{
- LL_ERRS() << "Unknown layer type!" << (S32)vl_datap->mType << LL_ENDL;
+ // Corrupted message? New feature?
+ LL_WARNS() << "Unknown layer type!" << (S32)vl_datap->mType
+ << " for region " << vl_datap->mRegionp->getName() << LL_ENDL;
+ delete vl_datap; // addLayerData took ownership
+ return;
}
mPacketData.push_back(vl_datap);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index e2cafffb51..0bdcb535a8 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -44,6 +44,7 @@
#include "llanimationstates.h"
#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
+#include "llgroupcolormap.h" // group-based nameplate tinting
#include "llavatarrendernotifier.h"
#include "llcontrolavatar.h"
#include "llexperiencecache.h"
@@ -218,6 +219,13 @@ enum ERenderName
RENDER_NAME_FADE
};
+enum ERenderGroupTitle
+{
+ RENDER_GROUP_TITLE_NEVER,
+ RENDER_GROUP_TITLE_SELF,
+ RENDER_GROUP_TITLE_ALWAYS
+};
+
#define JELLYDOLLS_SHOULD_IMPOSTOR
//-----------------------------------------------------------------------------
@@ -608,7 +616,7 @@ const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
};
S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
-bool LLVOAvatar::sRenderGroupTitles = true;
+S32 LLVOAvatar::sRenderGroupTitles = RENDER_GROUP_TITLE_ALWAYS;
S32 LLVOAvatar::sNumVisibleChatBubbles = 0;
bool LLVOAvatar::sDebugInvisible = false;
bool LLVOAvatar::sShowAttachmentPoints = false;
@@ -667,6 +675,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNameAlpha(0.f),
mRenderGroupTitles(sRenderGroupTitles),
mNameCloud(false),
+ mActiveGroupID(),
+ mGroupFetchPending(false),
mFirstTEMessageReceived( false ),
mFirstAppearanceMessageReceived( false ),
mCulled( false ),
@@ -3584,9 +3594,10 @@ void LLVOAvatar::idleUpdateNameTagText(bool new_name)
addNameTagLine(line, name_tag_color, LLFontGL::NORMAL,
LLFontGL::getFontSansSerifSmall());
}
+ bool render_title = (sRenderGroupTitles == RENDER_GROUP_TITLE_ALWAYS) ||
+ (isSelf() && (sRenderGroupTitles == RENDER_GROUP_TITLE_SELF));
- if (sRenderGroupTitles
- && title && title->getString() && title->getString()[0] != '\0')
+ if (render_title && title && title->getString() && title->getString()[0] != '\0')
{
std::string title_str = title->getString();
LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);
@@ -3642,7 +3653,26 @@ void LLVOAvatar::idleUpdateNameTagText(bool new_name)
mNameAppearance = is_appearance;
mNameFriend = is_friend;
mNameCloud = is_cloud;
- mTitle = title ? title->getString() : "";
+
+ // Group-based nameplate tinting: when the title NameValue changes on a
+ // non-self avatar it means their active group (or role) changed. Fire
+ // a lightweight AvatarPropertiesRequest so the AvatarGroupsReply arrives
+ // and we can discover the active group UUID. We register ourselves as an
+ // observer for APT_GROUPS in processProperties() below.
+ const std::string new_title = title ? title->getString() : "";
+ if (!isSelf() && new_title != mTitle)
+ {
+ // Reset cached group UUID - it will be repopulated by the reply.
+ mActiveGroupID.setNull();
+ if (!mGroupFetchPending)
+ {
+ mGroupFetchPending = true;
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getID(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarLegacyPropertiesRequest(getID());
+ }
+ }
+
+ mTitle = new_title;
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
new_name = true;
}
@@ -3875,7 +3905,80 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend)
// ...not using display names
color_name = "NameTagLegacy";
}
- return LLUIColorTable::getInstance()->getColor( color_name );
+
+ LLColor4 base_color = LLUIColorTable::getInstance()->getColor(color_name);
+
+ // Group-based nameplate tinting: override with the group color if one is set.
+ // For self, the active group UUID is always available via gAgent.
+ // For others, it is populated asynchronously via AvatarGroupsReply.
+ LLUUID active_group;
+ if (isSelf())
+ {
+ active_group = gAgent.getGroupID();
+ }
+ else
+ {
+ active_group = mActiveGroupID;
+ }
+
+ if (active_group.notNull())
+ {
+ LLColor4 group_color = LLGroupColorMap::getInstance()->getGroupColor(active_group);
+ if (group_color.mV[VW] >= 0.01f) // non-transparent = has a color set
+ {
+ return group_color;
+ }
+ }
+
+ return base_color;
+}
+
+// ---------------------------------------------------------------------------
+// Group-based nameplate tinting: observer callback
+// ---------------------------------------------------------------------------
+
+void LLVOAvatar::processProperties(void* data, EAvatarProcessorType type)
+{
+ if (type != APT_GROUPS)
+ return;
+
+ LLAvatarGroups* groups = static_cast<LLAvatarGroups*>(data);
+ if (!groups || groups->avatar_id != getID())
+ return;
+
+ // Un-register ourselves — we only need this one reply per title change.
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getID(), this);
+ mGroupFetchPending = false;
+
+ // The active group is the one whose GroupTitle matches the avatar's
+ // current Title NameValue (mTitle). Each avatar can only have one
+ // selected role title displayed at a time, so this match is unambiguous.
+ for (const auto& gd : groups->group_list)
+ {
+ if (gd.group_title == mTitle)
+ {
+ mActiveGroupID = gd.group_id;
+ // Force nametag rebuild so new color is shown immediately.
+ clearNameTag();
+ return;
+ }
+ }
+
+ // No match found (e.g. avatar has no active group or title is blank).
+ mActiveGroupID.setNull();
+ clearNameTag();
+}
+
+// Request the group list for a non-self avatar so we can resolve their
+// active group UUID. Called from idleUpdateNameTagText on title change.
+void LLVOAvatar::sendAvatarGroupsRequest()
+{
+ if (!isSelf() && !mGroupFetchPending)
+ {
+ mGroupFetchPending = true;
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getID(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarLegacyPropertiesRequest(getID());
+ }
}
void LLVOAvatar::idleUpdateBelowWater()
@@ -6008,6 +6111,7 @@ const LLUUID& LLVOAvatar::getStepSound() const
//-----------------------------------------------------------------------------
void LLVOAvatar::processAnimationStateChanges()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
if ( isAnyAnimationSignaled(AGENT_WALK_ANIMS, NUM_AGENT_WALK_ANIMS) )
{
startMotion(ANIM_AGENT_WALK_ADJUST);
@@ -6271,6 +6375,7 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
// virtual
bool LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
{
+ static LLCachedControl<bool> disable_pre_jump_land(gSavedSettings, "DisablePreJumpLand");
LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LLUUID remap_id = remapMotionID(id);
@@ -6280,9 +6385,17 @@ bool LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
}
- if (isSelf() && remap_id == ANIM_AGENT_AWAY)
+ if (isSelf())
{
+ if (remap_id == ANIM_AGENT_AWAY)
+ {
gAgent.setAFK();
+ }
+ else if (disable_pre_jump_land && (remap_id == ANIM_AGENT_PRE_JUMP || remap_id == ANIM_AGENT_LAND || remap_id == ANIM_AGENT_MEDIUM_LAND))
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_FINISH_ANIM);
+ return false;
+ }
}
return LLCharacter::startMotion(remap_id, time_offset);
@@ -7590,7 +7703,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
updateAttachmentOverrides();
}
- updateVisualComplexity();
+ // Inform complexity logic to do partial update.
+ markAttachmentComplexityDirty(viewer_object->getID());
if (viewer_object->isSelected())
{
@@ -7894,7 +8008,7 @@ bool LLVOAvatar::detachObject(LLViewerObject *viewer_object)
if (attachment->isObjectAttached(viewer_object))
{
- updateVisualComplexity();
+ markAttachmentComplexityDirty(viewer_object->getID(), true);
bool is_animated_object = viewer_object->isAnimatedObject();
cleanupAttachedMesh(viewer_object);
@@ -8321,6 +8435,7 @@ void LLVOAvatar::updateRezzedStatusTimers(S32 rez_status)
selfStopPhase("wear_inventory_category", false);
selfStopPhase("process_initial_wearables_update", false);
+ // Start a complexity update.
updateVisualComplexity();
}
}
@@ -8596,6 +8711,10 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading)
if (changed && isSelf())
{
+ // Agent's own avatar doesn't track bakes the same way as other avatars.
+ // So just update here, on cloud removal.
+ markBodyPartsComplexityDirty();
+
// to know about outfit switching
LLAvatarRenderNotifier::getInstance()->updateNotificationState();
}
@@ -8612,7 +8731,7 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading)
bool LLVOAvatar::isFullyLoaded() const
{
- return (mRenderUnloadedAvatar || mFullyLoaded);
+ return (mRenderUnloadedAvatar && !isSelf()) || mFullyLoaded;
}
bool LLVOAvatar::hasFirstFullAttachmentData() const
@@ -9256,6 +9375,7 @@ void LLVOAvatar::releaseComponentTextures()
{
// Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
+ markBodyPartsComplexityDirty();
}
}
@@ -9273,6 +9393,7 @@ void LLVOAvatar::releaseComponentTextures()
{
const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture];
setTETexture(te, IMG_DEFAULT_AVATAR);
+ markBodyPartsComplexityDirty();
}
}
}
@@ -10158,6 +10279,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( bool success, LLViewerFetchedTexture
LL_INFOS() << "unexpected image id: " << id << LL_ENDL;
}
self->dirtyMesh();
+ self->markBodyPartsComplexityDirty();
}
else
{
@@ -10190,6 +10312,10 @@ void LLVOAvatar::onInitialBakedTextureLoaded( bool success, LLViewerFetchedTextu
}
if (final || !success )
{
+ if (selfp)
+ {
+ selfp->markBodyPartsComplexityDirty();
+ }
delete avatar_idp;
}
}
@@ -10212,6 +10338,7 @@ void LLVOAvatar::onBakedTextureLoaded(bool success,
if (selfp && !success)
{
selfp->removeMissingBakedTextures();
+ selfp->markBodyPartsComplexityDirty();
}
if( final || !success )
@@ -10222,6 +10349,7 @@ void LLVOAvatar::onBakedTextureLoaded(bool success,
if( selfp && success && final )
{
selfp->useBakedTexture( id );
+ selfp->markBodyPartsComplexityDirty();
}
}
@@ -11172,10 +11300,384 @@ void LLVOAvatar::idleUpdateDebugInfo()
void LLVOAvatar::updateVisualComplexity()
{
LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL;
- // Set the cache time to in the past so it's updated ASAP
+ // Trigger cache recalculation on next idle update.
+ // Will recalculate stale, missing data and control avatar.
mVisualComplexityStale = true;
}
+void LLVOAvatar::calculateAttachmentComplexity(LLViewerObject* attached_object,
+ const F32 max_attachment_complexity,
+ ComplexityComponent& cache)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ cache.reset();
+
+ if (!attached_object
+ || attached_object->isDead())
+ {
+ return;
+ }
+
+ accountRenderComplexityForObject(
+ attached_object,
+ max_attachment_complexity,
+ cache.textures,
+ cache.render_cost,
+ cache.triangle_count,
+ cache.est_triangle_count,
+ cache.surface_area,
+ cache.hud_complexity,
+ cache.object_complexity
+ );
+
+ cache.last_update_time = LLFrameTimer::getTotalSeconds();
+ cache.needs_update = false;
+}
+
+void LLVOAvatar::calculateBodyPartsComplexity(ComplexityComponent& cache)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ cache.reset();
+
+ // Body parts have a fixed cost
+ // This represents the base avatar mesh (eyes, hair, shape, skin, etc.)
+ cache.render_cost = calculateBodyPartsComplexity();
+
+ // For more accurate body part complexity, could enumerate mesh LODs here
+ // For now, using a constant cost as in the original implementation
+
+ cache.last_update_time = LLFrameTimer::getTotalSeconds();
+ cache.needs_update = false;
+}
+
+bool LLVOAvatar::shouldUpdateComplexityComponent(const ComplexityComponent& component) const
+{
+ if (component.needs_update)
+ {
+ return true;
+ }
+
+ constexpr F32 CACHE_LIFETIME_SECONDS = 30.0; // Todo: should be indefinite, until something actually changes
+ F64 current_time = LLFrameTimer::getTotalSeconds();
+ return (current_time - component.last_update_time) > CACHE_LIFETIME_SECONDS;
+}
+
+bool LLVOAvatar::calculateControlAvatarComplexity(ComplexityComponent& cache, const F32 max_attachment_complexity)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ cache.reset();
+
+ if (!isControlAvatar())
+ {
+ return false;
+ }
+
+ LLControlAvatar* control_av = dynamic_cast<LLControlAvatar*>(this);
+ if (!control_av)
+ {
+ return false;
+ }
+
+ LLVOVolume* volp = control_av->mRootVolp;
+ if (!volp || volp->isAttachment())
+ {
+ return false;
+ }
+
+ accountRenderComplexityForObject(
+ volp,
+ max_attachment_complexity,
+ cache.textures,
+ cache.render_cost,
+ cache.triangle_count,
+ cache.est_triangle_count,
+ cache.surface_area,
+ cache.hud_complexity,
+ cache.object_complexity
+ );
+
+ // todo: store 'expires' time instead or make it indefinite?
+ cache.last_update_time = LLFrameTimer::getTotalSeconds();
+ cache.needs_update = false;
+
+ return true;
+}
+
+void LLVOAvatar::accumulateComplexityComponent(const ComplexityComponent& component,
+ U32& total_cost,
+ hud_complexity_list_t& hud_list,
+ object_complexity_list_t& object_list)
+{
+ total_cost += component.render_cost;
+ mAttachmentSurfaceArea += component.surface_area;
+ mAttachmentVisibleTriangleCount += component.triangle_count;
+ mAttachmentEstTriangleCount += component.est_triangle_count;
+
+ // Add HUD/object complexity info if present
+ if (component.hud_complexity.objectId.notNull())
+ {
+ hud_list.push_back(component.hud_complexity);
+ }
+ if (component.object_complexity.objectId.notNull())
+ {
+ object_list.push_back(component.object_complexity);
+ }
+}
+
+void LLVOAvatar::markAttachmentComplexityDirty(const LLUUID& object_id, bool force_reset_attachment)
+{
+ // Mark the cache entry if it exists
+ complexity_cache_map_t::iterator it = mComplexityCache.find(object_id);
+ if (it != mComplexityCache.end())
+ {
+ if (force_reset_attachment)
+ {
+ // Object was detached.
+ // Force reset it in case it lingers in gObjectList for some reason (ex: dropped to world).
+ it->second.reset();
+ }
+ it->second.needs_update = true;
+ }
+
+ // Launch update process if not already scheduled
+ // It will add any missing attachments.
+ mVisualComplexityStale = true;
+}
+
+void LLVOAvatar::markBodyPartsComplexityDirty()
+{
+ mBodyPartsComplexity.needs_update = true;
+
+ // Launch update process if not already scheduled
+ mVisualComplexityStale = true;
+}
+
+void LLVOAvatar::performPartialComplexityUpdate(const F32 max_attachment_complexity)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ // Update any attachments marked as dirty
+ // Todo: might want to limit time or count here and defer the rest
+ // till next run. In such a case will need to make sure
+ // mVisualComplexityStale remains true.
+
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment || !attachment->getValid())
+ {
+ continue;
+ }
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isDead())
+ {
+ LLUUID object_id = attached_object->getID();
+ ComplexityComponent& cache = mComplexityCache[object_id];
+
+ // Update if cache is stale or a new entry.
+ if (shouldUpdateComplexityComponent(cache))
+ {
+ calculateAttachmentComplexity(attached_object, max_attachment_complexity, cache);
+ }
+ }
+ }
+ }
+
+ // Update body parts if stale
+ if (shouldUpdateComplexityComponent(mBodyPartsComplexity))
+ {
+ calculateBodyPartsComplexity(mBodyPartsComplexity);
+ }
+}
+
+// Calculations for mVisualComplexity value
+// Call rate is flexible, can be once in 20, can be once in 200 frames,
+// depends on priority and known cost of an avatar in question.
+void LLVOAvatar::calculateUpdateRenderComplexity()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ // ****************************************************************
+ // This calculation should not be modified by third party viewers,
+ // since it is used to limit rendering and should be uniform for
+ // everyone. If you have suggested improvements, submit them to
+ // the official viewer for consideration.
+ // ****************************************************************
+
+ if (!mVisualComplexityStale)
+ {
+ return;
+ }
+
+ // Get the attachment complexity limit
+ static LLCachedControl<F32> max_complexity_setting(gSavedSettings, "MaxAttachmentComplexity");
+ F32 max_attachment_complexity = max_complexity_setting;
+ max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);
+
+ // Update complexity for any dirty attachments or body parts.
+ //
+ // Todo: Limit this by time or count and continue later as
+ // doing everything in one go can be very expensive (multiple ms)
+ // Note that calculateUpdateRenderComplexity() can be launched once
+ // per 200 frames. Limiting it by time or count runs the risk of
+ // already checked attachments getting stale on last_update_time,
+ // thus function will keep running indefinetely.
+ performPartialComplexityUpdate(max_attachment_complexity);
+
+ // Reset per-run counters
+ mAttachmentSurfaceArea = 0.f;
+ mAttachmentVisibleTriangleCount = 0;
+ mAttachmentEstTriangleCount = 0.f;
+
+ U32 total_cost = 0;
+ hud_complexity_list_t hud_complexity_list;
+ object_complexity_list_t object_complexity_list;
+
+ // Calculate and accumulate control avatar complexity if applicable
+ // For now this is on each run.
+ // Todo: See if mControlAvatarComplexity.needs_update is applicable here.
+ if (calculateControlAvatarComplexity(mControlAvatarComplexity, max_attachment_complexity))
+ {
+ accumulateComplexityComponent(
+ mControlAvatarComplexity,
+ total_cost,
+ hud_complexity_list,
+ object_complexity_list);
+ }
+
+ // Accumulate body parts complexity
+ accumulateComplexityComponent(mBodyPartsComplexity, total_cost, hud_complexity_list, object_complexity_list);
+
+ // Accumulate all attachment complexity from cache
+ // Clean up cache entries for attachments that no longer exist
+ std::vector<LLUUID> to_remove;
+
+ for (complexity_cache_map_t::iterator cache_iter = mComplexityCache.begin();
+ cache_iter != mComplexityCache.end(); ++cache_iter)
+ {
+ const LLUUID& object_id = cache_iter->first;
+
+ // Verify object still exists
+ LLViewerObject* obj = gObjectList.findObject(object_id);
+ if (!obj
+ || obj->isDead()
+ || !obj->isAttachment())
+ {
+ to_remove.push_back(object_id);
+ continue;
+ }
+
+ // Accumulate this attachment's complexity
+ accumulateComplexityComponent(cache_iter->second, total_cost,
+ hud_complexity_list, object_complexity_list);
+ }
+
+ // Remove stale cache entries
+ for (std::vector<LLUUID>::iterator it = to_remove.begin(); it != to_remove.end(); ++it)
+ {
+ mComplexityCache.erase(*it);
+ }
+
+ if (total_cost != mVisualComplexity)
+ {
+ LL_DEBUGS("AvatarRender") << "Avatar " << getID()
+ << " complexity updated was " << mVisualComplexity << " now " << total_cost
+ << " reported " << mReportedVisualComplexity
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("AvatarRender") << "Avatar " << getID()
+ << " complexity updated no change " << mVisualComplexity
+ << " reported " << mReportedVisualComplexity
+ << LL_ENDL;
+ }
+
+ // Store results
+ mVisualComplexity = total_cost;
+
+ // Call the reporting function with the aggregated lists
+ processComplexityCostChange(hud_complexity_list, object_complexity_list);
+
+ // Stop processing until something changes
+ mVisualComplexityStale = false;
+}
+
+U32 LLVOAvatar::calculateBodyPartsComplexity()
+{
+ constexpr U32 COMPLEXITY_BODY_PART_COST = 200;
+ U32 cost = 0;
+ for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
+ {
+ const LLAvatarAppearanceDictionary::BakedEntry* baked_dict
+ = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index);
+ ETextureIndex tex_index = baked_dict->mTextureIndex;
+ if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
+ {
+ // Same as isTextureVisible(), but doesn't account for isSelf to ensure identical numbers for all avatars
+ if (isIndexLocalTexture(tex_index))
+ {
+ if (isTextureDefined(tex_index, 0))
+ {
+ cost += COMPLEXITY_BODY_PART_COST;
+ }
+ }
+ else
+ {
+ // baked textures can use TE images directly
+ if (isTextureDefined(tex_index)
+ && (getTEImage(tex_index)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha))
+ {
+ cost += COMPLEXITY_BODY_PART_COST;
+ }
+ }
+ }
+ }
+ LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL;
+ return cost;
+}
+
+void LLVOAvatar::processComplexityCostChange(const hud_complexity_list_t &hud_complexity_list, const object_complexity_list_t &object_complexity_list)
+{
+ static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
+
+ if (isSelf() && show_my_complexity_changes)
+ {
+ // Avatar complexity
+ LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
+ LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
+ // HUD complexity
+ LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
+ }
+
+ //schedule an update to ART next frame if needed
+ if (LLPerfStats::tunables.userAutoTuneEnabled &&
+ LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY &&
+ !isVisuallyMuted())
+ {
+ const LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames
+ LL::WorkQueue::getInstance("mainloop")->post([id]()
+ {
+ LLViewerObject* obj = gObjectList.findObject(id);
+ if (obj
+ && !obj->isDead()
+ && obj->isAvatar()
+ && obj->mDrawable)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*)obj;
+ gPipeline.profileAvatar(avatar);
+ }
+ });
+ }
+}
// Account for the complexity of a single top-level object associated
// with an avatar. This will be either an attached object or an animated
@@ -11185,15 +11687,18 @@ void LLVOAvatar::accountRenderComplexityForObject(
const F32 max_attachment_complexity,
LLVOVolume::texture_cost_t& textures,
U32& cost,
- hud_complexity_list_t& hud_complexity_list,
- object_complexity_list_t& object_complexity_list)
+ U32& visible_triangle_count,
+ F32& est_triangle_count,
+ F32& surface_area,
+ LLHUDComplexity& hud_object_complexity,
+ LLObjectComplexity& object_complexity)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
if (attached_object && !attached_object->isHUDAttachment())
{
- mAttachmentVisibleTriangleCount += attached_object->recursiveGetTriangleCount();
- mAttachmentEstTriangleCount += attached_object->recursiveGetEstTrianglesMax();
- mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea();
+ visible_triangle_count += attached_object->recursiveGetTriangleCount();
+ est_triangle_count += attached_object->recursiveGetEstTrianglesMax();
+ surface_area += attached_object->recursiveGetScaledSurfaceArea();
textures.clear();
const LLDrawable* drawable = attached_object->mDrawable;
@@ -11248,11 +11753,9 @@ void LLVOAvatar::accountRenderComplexityForObject(
if (isSelf())
{
- LLObjectComplexity object_complexity;
object_complexity.objectName = attached_object->getAttachmentItemName();
object_complexity.objectId = attached_object->getAttachmentItemID();
object_complexity.objectCost = (U32)attachment_total_cost;
- object_complexity_list.push_back(object_complexity);
}
}
}
@@ -11264,13 +11767,12 @@ void LLVOAvatar::accountRenderComplexityForObject(
&& attached_object->mDrawable)
{
textures.clear();
- mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea();
+ surface_area += attached_object->recursiveGetScaledSurfaceArea();
const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
if (volume)
{
bool is_rigged_mesh = volume->isRiggedMeshFast();
- LLHUDComplexity hud_object_complexity;
hud_object_complexity.objectName = attached_object->getAttachmentItemName();
hud_object_complexity.objectId = attached_object->getAttachmentItemID();
std::string joint_name;
@@ -11325,140 +11827,6 @@ void LLVOAvatar::accountRenderComplexityForObject(
}
}
}
- hud_complexity_list.push_back(hud_object_complexity);
- }
- }
-}
-
-// Calculations for mVisualComplexity value
-void LLVOAvatar::calculateUpdateRenderComplexity()
-{
- /*****************************************************************
- * This calculation should not be modified by third party viewers,
- * since it is used to limit rendering and should be uniform for
- * everyone. If you have suggested improvements, submit them to
- * the official viewer for consideration.
- *****************************************************************/
- if (mVisualComplexityStale)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
-
- static const U32 COMPLEXITY_BODY_PART_COST = 200;
- static LLCachedControl<F32> max_complexity_setting(gSavedSettings, "MaxAttachmentComplexity");
- F32 max_attachment_complexity = max_complexity_setting;
- max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);
-
- // Diagnostic list of all textures on our avatar
- static std::unordered_set<const LLViewerTexture*> all_textures;
-
- U32 cost = VISUAL_COMPLEXITY_UNKNOWN;
- LLVOVolume::texture_cost_t textures;
- hud_complexity_list_t hud_complexity_list;
- object_complexity_list_t object_complexity_list;
-
- for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
- {
- const LLAvatarAppearanceDictionary::BakedEntry *baked_dict
- = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index);
- ETextureIndex tex_index = baked_dict->mTextureIndex;
- if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
- {
- // Same as isTextureVisible(), but doesn't account for isSelf to ensure identical numbers for all avatars
- if (isIndexLocalTexture(tex_index))
- {
- if (isTextureDefined(tex_index, 0))
- {
- cost += COMPLEXITY_BODY_PART_COST;
- }
- }
- else
- {
- // baked textures can use TE images directly
- if (isTextureDefined(tex_index)
- && (getTEImage(tex_index)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha))
- {
- cost += COMPLEXITY_BODY_PART_COST;
- }
- }
- }
- }
- LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL;
-
- mAttachmentVisibleTriangleCount = 0;
- mAttachmentEstTriangleCount = 0.f;
- mAttachmentSurfaceArea = 0.f;
-
- // A standalone animated object needs to be accounted for
- // using its associated volume. Attached animated objects
- // will be covered by the subsequent loop over attachments.
- LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
- if (control_av)
- {
- LLVOVolume *volp = control_av->mRootVolp;
- if (volp && !volp->isAttachment())
- {
- accountRenderComplexityForObject(volp, max_attachment_complexity,
- textures, cost, hud_complexity_list, object_complexity_list);
- }
- }
-
- // Account for complexity of all attachments.
- for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin();
- attachment_point != mAttachmentPoints.end();
- ++attachment_point)
- {
- LLViewerJointAttachment* attachment = attachment_point->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- LLViewerObject* attached_object = attachment_iter->get();
- accountRenderComplexityForObject(attached_object, max_attachment_complexity,
- textures, cost, hud_complexity_list, object_complexity_list);
- }
- }
-
- if ( cost != mVisualComplexity )
- {
- LL_DEBUGS("AvatarRender") << "Avatar "<< getID()
- << " complexity updated was " << mVisualComplexity << " now " << cost
- << " reported " << mReportedVisualComplexity
- << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("AvatarRender") << "Avatar "<< getID()
- << " complexity updated no change " << mVisualComplexity
- << " reported " << mReportedVisualComplexity
- << LL_ENDL;
- }
- mVisualComplexity = cost;
- mVisualComplexityStale = false;
-
- static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
-
- if (isSelf() && show_my_complexity_changes)
- {
- // Avatar complexity
- LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
- LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
- // HUD complexity
- LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
- }
-
- //schedule an update to ART next frame if needed
- if (LLPerfStats::tunables.userAutoTuneEnabled &&
- LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY &&
- !isVisuallyMuted())
- {
- LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames
- LL::WorkQueue::getInstance("mainloop")->post([this, id]()
- {
- if (gObjectList.findObject(id) != nullptr)
- {
- gPipeline.profileAvatar(this);
- }
- });
}
}
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 1e563c4869..cc2a083794 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -36,6 +36,7 @@
#include <boost/signals2/trackable.hpp>
#include "llavatarappearance.h"
+#include "llavatarpropertiesprocessor.h" // LLAvatarPropertiesObserver (group tinting)
#include "llchat.h"
#include "lldrawpoolalpha.h"
#include "llviewerobject.h"
@@ -87,6 +88,7 @@ extern U32 gFrameCount;
class LLVOAvatar :
public LLAvatarAppearance,
public LLViewerObject,
+ public LLAvatarPropertiesObserver, // group-based nameplate tinting
public boost::signals2::trackable
{
LL_ALIGN_NEW;
@@ -292,6 +294,11 @@ public:
void idleUpdateNameTagAlpha(bool new_name, F32 alpha);
LLColor4 getNameTagColor(bool is_friend);
void clearNameTag();
+
+ // LLAvatarPropertiesObserver: receives APT_GROUPS reply for group-tint lookup
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) override;
+ void sendAvatarGroupsRequest();
+ const LLUUID& getActiveGroupID() const { return mActiveGroupID; }
static void invalidateNameTag(const LLUUID& agent_id);
// force all name tags to rebuild, useful when display names turned on/off
static void invalidateNameTags();
@@ -302,11 +309,17 @@ public:
const F32 max_attachment_complexity,
LLVOVolume::texture_cost_t& textures,
U32& cost,
- hud_complexity_list_t& hud_complexity_list,
- object_complexity_list_t& object_complexity_list);
+ U32& visible_triangle_count,
+ F32& est_triangle_count,
+ F32& surface_area,
+ LLHUDComplexity& hud_object_complexity,
+ LLObjectComplexity& object_complexity);
void calculateUpdateRenderComplexity();
static const U32 VISUAL_COMPLEXITY_UNKNOWN;
void updateVisualComplexity();
+ // Mark that an attachment needs complexity recalculation
+ void markAttachmentComplexityDirty(const LLUUID& object_id, bool force_reset_attachment = false);
+ void markBodyPartsComplexityDirty();
void placeProfileQuery();
void readProfileQuery(S32 retries);
@@ -354,7 +367,7 @@ public:
//--------------------------------------------------------------------
public:
static S32 sRenderName;
- static bool sRenderGroupTitles;
+ static S32 sRenderGroupTitles;
static const U32 NON_IMPOSTORS_MAX_SLIDER; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
* slider in panel_preferences_graphics1.xml */
static U32 sMaxNonImpostors; // affected by control "RenderAvatarMaxNonImpostors"
@@ -581,12 +594,6 @@ private:
// CPU render time in ms
F32 mCPURenderTime = 0.f;
- // the isTooComplex method uses these mutable values to avoid recalculating too frequently
- // DEPRECATED -- obsolete avatar render cost values
- mutable U32 mVisualComplexity;
- mutable bool mVisualComplexityStale;
- U32 mReportedVisualComplexity; // from other viewers through the simulator
-
mutable bool mCachedInMuteList;
mutable F64 mCachedMuteListUpdateTime;
mutable bool mCachedInBuddyList = false;
@@ -595,6 +602,81 @@ private:
VisualMuteSettings mVisuallyMuteSetting; // Always or never visually mute this AV
//--------------------------------------------------------------------
+ // Complexity calculation and caching
+ //--------------------------------------------------------------------
+
+private:
+ // Structure to cache complexity metrics for individual attachments or components
+ struct ComplexityComponent
+ {
+ U32 render_cost;
+ U32 triangle_count;
+ F32 surface_area;
+ F32 est_triangle_count;
+ LLVOVolume::texture_cost_t textures;
+ F64 last_update_time;
+ bool needs_update;
+
+ // For tracking HUD and object lists
+ LLHUDComplexity hud_complexity;
+ LLObjectComplexity object_complexity;
+
+ ComplexityComponent()
+ : render_cost(0)
+ , triangle_count(0)
+ , surface_area(0.f)
+ , est_triangle_count(0.f)
+ , last_update_time(0.0)
+ , needs_update(true)
+ {
+ }
+
+ void reset()
+ {
+ render_cost = 0;
+ triangle_count = 0;
+ surface_area = 0.f;
+ est_triangle_count = 0.f;
+ textures.clear();
+ hud_complexity.reset();
+ object_complexity.reset();
+ needs_update = true;
+ }
+ };
+
+ void calculateAttachmentComplexity(LLViewerObject* attached_object,
+ const F32 max_attachment_complexity,
+ ComplexityComponent& cache);
+ void calculateBodyPartsComplexity(ComplexityComponent& cache);
+ U32 calculateBodyPartsComplexity();
+
+ // return true, if a valid control avatar.
+ bool calculateControlAvatarComplexity(ComplexityComponent& cache, const F32 max_attachment_complexity);
+
+ void accumulateComplexityComponent(const ComplexityComponent& component,
+ U32& total_cost,
+ hud_complexity_list_t& hud_list,
+ object_complexity_list_t& object_list);
+
+ bool shouldUpdateComplexityComponent(const ComplexityComponent& component) const;
+ void performPartialComplexityUpdate(const F32 max_attachment_complexity);
+
+ void processComplexityCostChange(const hud_complexity_list_t &hud_complexity_list, const object_complexity_list_t &object_complexity_list);
+
+ // Todo: probably safe to store by local instead of global id
+ // since they should be unique to this avatar, but local id might be not known.
+ typedef std::map<LLUUID, ComplexityComponent> complexity_cache_map_t;
+ complexity_cache_map_t mComplexityCache; // Cache per-attachment complexity
+ ComplexityComponent mBodyPartsComplexity; // Cache for body parts (mesh, eyes, hair, etc)
+ ComplexityComponent mControlAvatarComplexity; // Cache for animated object control avatar
+
+ // the isTooComplex method uses these mutable values to avoid recalculating too frequently
+ // DEPRECATED -- obsolete avatar render cost values
+ mutable U32 mVisualComplexity;
+ mutable bool mVisualComplexityStale;
+ U32 mReportedVisualComplexity; // from other viewers through the simulator
+
+ //--------------------------------------------------------------------
// animated object status
//--------------------------------------------------------------------
public:
@@ -630,7 +712,6 @@ private:
// Shadowing
//--------------------------------------------------------------------
public:
- void updateShadowFaces();
LLDrawable* mShadow;
private:
LLFace* mShadow0Facep;
@@ -1120,7 +1201,11 @@ private:
bool mNameFriend;
bool mNameCloud;
F32 mNameAlpha;
- bool mRenderGroupTitles;
+ S32 mRenderGroupTitles;
+
+ // Group-based nameplate tinting
+ LLUUID mActiveGroupID; // active group UUID; null until known
+ bool mGroupFetchPending; // true while AvatarPropertiesRequest is in flight
//--------------------------------------------------------------------
// Display the name (then optionally fade it out)
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 5d456b1a19..e513a3813f 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -32,6 +32,7 @@
#include "lldrawable.h"
#include "llviewerregion.h"
#include "llagentcamera.h"
+#include "llmemory.h"
#include "llsdserialize.h"
#include "llworld.h" // For LLWorld::getInstance()
//static variables
@@ -488,11 +489,12 @@ void LLVOCacheEntry::updateDebugSettings()
static const F32 MIN_RADIUS = 1.0f;
F32 draw_radius = gAgentCamera.mDrawDistance;
- if (LLViewerTexture::isSystemMemoryCritical())
+ const F32 mem_factor = LLMemory::getSystemMemoryBudgetFactor();
+ if (mem_factor > 1.f)
{
// Factor is intended to go from 1.0 to 2.0
// For safety cap reduction at 50%, we don't want to go below half of draw distance
- draw_radius = llmax(draw_radius / LLViewerTexture::getSystemMemoryBudgetFactor(), draw_radius / 2.f);
+ draw_radius = llmax(draw_radius / mem_factor, draw_radius / 2.f);
}
const F32 clamped_min_radius = llclamp((F32) min_radius, MIN_RADIUS, draw_radius); // [1, mDrawDistance]
sNearRadius = MIN_RADIUS + ((clamped_min_radius - MIN_RADIUS) * adjust_factor);
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index b941d356a1..0852258994 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -472,10 +472,6 @@ void LLVoiceChannelGroup::activate()
}
}
}
-
- // Mic default state is OFF on initiating/joining Ad-Hoc/Group calls. It's on for P2P using the AdHoc infra.
-
- LLVoiceClient::getInstance()->setUserPTTState(mIsP2P);
}
}
@@ -534,6 +530,10 @@ void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
case STATUS_JOINED:
mRetries = 3;
mIsRetrying = false;
+
+ // Mic default state is OFF on initiating/joining Ad-Hoc/Group calls. It's on for P2P using the AdHoc infra.
+ LLVoiceClient::getInstance()->setUserPTTState(mIsP2P);
+ break;
default:
break;
}
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 7f7d9342e0..95b6bb4227 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -25,8 +25,10 @@
*/
#include "llvoiceclient.h"
-#include "llvoicevivox.h"
-#if USE_WEBRTC
+#if __FreeBSD__ || _M_ARM64
+#include "llviewerregion.h"
+#include "llmutelist.h"
+#else
#include "llvoicewebrtc.h"
#endif
#include "llviewernetwork.h"
@@ -41,6 +43,7 @@
#include "llagent.h"
#include "lltrans.h"
#include "lluiusage.h"
+#include "llnearbyvoicemoderation.h"
const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
@@ -118,17 +121,13 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv
LLVoiceModuleInterface *getVoiceModule(const std::string &voice_server_type)
{
- if (voice_server_type == VIVOX_VOICE_SERVER_TYPE || voice_server_type.empty())
- {
- return (LLVoiceModuleInterface *) LLVivoxVoiceClient::getInstance();
- }
-#if USE_WEBRTC
- else if (voice_server_type == WEBRTC_VOICE_SERVER_TYPE)
+#if !__FreeBSD__ && !_M_ARM64
+ if (voice_server_type == WEBRTC_VOICE_SERVER_TYPE)
{
return (LLVoiceModuleInterface *) LLWebRTCVoiceClient::getInstance();
}
-#endif
else
+#endif
{
LLNotificationsUtil::add("VoiceVersionMismatch");
return nullptr;
@@ -169,10 +168,9 @@ void LLVoiceClient::init(LLPumpIO *pump)
{
// Initialize all of the voice modules
m_servicePump = pump;
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->init(pump);
#endif
- LLVivoxVoiceClient::getInstance()->init(pump);
}
void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID)
@@ -182,19 +180,20 @@ void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &age
mRegionChangedCallbackSlot.disconnect();
}
mRegionChangedCallbackSlot = gAgent.addRegionChangedCallback(boost::bind(&LLVoiceClient::onRegionChanged, this));
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->userAuthorized(user_id, agentID);
#endif
- LLVivoxVoiceClient::getInstance()->userAuthorized(user_id, agentID);
}
void LLVoiceClient::handleSimulatorFeaturesReceived(const LLSD &simulatorFeatures)
{
std::string voiceServerType = simulatorFeatures["VoiceServerType"].asString();
+#if !__FreeBSD__ && !_M_ARM64
if (voiceServerType.empty())
{
- voiceServerType = VIVOX_VOICE_SERVER_TYPE;
+ voiceServerType = WEBRTC_VOICE_SERVER_TYPE;
}
+#endif
if (mSpatialVoiceModule && !mNonSpatialVoiceModule)
{
@@ -294,24 +293,19 @@ void LLVoiceClient::setNonSpatialVoiceModule(const std::string &voice_server_typ
void LLVoiceClient::setHidden(bool hidden)
{
LL_INFOS("Voice") << "( " << (hidden ? "true" : "false") << " )" << LL_ENDL;
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setHidden(hidden);
#endif
- LLVivoxVoiceClient::getInstance()->setHidden(hidden);
}
void LLVoiceClient::terminate()
{
-#if USE_WEBRTC
- if (LLVivoxVoiceClient::instanceExists())
+#if !__FreeBSD__ && !_M_ARM64
+ if (LLWebRTCVoiceClient::instanceExists())
{
LLWebRTCVoiceClient::getInstance()->terminate();
}
#endif
- if (LLVivoxVoiceClient::instanceExists())
- {
- LLVivoxVoiceClient::getInstance()->terminate();
- }
mSpatialVoiceModule = NULL;
m_servicePump = NULL;
@@ -346,10 +340,9 @@ void LLVoiceClient::updateSettings()
updateMicMuteLogic();
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->updateSettings();
#endif
- LLVivoxVoiceClient::getInstance()->updateSettings();
}
//--------------------------------------------------
@@ -357,53 +350,47 @@ void LLVoiceClient::updateSettings()
void LLVoiceClient::tuningStart()
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->tuningStart();
#endif
- LLVivoxVoiceClient::getInstance()->tuningStart();
}
void LLVoiceClient::tuningStop()
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->tuningStop();
#endif
- LLVivoxVoiceClient::getInstance()->tuningStop();
}
bool LLVoiceClient::inTuningMode()
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->inTuningMode();
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return LLVivoxVoiceClient::getInstance()->inTuningMode();
+ return LLWebRTCVoiceClient::getInstance()->inTuningMode();
#endif
}
void LLVoiceClient::tuningSetMicVolume(float volume)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->tuningSetMicVolume(volume);
-#else
- LLVivoxVoiceClient::getInstance()->tuningSetMicVolume(volume);
#endif
}
void LLVoiceClient::tuningSetSpeakerVolume(float volume)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->tuningSetSpeakerVolume(volume);
-#else
- LLVivoxVoiceClient::getInstance()->tuningSetSpeakerVolume(volume);
#endif
}
float LLVoiceClient::tuningGetEnergy(void)
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->tuningGetEnergy();
+#if __FreeBSD__ || _M_ARM64
+ return 0.0f;
#else
- return LLVivoxVoiceClient::getInstance()->tuningGetEnergy();
+ return LLWebRTCVoiceClient::getInstance()->tuningGetEnergy();
#endif
}
@@ -412,63 +399,61 @@ float LLVoiceClient::tuningGetEnergy(void)
bool LLVoiceClient::deviceSettingsAvailable()
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->deviceSettingsAvailable();
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return LLVivoxVoiceClient::getInstance()->deviceSettingsAvailable();
+ return LLWebRTCVoiceClient::getInstance()->deviceSettingsAvailable();
#endif
}
bool LLVoiceClient::deviceSettingsUpdated()
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->deviceSettingsUpdated();
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return LLVivoxVoiceClient::getInstance()->deviceSettingsUpdated();
+ return LLWebRTCVoiceClient::getInstance()->deviceSettingsUpdated();
#endif
}
void LLVoiceClient::refreshDeviceLists(bool clearCurrentList)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->refreshDeviceLists(clearCurrentList);
-#else
- LLVivoxVoiceClient::getInstance()->refreshDeviceLists(clearCurrentList);
#endif
}
void LLVoiceClient::setCaptureDevice(const std::string& name)
{
- LLVivoxVoiceClient::getInstance()->setCaptureDevice(name);
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setCaptureDevice(name);
#endif
}
void LLVoiceClient::setRenderDevice(const std::string& name)
{
- LLVivoxVoiceClient::getInstance()->setRenderDevice(name);
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setRenderDevice(name);
#endif
}
const LLVoiceDeviceList& LLVoiceClient::getCaptureDevices()
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->getCaptureDevices();
+#if __FreeBSD__ || _M_ARM64
+ static LLVoiceDeviceList devices;
+ return devices;
#else
- return LLVivoxVoiceClient::getInstance()->getCaptureDevices();
+ return LLWebRTCVoiceClient::getInstance()->getCaptureDevices();
#endif
}
const LLVoiceDeviceList& LLVoiceClient::getRenderDevices()
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->getRenderDevices();
+#if __FreeBSD__ || _M_ARM64
+ static LLVoiceDeviceList devices;
+ return devices;
#else
- return LLVivoxVoiceClient::getInstance()->getRenderDevices();
+ return LLWebRTCVoiceClient::getInstance()->getRenderDevices();
#endif
}
@@ -478,20 +463,18 @@ const LLVoiceDeviceList& LLVoiceClient::getRenderDevices()
void LLVoiceClient::getParticipantList(std::set<LLUUID> &participants) const
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->getParticipantList(participants);
#endif
- LLVivoxVoiceClient::getInstance()->getParticipantList(participants);
}
bool LLVoiceClient::isParticipant(const LLUUID &speaker_id) const
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->isParticipant(speaker_id) ||
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return
+ return LLWebRTCVoiceClient::getInstance()->isParticipant(speaker_id);
#endif
- LLVivoxVoiceClient::getInstance()->isParticipant(speaker_id);
}
@@ -583,22 +566,20 @@ void LLVoiceClient::activateSpatialChannel(bool activate)
bool LLVoiceClient::isCurrentChannel(const LLSD& channelInfo)
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->isCurrentChannel(channelInfo) ||
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return
+ return LLWebRTCVoiceClient::getInstance()->isCurrentChannel(channelInfo);
#endif
- LLVivoxVoiceClient::getInstance()->isCurrentChannel(channelInfo);
}
bool LLVoiceClient::compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2)
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2) ||
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return
+ return LLWebRTCVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2);
#endif
- LLVivoxVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2);
}
LLVoiceP2PIncomingCallInterfacePtr LLVoiceClient::getIncomingCallInterface(const LLSD& voice_call_info)
@@ -623,12 +604,14 @@ LLVoiceP2POutgoingCallInterface *LLVoiceClient::getOutgoingCallInterface(const L
LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion();
voice_server_type = versionInfo.internalVoiceServerType;
}
+#if !__FreeBSD__ && !_M_ARM64
if (voiceChannelInfo.has("voice_server_type") && voiceChannelInfo["voice_server_type"] != voice_server_type)
{
// there's a mismatch between what the peer is offering and what our server
- // can handle, so downgrade to vivox
- voice_server_type = VIVOX_VOICE_SERVER_TYPE;
+ // can handle, so default to webrtc
+ voice_server_type = WEBRTC_VOICE_SERVER_TYPE;
}
+#endif
LLVoiceModuleInterface *module = getVoiceModule(voice_server_type);
return dynamic_cast<LLVoiceP2POutgoingCallInterface *>(module);
}
@@ -639,18 +622,16 @@ LLVoiceP2POutgoingCallInterface *LLVoiceClient::getOutgoingCallInterface(const L
void LLVoiceClient::setVoiceVolume(F32 volume)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setVoiceVolume(volume);
#endif
- LLVivoxVoiceClient::getInstance()->setVoiceVolume(volume);
}
void LLVoiceClient::setMicGain(F32 gain)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setMicGain(gain);
#endif
- LLVivoxVoiceClient::getInstance()->setMicGain(gain);
}
@@ -696,16 +677,12 @@ bool LLVoiceClient::voiceEnabled()
void LLVoiceClient::setVoiceEnabled(bool enabled)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
if (LLWebRTCVoiceClient::instanceExists())
{
LLWebRTCVoiceClient::getInstance()->setVoiceEnabled(enabled);
}
#endif
- if (LLVivoxVoiceClient::instanceExists())
- {
- LLVivoxVoiceClient::getInstance()->setVoiceEnabled(enabled);
- }
}
void LLVoiceClient::updateMicMuteLogic()
@@ -724,10 +701,9 @@ void LLVoiceClient::updateMicMuteLogic()
// Either of these always overrides any other PTT setting.
new_mic_mute = true;
}
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setMuteMic(new_mic_mute);
#endif
- LLVivoxVoiceClient::getInstance()->setMuteMic(new_mic_mute);
}
void LLVoiceClient::setMuteMic(bool muted)
@@ -748,6 +724,9 @@ void LLVoiceClient::setUserPTTState(bool ptt)
{
if (ptt)
{
+ // Nearby chat is muted by moderator, don't toggle PTT
+ if (!mUserPTTState && LLNearbyVoiceModeration::getInstance()->showNotificationIfNeeded())
+ return;
LLUIUsage::instance().logCommand("Agent.EnableMicrophone");
}
mUserPTTState = ptt;
@@ -821,25 +800,20 @@ bool LLVoiceClient::getVoiceEnabled(const LLUUID& id) const
std::string LLVoiceClient::getDisplayName(const LLUUID& id) const
{
-#if USE_WEBRTC
- std::string result = LLWebRTCVoiceClient::getInstance()->getDisplayName(id);
- if (result.empty())
- {
- result = LLVivoxVoiceClient::getInstance()->getDisplayName(id);
- }
- return result;
+#if __FreeBSD__ || _M_ARM64
+ std::string result;
#else
- return LLVivoxVoiceClient::getInstance()->getDisplayName(id);
+ std::string result = LLWebRTCVoiceClient::getInstance()->getDisplayName(id);
#endif
+ return result;
}
bool LLVoiceClient::isVoiceWorking() const
{
-#if USE_WEBRTC
- return LLVivoxVoiceClient::getInstance()->isVoiceWorking() ||
- LLWebRTCVoiceClient::getInstance()->isVoiceWorking();
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return LLVivoxVoiceClient::getInstance()->isVoiceWorking();
+ return LLWebRTCVoiceClient::getInstance()->isVoiceWorking();
#endif
}
@@ -855,33 +829,30 @@ bool LLVoiceClient::isOnlineSIP(const LLUUID& id)
bool LLVoiceClient::getIsSpeaking(const LLUUID& id)
{
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->getIsSpeaking(id) ||
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return
+ return LLWebRTCVoiceClient::getInstance()->getIsSpeaking(id);
#endif
- LLVivoxVoiceClient::getInstance()->getIsSpeaking(id);
}
bool LLVoiceClient::getIsModeratorMuted(const LLUUID& id)
{
// don't bother worrying about p2p calls, as
// p2p calls don't have mute.
-#if USE_WEBRTC
- return LLWebRTCVoiceClient::getInstance()->getIsModeratorMuted(id) ||
+#if __FreeBSD__ || _M_ARM64
+ return false;
#else
- return
+ return LLWebRTCVoiceClient::getInstance()->getIsModeratorMuted(id);
#endif
- LLVivoxVoiceClient::getInstance()->getIsModeratorMuted(id);
}
F32 LLVoiceClient::getCurrentPower(const LLUUID& id)
{
-#if USE_WEBRTC
- return std::fmax(LLVivoxVoiceClient::getInstance()->getCurrentPower(id),
- LLWebRTCVoiceClient::getInstance()->getCurrentPower(id));
+#if __FreeBSD__ || _M_ARM64
+ return 0.0f;
#else
- return LLVivoxVoiceClient::getInstance()->getCurrentPower(id);
+ return LLWebRTCVoiceClient::getInstance()->getCurrentPower(id);
#endif
}
@@ -894,19 +865,18 @@ bool LLVoiceClient::getOnMuteList(const LLUUID& id)
F32 LLVoiceClient::getUserVolume(const LLUUID& id)
{
-#if USE_WEBRTC
- return std::fmax(LLVivoxVoiceClient::getInstance()->getUserVolume(id), LLWebRTCVoiceClient::getInstance()->getUserVolume(id));
+#if __FreeBSD__ || _M_ARM64
+ return 0.0f;
#else
- return LLVivoxVoiceClient::getInstance()->getUserVolume(id);
+ return LLWebRTCVoiceClient::getInstance()->getUserVolume(id);
#endif
}
void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
{
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->setUserVolume(id, volume);
#endif
- LLVivoxVoiceClient::getInstance()->setUserVolume(id, volume);
}
//--------------------------------------------------
@@ -914,19 +884,14 @@ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
{
- LLVivoxVoiceClient::getInstance()->addObserver(observer);
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->addObserver(observer);
#endif
}
void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
{
- if (LLVivoxVoiceClient::instanceExists())
- {
- LLVivoxVoiceClient::getInstance()->removeObserver(observer);
- }
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
if (LLWebRTCVoiceClient::instanceExists())
{
LLWebRTCVoiceClient::getInstance()->removeObserver(observer);
@@ -936,19 +901,14 @@ void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
void LLVoiceClient::addObserver(LLFriendObserver* observer)
{
- LLVivoxVoiceClient::getInstance()->addObserver(observer);
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->addObserver(observer);
#endif
}
void LLVoiceClient::removeObserver(LLFriendObserver* observer)
{
- if (LLVivoxVoiceClient::instanceExists())
- {
- LLVivoxVoiceClient::getInstance()->removeObserver(observer);
- }
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
if (LLWebRTCVoiceClient::instanceExists())
{
LLWebRTCVoiceClient::getInstance()->removeObserver(observer);
@@ -958,19 +918,14 @@ void LLVoiceClient::removeObserver(LLFriendObserver* observer)
void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
{
- LLVivoxVoiceClient::getInstance()->addObserver(observer);
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
LLWebRTCVoiceClient::getInstance()->addObserver(observer);
#endif
}
void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
{
- if (LLVivoxVoiceClient::instanceExists())
- {
- LLVivoxVoiceClient::getInstance()->removeObserver(observer);
- }
-#if USE_WEBRTC
+#if !__FreeBSD__ && !_M_ARM64
if (LLWebRTCVoiceClient::instanceExists())
{
LLWebRTCVoiceClient::getInstance()->removeObserver(observer);
@@ -978,22 +933,6 @@ void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
#endif
}
-std::string LLVoiceClient::sipURIFromID(const LLUUID &id) const
-{
- if (mNonSpatialVoiceModule)
- {
- return mNonSpatialVoiceModule->sipURIFromID(id);
- }
- else if (mSpatialVoiceModule)
- {
- return mSpatialVoiceModule->sipURIFromID(id);
- }
- else
- {
- return std::string();
- }
-}
-
LLSD LLVoiceClient::getP2PChannelInfoTemplate(const LLUUID& id) const
{
if (mNonSpatialVoiceModule)
@@ -1026,7 +965,7 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode
const LLSD& context,
const LLSD& input) const
{
- std::string voice_server_type = "vivox";
+ std::string voice_server_type = "webrtc";
if (input.has("body") && input["body"].has("voice_server_type"))
{
voice_server_type = input["body"]["voice_server_type"].asString();
@@ -1034,17 +973,13 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode
LLVoiceModuleInterface *voiceModule = NULL;
- if (voice_server_type == "vivox" || voice_server_type.empty())
- {
- voiceModule = (LLVoiceModuleInterface *) LLVivoxVoiceClient::getInstance();
- }
-#if USE_WEBRTC
- else if (voice_server_type == "webrtc")
+#if !__FreeBSD__ && !_M_ARM64
+ if (voice_server_type == "webrtc" || voice_server_type.empty())
{
voiceModule = (LLVoiceModuleInterface *) LLWebRTCVoiceClient::getInstance();
}
-#endif
else
+#endif
{
LL_WARNS("Voice") << "Unknown voice server type " << voice_server_type << LL_ENDL;
if (!sAlertedUser)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 788ea3b3b3..70bce055f9 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -106,7 +106,7 @@ struct LLVoiceVersionInfo
/// @class LLVoiceP2POutgoingCallInterface
/// @brief Outgoing call interface
///
-/// For providers that support P2P signaling (vivox)
+/// For providers that support P2P signaling
/////////////////////////////////
class LLVoiceP2POutgoingCallInterface
@@ -121,7 +121,7 @@ class LLVoiceP2POutgoingCallInterface
/// @class LLVoiceP2PIncomingCallInterface
/// @brief Incoming call interface
///
-/// For providers that support P2P signaling (vivox)
+/// For providers that support P2P signaling
/////////////////////////////////
class LLVoiceP2PIncomingCallInterface
{
@@ -180,7 +180,6 @@ public:
virtual bool deviceSettingsAvailable()=0;
virtual bool deviceSettingsUpdated() = 0;
- // Requery the vivox daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
@@ -280,7 +279,6 @@ public:
virtual void removeObserver(LLVoiceClientParticipantObserver* observer)=0;
//@}
- virtual std::string sipURIFromID(const LLUUID &id) const=0;
virtual LLSD getP2PChannelInfoTemplate(const LLUUID& id) const=0;
//@}
@@ -384,7 +382,7 @@ public:
bool deviceSettingsAvailable();
bool deviceSettingsUpdated(); // returns true when the device list has been updated recently.
- // Requery the vivox daemon for the current list of input/output devices.
+ // Requery the voice driver for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
@@ -488,7 +486,6 @@ public:
static void addObserver(LLVoiceClientParticipantObserver* observer);
static void removeObserver(LLVoiceClientParticipantObserver* observer);
- std::string sipURIFromID(const LLUUID &id) const;
LLSD getP2PChannelInfoTemplate(const LLUUID& id) const;
//////////////////////////
@@ -513,7 +510,7 @@ protected:
LLVoiceModuleInterface* mSpatialVoiceModule;
LLVoiceModuleInterface* mNonSpatialVoiceModule;
- LLSD mSpatialCredentials; // used to store spatial credentials for vivox
+ LLSD mSpatialCredentials; // used to store spatial credentials for the voice subsystem
// so they're available when the region voice
// server is retrieved.
LLPumpIO *m_servicePump;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
deleted file mode 100644
index e08bc2dfc4..0000000000
--- a/indra/newview/llvoicevivox.cpp
+++ /dev/null
@@ -1,7935 +0,0 @@
- /**
- * @file LLVivoxVoiceClient.cpp
- * @brief Implementation of LLVivoxVoiceClient class which is the interface to the voice client process.
- *
- * $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"
-#include <algorithm>
-#include "llvoicevivox.h"
-
-#include "llsdutil.h"
-
-// Linden library includes
-#include "llavatarnamecache.h"
-#include "llvoavatarself.h"
-#include "llbufferstream.h"
-#include "llfile.h"
-#include "llmenugl.h"
-#if 1
-# include "expat.h"
-#else
-# include "expat/expat.h"
-#endif
-#include "llcallbacklist.h"
-#include "llviewerregion.h"
-#include "llviewernetwork.h" // for gGridChoice
-#include "llbase64.h"
-#include "llviewercontrol.h"
-#include "llappviewer.h" // for gDisconnected, gDisableVoice
-#include "llprocess.h"
-
-// Viewer includes
-#include "llmutelist.h" // to check for muted avatars
-#include "llagent.h"
-#include "llcachename.h"
-#include "llimview.h" // for LLIMMgr
-#include "llparcel.h"
-#include "llviewerparcelmgr.h"
-#include "llfirstuse.h"
-#include "llspeakers.h"
-#include "lltrans.h"
-#include "llviewerwindow.h"
-#include "llviewercamera.h"
-#include "llversioninfo.h"
-
-#include "llviewernetwork.h"
-#include "llnotificationsutil.h"
-
-#include "llcorehttputil.h"
-#include "lleventfilter.h"
-
-#include "stringize.h"
-
-// for base64 decoding
-#include "apr_base64.h"
-
-#define USE_SESSION_GROUPS 0
-#define VX_NULL_POSITION -2147483648.0 /*The Silence*/
-
-extern LLMenuBarGL* gMenuBarView;
-extern void handle_voice_morphing_subscribe();
-
-const std::string VIVOX_VOICE_SERVER_TYPE = "vivox";
-
-namespace {
- const F32 VOLUME_SCALE_VIVOX = 0.01f;
-
- const F32 SPEAKING_TIMEOUT = 1.f;
-
- static const std::string VISIBLE_VOICE_SERVER_TYPE = "Vivox";
-
- // Don't retry connecting to the daemon more frequently than this:
- const F32 DAEMON_CONNECT_THROTTLE_SECONDS = 1.0f;
- const int DAEMON_CONNECT_RETRY_MAX = 3;
-
- // Don't send positional updates more frequently than this:
- const F32 UPDATE_THROTTLE_SECONDS = 0.5f;
-
- // Timeout for connection to Vivox
- const F32 CONNECT_ATTEMPT_TIMEOUT = 300.0f;
- const F32 CONNECT_DNS_TIMEOUT = 5.0f;
- const int CONNECT_RETRY_MAX = 3;
-
- const F32 LOGIN_ATTEMPT_TIMEOUT = 30.0f;
- const F32 LOGOUT_ATTEMPT_TIMEOUT = 5.0f;
- const int LOGIN_RETRY_MAX = 3;
-
- const F32 PROVISION_RETRY_TIMEOUT = 2.0;
- const int PROVISION_RETRY_MAX = 5;
-
- // Cosine of a "trivially" small angle
- const F32 FOUR_DEGREES = 4.0f * (F_PI / 180.0f);
- const F32 MINUSCULE_ANGLE_COS = (F32) cos(0.5f * FOUR_DEGREES);
-
- const F32 SESSION_JOIN_TIMEOUT = 30.0f;
-
- // Defines the maximum number of times(in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine()
- // which is treated as normal. The is the number of frames to wait for a channel join before giving up. This was changed
- // from the original count of 50 for two reason. Modern PCs have higher frame rates and sometimes the SLVoice process
- // backs up processing join requests. There is a log statement that records when channel joins take longer than 100 frames.
- const int MAX_NORMAL_JOINING_SPATIAL_NUM = 1500;
-
- // How often to check for expired voice fonts in seconds
- const F32 VOICE_FONT_EXPIRY_INTERVAL = 10.f;
- // Time of day at which Vivox expires voice font subscriptions.
- // Used to replace the time portion of received expiry timestamps.
- static const std::string VOICE_FONT_EXPIRY_TIME = "T05:00:00Z";
-
- // Maximum length of capture buffer recordings in seconds.
- const F32 CAPTURE_BUFFER_MAX_TIME = 10.f;
-
- const int ERROR_VIVOX_OBJECT_NOT_FOUND = 1001;
- const int ERROR_VIVOX_NOT_LOGGED_IN = 1007;
-}
-
-static int scale_mic_volume(float volume)
-{
- // incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.
- // Map it to Vivox levels as follows: 0.0 -> 30, 1.0 -> 50, 2.0 -> 70
- return 30 + (int)(volume * 20.0f);
-}
-
-static int scale_speaker_volume(float volume)
-{
- // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
- // Map it to Vivox levels as follows: 0.0 -> 30, 0.5 -> 50, 1.0 -> 70
- return 30 + (int)(volume * 40.0f);
-
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-class LLVivoxVoiceClientMuteListObserver : public LLMuteListObserver
-{
- /* virtual */ void onChange() { LLVivoxVoiceClient::getInstance()->muteListChanged();}
-};
-
-
-void LLVoiceVivoxStats::reset()
-{
- mStartTime = -1.0f;
- mConnectCycles = 0;
- mConnectTime = -1.0f;
- mConnectAttempts = 0;
- mProvisionTime = -1.0f;
- mProvisionAttempts = 0;
- mEstablishTime = -1.0f;
- mEstablishAttempts = 0;
-}
-
-LLVoiceVivoxStats::LLVoiceVivoxStats()
-{
- reset();
-}
-
-LLVoiceVivoxStats::~LLVoiceVivoxStats()
-{
-}
-
-void LLVoiceVivoxStats::connectionAttemptStart()
-{
- if (!mConnectAttempts)
- {
- mStartTime = LLTimer::getTotalTime();
- mConnectCycles++;
- }
- mConnectAttempts++;
-}
-
-void LLVoiceVivoxStats::connectionAttemptEnd(bool success)
-{
- if ( success )
- {
- mConnectTime = (LLTimer::getTotalTime() - mStartTime) / USEC_PER_SEC;
- }
-}
-
-void LLVoiceVivoxStats::provisionAttemptStart()
-{
- if (!mProvisionAttempts)
- {
- mStartTime = LLTimer::getTotalTime();
- }
- mProvisionAttempts++;
-}
-
-void LLVoiceVivoxStats::provisionAttemptEnd(bool success)
-{
- if ( success )
- {
- mProvisionTime = (LLTimer::getTotalTime() - mStartTime) / USEC_PER_SEC;
- }
-}
-
-void LLVoiceVivoxStats::establishAttemptStart()
-{
- if (!mEstablishAttempts)
- {
- mStartTime = LLTimer::getTotalTime();
- }
- mEstablishAttempts++;
-}
-
-void LLVoiceVivoxStats::establishAttemptEnd(bool success)
-{
- if ( success )
- {
- mEstablishTime = (LLTimer::getTotalTime() - mStartTime) / USEC_PER_SEC;
- }
-}
-
-LLSD LLVoiceVivoxStats::read()
-{
- LLSD stats(LLSD::emptyMap());
-
- stats["connect_cycles"] = LLSD::Integer(mConnectCycles);
- stats["connect_attempts"] = LLSD::Integer(mConnectAttempts);
- stats["connect_time"] = LLSD::Real(mConnectTime);
-
- stats["provision_attempts"] = LLSD::Integer(mProvisionAttempts);
- stats["provision_time"] = LLSD::Real(mProvisionTime);
-
- stats["establish_attempts"] = LLSD::Integer(mEstablishAttempts);
- stats["establish_time"] = LLSD::Real(mEstablishTime);
-
- return stats;
-}
-
-static LLVivoxVoiceClientMuteListObserver mutelist_listener;
-static bool sMuteListListener_listening = false;
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-static LLProcessPtr sGatewayPtr;
-static LLEventStream sGatewayPump("VivoxDaemonPump", true);
-
-static bool isGatewayRunning()
-{
- return sGatewayPtr && sGatewayPtr->isRunning();
-}
-
-static void killGateway()
-{
- if (sGatewayPtr)
- {
- LL_DEBUGS("Voice") << "SLVoice " << sGatewayPtr->getStatusString() << LL_ENDL;
-
- sGatewayPump.stopListening("VivoxDaemonPump");
- sGatewayPtr->kill(__FUNCTION__);
- sGatewayPtr=NULL;
- }
- else
- {
- LL_DEBUGS("Voice") << "no gateway" << LL_ENDL;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-bool LLVivoxVoiceClient::sShuttingDown = false;
-bool LLVivoxVoiceClient::sConnected = false;
-LLPumpIO *LLVivoxVoiceClient::sPump = nullptr;
-
-LLVivoxVoiceClient::LLVivoxVoiceClient() :
- mWriteOffset(0),
- mHidden(true),
- mSessionTerminateRequested(false),
- mRelogRequested(false),
- mTerminateDaemon(false),
- mSpatialJoiningNum(0),
-
- mTuningMode(false),
- mTuningEnergy(0.0f),
- mTuningMicVolume(0),
- mTuningMicVolumeDirty(true),
- mTuningSpeakerVolume(50), // Set to 50 so the user can hear himself when he sets his mic volume
- mTuningSpeakerVolumeDirty(true),
- mDevicesListUpdated(false),
-
- mAudioSession(), // TBD - should be NULL
- mNextAudioSession(),
-
- mCurrentParcelLocalID(0),
- mConnectorEstablished(false),
- mAccountLoggedIn(false),
- mNumberOfAliases(0),
- mCommandCookie(0),
- mLoginRetryCount(0),
-
- mBuddyListMapPopulated(false),
- mBlockRulesListReceived(false),
- mAutoAcceptRulesListReceived(false),
-
- mCaptureDeviceDirty(false),
- mRenderDeviceDirty(false),
- mSpatialCoordsDirty(false),
- mIsInitialized(false),
-
- mMuteMic(false),
- mMuteMicDirty(false),
- mFriendsListDirty(true),
-
- mEarLocation(0),
- mSpeakerVolumeDirty(true),
- mSpeakerMuteDirty(true),
- mMicVolume(0),
- mMicVolumeDirty(true),
-
- mVoiceEnabled(false),
- mProcessChannels(false),
- mWriteInProgress(false),
-
- mVoiceFontsReceived(false),
- mVoiceFontsNew(false),
- mVoiceFontListDirty(false),
-
- mCaptureBufferMode(false),
- mCaptureBufferRecording(false),
- mCaptureBufferRecorded(false),
- mCaptureBufferPlaying(false),
- mShutdownComplete(true),
- mPlayRequestCount(0),
-
- mAvatarNameCacheConnection(),
- mIsInTuningMode(false),
- mIsInChannel(false),
- mIsJoiningSession(false),
- mIsWaitingForFonts(false),
- mIsLoggingIn(false),
- mIsLoggedIn(false),
- mIsProcessingChannels(false),
- mIsCoroutineActive(false),
- mVivoxPump("vivoxClientPump")
-{
- sShuttingDown = false;
- sConnected = false;
- sPump = nullptr;
-
- mSpeakerVolume = scale_speaker_volume(0);
-
- mVoiceVersion.serverVersion = "";
- mVoiceVersion.voiceServerType = VISIBLE_VOICE_SERVER_TYPE;
- mVoiceVersion.internalVoiceServerType = VIVOX_VOICE_SERVER_TYPE;
- mVoiceVersion.majorVersion = 1;
- mVoiceVersion.minorVersion = 0;
- mVoiceVersion.mBuildVersion = "";
- mVoiceVersion.serverVersion = "";
-
- // gMuteListp isn't set up at this point, so we defer this until later.
-// gMuteListp->addObserver(&mutelist_listener);
-
-
-#if LL_DARWIN || LL_LINUX
- // HACK: THIS DOES NOT BELONG HERE
- // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
- // This should cause us to ignore SIGPIPE and handle the error through proper channels.
- // This should really be set up elsewhere. Where should it go?
- signal(SIGPIPE, SIG_IGN);
-
- // Since we're now launching the gateway with fork/exec instead of system(), we need to deal with zombie processes.
- // Ignoring SIGCHLD should prevent zombies from being created. Alternately, we could use wait(), but I'd rather not do that.
- signal(SIGCHLD, SIG_IGN);
-#endif
-
-
- gIdleCallbacks.addFunction(idle, this);
-}
-
-//---------------------------------------------------
-
-LLVivoxVoiceClient::~LLVivoxVoiceClient()
-{
- if (mAvatarNameCacheConnection.connected())
- {
- mAvatarNameCacheConnection.disconnect();
- }
- sShuttingDown = true;
-}
-
-//---------------------------------------------------
-
-void LLVivoxVoiceClient::init(LLPumpIO *pump)
-{
- // constructor will set up LLVoiceClient::getInstance()
- sPump = pump;
-
-// LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
-// boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
-
-}
-
-void LLVivoxVoiceClient::terminate()
-{
- if (sShuttingDown)
- {
- return;
- }
-
- // needs to be done manually here since we will not get another pass in
- // coroutines... that mechanism is long since gone.
- if (mIsLoggedIn)
- {
- logoutOfVivox(false);
- }
-
- if(sConnected)
- {
- breakVoiceConnection(false);
- sConnected = false;
- }
- else
- {
- mRelogRequested = false;
- killGateway();
- }
-
- sShuttingDown = true;
- sPump = NULL;
-}
-
-//---------------------------------------------------
-
-void LLVivoxVoiceClient::cleanUp()
-{
- LL_DEBUGS("Voice") << LL_ENDL;
-
- deleteAllSessions();
- deleteAllVoiceFonts();
- deleteVoiceFontTemplates();
- LL_DEBUGS("Voice") << "exiting" << LL_ENDL;
-}
-
-//---------------------------------------------------
-
-const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion()
-{
- return mVoiceVersion;
-}
-
-//---------------------------------------------------
-
-void LLVivoxVoiceClient::updateSettings()
-{
- setVoiceEnabled(LLVoiceClient::getInstance()->voiceEnabled());
- setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
-
- std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
- setCaptureDevice(inputDevice);
- std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
- setRenderDevice(outputDevice);
- F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
- setMicGain(mic_level);
-}
-
-/////////////////////////////
-// utility functions
-
-bool LLVivoxVoiceClient::writeString(const std::string &str)
-{
- bool result = false;
- LL_DEBUGS("LowVoice") << "sending:\n" << str << LL_ENDL;
-
- if(sConnected)
- {
- apr_status_t err;
- apr_size_t size = (apr_size_t)str.size();
- apr_size_t written = size;
-
- //MARK: Turn this on to log outgoing XML
- // LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
-
- // check return code - sockets will fail (broken, etc.)
- err = apr_socket_send(
- mSocket->getSocket(),
- (const char*)str.data(),
- &written);
-
- if(err == 0 && written == size)
- {
- // Success.
- result = true;
- }
- else if (err == 0 && written != size) {
- // Did a short write, log it for now
- LL_WARNS("Voice") << ") short write on socket sending data to vivox daemon." << "Sent " << written << "bytes instead of " << size <<LL_ENDL;
- }
- else if(APR_STATUS_IS_EAGAIN(err))
- {
- char buf[MAX_STRING];
- LL_WARNS("Voice") << "EAGAIN error " << err << " (" << apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << LL_ENDL;
- }
- else
- {
- // Assume any socket error means something bad. For now, just close the socket.
- char buf[MAX_STRING];
- LL_WARNS("Voice") << "apr error " << err << " ("<< apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << LL_ENDL;
- daemonDied();
- }
- }
-
- return result;
-}
-
-
-/////////////////////////////
-// session control messages
-void LLVivoxVoiceClient::connectorCreate()
-{
- std::ostringstream stream;
- std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-
- // Transition to stateConnectorStarted when the connector handle comes back.
- std::string vivoxLogLevel = gSavedSettings.getString("VivoxDebugLevel");
- if ( vivoxLogLevel.empty() )
- {
- vivoxLogLevel = "0";
- }
- LL_DEBUGS("Voice") << "creating connector with log level " << vivoxLogLevel << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.Create.1\">"
- << "<ClientName>V2 SDK</ClientName>"
- << "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>"
- << "<Mode>Normal</Mode>"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Logging>"
- << "<Folder>" << logdir << "</Folder>"
- << "<FileNamePrefix>Connector</FileNamePrefix>"
- << "<FileNameSuffix>.log</FileNameSuffix>"
- << "<LogLevel>" << vivoxLogLevel << "</LogLevel>"
- << "</Logging>"
- << "<Application>" << LLVersionInfo::instance().getChannel() << " " << LLVersionInfo::instance().getVersion() << "</Application>"
- //<< "<Application></Application>" //Name can cause problems per vivox.
- << "<MaxCalls>12</MaxCalls>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::connectorShutdown()
-{
- if(mConnectorEstablished)
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.InitiateShutdown.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "</Request>"
- << "\n\n\n";
-
- mShutdownComplete = false;
- mConnectorEstablished = false;
-
- writeString(stream.str());
- }
- else
- {
- mShutdownComplete = true;
- }
-}
-
-void LLVivoxVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID)
-{
-
- mAccountDisplayName = user_id;
-
- LL_INFOS("Voice") << "name \"" << mAccountDisplayName << "\" , ID " << agentID << LL_ENDL;
-
- mAccountName = nameFromID(agentID);
-}
-
-void LLVivoxVoiceClient::setLoginInfo(
- const std::string& account_name,
- const std::string& password,
- const std::string& voice_sip_uri_hostname,
- const std::string& voice_account_server_uri)
-{
- mVoiceSIPURIHostName = voice_sip_uri_hostname;
- mVoiceAccountServerURI = voice_account_server_uri;
-
- if(mAccountLoggedIn)
- {
- // Already logged in.
- LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
-
- // Don't process another login.
- return;
- }
- else if ( account_name != mAccountName )
- {
- LL_WARNS("Voice") << "Mismatched account name! " << account_name
- << " instead of " << mAccountName << LL_ENDL;
- }
- else
- {
- mAccountPassword = password;
- }
-
- std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
-
- if( !debugSIPURIHostName.empty() )
- {
- LL_INFOS("Voice") << "Overriding account server based on VivoxDebugSIPURIHostName: "
- << debugSIPURIHostName << LL_ENDL;
- mVoiceSIPURIHostName = debugSIPURIHostName;
- }
-
- if( mVoiceSIPURIHostName.empty() )
- {
- // we have an empty account server name
- // so we fall back to hardcoded defaults
-
- if(LLGridManager::getInstance()->isInProductionGrid())
- {
- // Use the release account server
- mVoiceSIPURIHostName = "bhr.vivox.com";
- }
- else
- {
- // Use the development account server
- mVoiceSIPURIHostName = "bhd.vivox.com";
- }
- LL_INFOS("Voice") << "Defaulting SIP URI host: "
- << mVoiceSIPURIHostName << LL_ENDL;
-
- }
-
- std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
-
- if( !debugAccountServerURI.empty() )
- {
- LL_INFOS("Voice") << "Overriding account server based on VivoxDebugVoiceAccountServerURI: "
- << debugAccountServerURI << LL_ENDL;
- mVoiceAccountServerURI = debugAccountServerURI;
- }
-
- if( mVoiceAccountServerURI.empty() )
- {
- // If the account server URI isn't specified, construct it from the SIP URI hostname
- mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";
- LL_INFOS("Voice") << "Inferring account server based on SIP URI Host name: "
- << mVoiceAccountServerURI << LL_ENDL;
- }
-}
-
-void LLVivoxVoiceClient::idle(void* user_data)
-{
-}
-
-//=========================================================================
-// the following are methods to support the coroutine implementation of the
-// voice connection and processing. They should only be called in the context
-// of a coroutine.
-//
-//
-
-typedef enum e_voice_control_coro_state
-{
- VOICE_STATE_ERROR = -1,
- VOICE_STATE_DONE = 0,
- VOICE_STATE_TP_WAIT, // entry point
- VOICE_STATE_START_DAEMON,
- VOICE_STATE_PROVISION_ACCOUNT,
- VOICE_STATE_START_SESSION,
- VOICE_STATE_SESSION_RETRY,
- VOICE_STATE_SESSION_ESTABLISHED,
- VOICE_STATE_WAIT_FOR_CHANNEL,
- VOICE_STATE_DISCONNECT,
- VOICE_STATE_WAIT_FOR_EXIT,
-} EVoiceControlCoroState;
-
-void LLVivoxVoiceClient::voiceControlCoro()
-{
- int state = 0;
- try
- {
- // state is passed as a reference instead of being
- // a member due to unresolved issues with coroutine
- // surviving longer than LLVivoxVoiceClient
- voiceControlStateMachine(state);
- }
- catch (const LLCoros::Stop&)
- {
- LL_DEBUGS("LLVivoxVoiceClient") << "Received a shutdown exception" << LL_ENDL;
- }
- catch (const LLContinueError&)
- {
- LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient");
- }
- catch (...)
- {
- // Ideally for Windows need to log SEH exception instead or to set SEH
- // handlers but bugsplat shows local variables for windows, which should
- // be enough
- LL_WARNS("Voice") << "voiceControlStateMachine crashed in state " << state << LL_ENDL;
- throw;
- }
-}
-
-void LLVivoxVoiceClient::voiceControlStateMachine(S32 &coro_state)
-{
- if (sShuttingDown)
- {
- return;
- }
-
- LL_DEBUGS("Voice") << "starting" << LL_ENDL;
- mIsCoroutineActive = true;
- LLCoros::set_consuming(true);
-
- U32 retry = 0;
-
- coro_state = VOICE_STATE_TP_WAIT;
-
- do
- {
- if (sShuttingDown)
- {
- // Vivox singleton performed the exit, logged out,
- // cleaned sockets, gateway and no longer cares
- // about state of coroutine, so just stop
- return;
- }
-
- switch (coro_state)
- {
- case VOICE_STATE_TP_WAIT:
- // starting point for voice
- if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
- {
- LL_DEBUGS("Voice") << "Suspending voiceControlCoro() momentarily for teleport. Tuning: " << mTuningMode << ". Relog: " << mRelogRequested << LL_ENDL;
- llcoro::suspendUntilTimeout(1.0);
- }
- else
- {
- coro_state = VOICE_STATE_START_DAEMON;
- }
- break;
-
- case VOICE_STATE_START_DAEMON:
- LL_DEBUGS("Voice") << "Launching daemon" << LL_ENDL;
- LLVoiceVivoxStats::getInstance()->reset();
- if (startAndLaunchDaemon())
- {
- coro_state = VOICE_STATE_PROVISION_ACCOUNT;
- }
- else
- {
- coro_state = VOICE_STATE_SESSION_RETRY;
- }
- break;
-
- case VOICE_STATE_PROVISION_ACCOUNT:
- if (provisionVoiceAccount())
- {
- coro_state = VOICE_STATE_START_SESSION;
- }
- else
- {
- coro_state = VOICE_STATE_SESSION_RETRY;
- }
- break;
-
- case VOICE_STATE_START_SESSION:
- if (establishVoiceConnection())
- {
- coro_state = VOICE_STATE_SESSION_ESTABLISHED;
- }
- else
- {
- coro_state = VOICE_STATE_SESSION_RETRY;
- }
- break;
-
- case VOICE_STATE_SESSION_RETRY:
- giveUp(); // cleans sockets and session
- if (mRelogRequested)
- {
- // We failed to connect, give it a bit time before retrying.
- retry++;
- F32 full_delay = llmin(5.f * (F32)retry, 60.f);
- F32 current_delay = 0.f;
- LL_INFOS("Voice") << "Voice failed to establish session after " << retry
- << " tries. Will attempt to reconnect in " << full_delay
- << " seconds" << LL_ENDL;
- while (current_delay < full_delay && !sShuttingDown)
- {
- // Assuming that a second has passed is not accurate,
- // but we don't need accurancy here, just to make sure
- // that some time passed and not to outlive voice itself
- current_delay++;
- llcoro::suspendUntilTimeout(1.f);
- }
- coro_state = VOICE_STATE_WAIT_FOR_EXIT;
- }
- else
- {
- coro_state = VOICE_STATE_DONE;
- }
- break;
-
- case VOICE_STATE_SESSION_ESTABLISHED:
- {
- // enable/disable the automatic VAD and explicitly set the initial values of
- // the VAD variables ourselves when it is off - see SL-15072 for more details
- // note: we set the other parameters too even if the auto VAD is on which is ok
- unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
- unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
- unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
- unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
- setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
-
- // watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
- gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
-
- if (mTuningMode)
- {
- performMicTuning();
- }
-
- coro_state = VOICE_STATE_WAIT_FOR_CHANNEL;
- }
- break;
-
- case VOICE_STATE_WAIT_FOR_CHANNEL:
- waitForChannel(); // todo: split into more states like login/fonts
- coro_state = VOICE_STATE_DISCONNECT;
- break;
-
- case VOICE_STATE_DISCONNECT:
- LL_DEBUGS("Voice") << "lost channel RelogRequested=" << mRelogRequested << LL_ENDL;
- endAndDisconnectSession();
- retry = 0; // Connected without issues
- coro_state = VOICE_STATE_WAIT_FOR_EXIT;
- break;
-
- case VOICE_STATE_WAIT_FOR_EXIT:
- if (isGatewayRunning())
- {
- LL_INFOS("Voice") << "waiting for SLVoice to exit" << LL_ENDL;
- llcoro::suspendUntilTimeout(1.0);
- }
- else if (mRelogRequested && mVoiceEnabled)
- {
- LL_INFOS("Voice") << "will attempt to reconnect to voice" << LL_ENDL;
- coro_state = VOICE_STATE_TP_WAIT;
- }
- else
- {
- coro_state = VOICE_STATE_DONE;
- }
- break;
-
- case VOICE_STATE_DONE:
- break;
- }
- } while (coro_state > 0);
-
- if (sShuttingDown)
- {
- // LLVivoxVoiceClient might be already dead
- return;
- }
-
- mIsCoroutineActive = false;
- LL_INFOS("Voice") << "exiting" << LL_ENDL;
-}
-
-bool LLVivoxVoiceClient::endAndDisconnectSession()
-{
- LL_DEBUGS("Voice") << LL_ENDL;
-
- breakVoiceConnection(true);
-
- killGateway();
-
- return true;
-}
-
-bool LLVivoxVoiceClient::callbackEndDaemon(const LLSD& data)
-{
- if (!sShuttingDown && mVoiceEnabled)
- {
- LL_WARNS("Voice") << "SLVoice terminated " << ll_stream_notation_sd(data) << LL_ENDL;
- terminateAudioSession(false);
- closeSocket();
- cleanUp();
- LLVoiceClient::getInstance()->setUserPTTState(false);
- gAgent.setVoiceConnected(false);
- mRelogRequested = true;
- }
- sGatewayPump.stopListening("VivoxDaemonPump");
- return false;
-}
-
-bool LLVivoxVoiceClient::startAndLaunchDaemon()
-{
- //---------------------------------------------------------------------
- if (!LLVoiceClient::getInstance()->voiceEnabled())
- {
- // Voice is locked out, we must not launch the vivox daemon.
- LL_WARNS("Voice") << "voice disabled; not starting daemon" << LL_ENDL;
- return false;
- }
-
- if (!isGatewayRunning())
- {
-#ifndef VIVOXDAEMON_REMOTEHOST
- // Launch the voice daemon
-#if LL_WINDOWS
- // On windows use exe (not work or RO) directory
- std::string exe_path = gDirUtilp->getExecutableDir();
- gDirUtilp->append(exe_path, "SLVoice.exe");
-#elif LL_DARWIN
- // On MAC use resource directory
- std::string exe_path = gDirUtilp->getAppRODataDir();
- gDirUtilp->append(exe_path, "SLVoice");
-#else
- std::string exe_path = gDirUtilp->getExecutableDir();
- gDirUtilp->append(exe_path, "SLVoice.exe");
-#endif
- // See if the vivox executable exists
- llstat s;
- if (!LLFile::stat(exe_path, &s))
- {
- // vivox executable exists. Build the command line and launch the daemon.
- LLProcess::Params params;
-#if LL_LINUX || __FreeBSD__
-#if __FreeBSD__
- params.envs.add("WINEARCH=win32");
- params.envs.add("WINEPREFIX=~/.i386-wine-pkg");
-#endif // __FreeBSD__
- params.executable = "wine";
- params.args.add(exe_path);
-#else
- params.executable = exe_path;
-#endif // LL_LINUX || __FreeBSD__
-
- // VOICE-88: Cycle through [portbase..portbase+portrange) on
- // successive tries because attempting to relaunch (after manually
- // disabling and then re-enabling voice) with the same port can
- // cause SLVoice's bind() call to fail with EADDRINUSE. We expect
- // that eventually the OS will time out previous ports, which is
- // why we cycle instead of incrementing indefinitely.
-
- static LLCachedControl<U32> portbase(gSavedSettings, "VivoxVoicePort");
- static LLCachedControl<std::string> host(gSavedSettings, "VivoxVoiceHost");
- static LLCachedControl<std::string> loglevel(gSavedSettings, "VivoxDebugLevel");
- static LLCachedControl<std::string> log_folder(gSavedSettings, "VivoxLogDirectory");
- static LLCachedControl<std::string> shutdown_timeout(gSavedSettings, "VivoxShutdownTimeout");
- static const U32 portrange = 100;
- static U32 portoffset = 0;
- U32 port = 0;
-
- if (LLAppViewer::instance()->isSecondInstance())
- {
- // Ideally need to know amount of instances and
- // to increment instance_offset on EADDRINUSE.
- // But for now just use rand
- static U32 instance_offset = portrange * ll_rand(20);
- port = portbase + portoffset + instance_offset;
- }
- else
- {
- // leave main thread with exclusive port set
- port = portbase + portoffset;
- }
- portoffset = (portoffset + 1) % portrange;
- params.args.add("-i");
- params.args.add(STRINGIZE(host() << ':' << port));
-
- params.args.add("-ll");
- if (loglevel().empty())
- {
- params.args.add("0");
- }
- else
- {
- params.args.add(loglevel);
- }
-
- params.args.add("-lf");
- if (log_folder().empty())
- {
- params.args.add(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""));
- }
- else
- {
- params.args.add(log_folder);
- }
-
- // set log file basename and .log
- params.args.add("-lp");
- params.args.add("SLVoice");
- params.args.add("-ls");
- params.args.add(".log");
-
- // rotate any existing log
- std::string new_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SLVoice.log");
- std::string old_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SLVoice.old");
- if (gDirUtilp->fileExists(new_log))
- {
- LLFile::rename(new_log, old_log);
- }
-
- if (!shutdown_timeout().empty())
- {
- params.args.add("-st");
- params.args.add(shutdown_timeout);
- }
- params.cwd = gDirUtilp->getAppRODataDir();
-
-# ifdef VIVOX_HANDLE_ARGS
- params.args.add("-ah");
- params.args.add(LLVivoxSecurity::getInstance()->accountHandle());
-
- params.args.add("-ch");
- params.args.add(LLVivoxSecurity::getInstance()->connectorHandle());
-# endif // VIVOX_HANDLE_ARGS
-
- params.postend = sGatewayPump.getName();
- sGatewayPump.listen("VivoxDaemonPump", boost::bind(&LLVivoxVoiceClient::callbackEndDaemon, this, _1));
-
- LL_INFOS("Voice") << "Launching SLVoice" << LL_ENDL;
- LL_DEBUGS("Voice") << "SLVoice params " << params << LL_ENDL;
-
- sGatewayPtr = LLProcess::create(params);
-
- mDaemonHost = LLHost(host().c_str(), port);
- }
- else
- {
- LL_WARNS("Voice") << exe_path << " not found." << LL_ENDL;
- return false;
- }
-#else
- // SLIM SDK: port changed from 44124 to 44125.
- // We can connect to a client gateway running on another host. This is useful for testing.
- // To do this, launch the gateway on a nearby host like this:
- // vivox-gw.exe -p tcp -i 0.0.0.0:44125
- // and put that host's IP address here.
- mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost"), gSavedSettings.getU32("VivoxVoicePort"));
-#endif
-
- // Dirty the states we'll need to sync with the daemon when it comes up.
- mMuteMicDirty = true;
- mMicVolumeDirty = true;
- mSpeakerVolumeDirty = true;
- mSpeakerMuteDirty = true;
- // These only need to be set if they're not default (i.e. empty string).
- mCaptureDeviceDirty = !mCaptureDevice.empty();
- mRenderDeviceDirty = !mRenderDevice.empty();
-
- mMainSessionGroupHandle.clear();
- }
- else
- {
- LL_DEBUGS("Voice") << " gateway running; not attempting to start" << LL_ENDL;
- }
-
- //---------------------------------------------------------------------
- llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
-
- LL_DEBUGS("Voice") << "Connecting to vivox daemon:" << mDaemonHost << LL_ENDL;
-
- int retryCount(0);
- LLVoiceVivoxStats::getInstance()->reset();
- while (!sConnected && !sShuttingDown && retryCount++ <= DAEMON_CONNECT_RETRY_MAX)
- {
- LLVoiceVivoxStats::getInstance()->connectionAttemptStart();
- LL_DEBUGS("Voice") << "Attempting to connect to vivox daemon: " << mDaemonHost << LL_ENDL;
- closeSocket();
- if (!mSocket)
- {
- mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
- }
-
- sConnected = mSocket->blockingConnect(mDaemonHost);
- LLVoiceVivoxStats::getInstance()->connectionAttemptEnd(sConnected);
- if (!sConnected)
- {
- llcoro::suspendUntilTimeout(DAEMON_CONNECT_THROTTLE_SECONDS);
- }
- }
-
- //---------------------------------------------------------------------
- if (sShuttingDown && !sConnected)
- {
- return false;
- }
-
- llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
-
- while (!sPump && !sShuttingDown)
- { // Can't use the pump until we have it available.
- llcoro::suspend();
- }
-
- if (sShuttingDown)
- {
- return false;
- }
-
- // MBW -- Note to self: pumps and pipes examples in
- // indra/test/io.cpp
- // indra/test/llpipeutil.{cpp|h}
-
- // Attach the pumps and pipes
-
- LLPumpIO::chain_t readChain;
-
- readChain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(mSocket)));
- readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser()));
-
-
- sPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
-
-
- //---------------------------------------------------------------------
- llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
-
- // Initial devices query
- getCaptureDevicesSendMessage();
- getRenderDevicesSendMessage();
-
- mLoginRetryCount = 0;
-
- return true;
-}
-
-bool LLVivoxVoiceClient::provisionVoiceAccount()
-{
- LL_INFOS("Voice") << "Provisioning voice account." << LL_ENDL;
-
- while ((!gAgent.getRegion() || !gAgent.getRegion()->capabilitiesReceived()) && !sShuttingDown)
- {
- LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
- // *TODO* Pump a message for wake up.
- llcoro::suspend();
- }
-
- if (sShuttingDown)
- {
- return false;
- }
-
- std::string url = gAgent.getRegionCapability("ProvisionVoiceAccountRequest");
-
- LL_DEBUGS("Voice") << "region ready for voice provisioning; url=" << url << LL_ENDL;
-
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("voiceAccountProvision", httpPolicy);
- LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
- LLCore::HttpOptions::ptr_t httpOpts = std::make_shared<LLCore::HttpOptions>();
- int retryCount(0);
-
- LLSD result;
- bool provisioned = false;
- do
- {
- LLVoiceVivoxStats::getInstance()->provisionAttemptStart();
- LLSD body;
- body["voice_server_type"] = "vivox";
- result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOpts);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (status == LLCore::HttpStatus(404))
- {
- F32 timeout = pow(PROVISION_RETRY_TIMEOUT, static_cast<float>(retryCount));
- LL_WARNS("Voice") << "Provision CAP 404. Retrying in " << timeout << " seconds. Retries: " << (S32)retryCount << LL_ENDL;
- llcoro::suspendUntilTimeout(timeout);
-
- if (sShuttingDown)
- {
- return false;
- }
- }
- else if (!status)
- {
- LL_WARNS("Voice") << "Unable to provision voice account." << LL_ENDL;
- LLVoiceVivoxStats::getInstance()->provisionAttemptEnd(false);
- return false;
- }
- else
- {
- provisioned = true;
- }
- } while (!provisioned && ++retryCount <= PROVISION_RETRY_MAX && !sShuttingDown);
-
- if (sShuttingDown && !provisioned)
- {
- return false;
- }
-
- LLVoiceVivoxStats::getInstance()->provisionAttemptEnd(provisioned);
- if (!provisioned)
- {
- LL_WARNS("Voice") << "Could not access voice provision cap after " << retryCount << " attempts." << LL_ENDL;
- return false;
- }
- LL_DEBUGS("Voice") << "Voice Provision Result." << result << LL_ENDL;
- std::string voiceSipUriHostname;
- std::string voiceAccountServerUri;
- std::string voiceUserName = result["username"].asString();
- std::string voicePassword = result["password"].asString();
-
- if (result.has("voice_sip_uri_hostname"))
- {
- voiceSipUriHostname = result["voice_sip_uri_hostname"].asString();
- }
-
- // this key is actually misnamed -- it will be an entire URI, not just a hostname.
- if (result.has("voice_account_server_name"))
- {
- voiceAccountServerUri = result["voice_account_server_name"].asString();
- }
-
- LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response"
- << " user " << (voiceUserName.empty() ? "not set" : "set")
- << " password " << (voicePassword.empty() ? "not set" : "set")
- << " sip uri " << voiceSipUriHostname
- << " account uri " << voiceAccountServerUri
- << LL_ENDL;
-
- setLoginInfo(voiceUserName, voicePassword, voiceSipUriHostname, voiceAccountServerUri);
-
- return true;
-}
-
-bool LLVivoxVoiceClient::establishVoiceConnection()
-{
- if (!mVoiceEnabled && mIsInitialized)
- {
- LL_WARNS("Voice") << "cannot establish connection; enabled "<<mVoiceEnabled<<" initialized "<<mIsInitialized<<LL_ENDL;
- return false;
- }
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LLSD result;
- bool connected(false);
- bool giving_up(false);
- int retries = 0;
- LL_INFOS("Voice") << "Requesting connection to voice service" << LL_ENDL;
-
- LLVoiceVivoxStats::getInstance()->establishAttemptStart();
- connectorCreate();
- do
- {
- result = llcoro::suspendUntilEventOn(mVivoxPump);
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
-
- if (result.has("connector"))
- {
- connected = LLSD::Boolean(result["connector"]);
- LLVoiceVivoxStats::getInstance()->establishAttemptEnd(connected);
- if (!connected)
- {
- if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX && !sShuttingDown)
- {
- F32 timeout = (F32)LLSD::Real(result["retry"]);
- timeout *= retries;
- LL_INFOS("Voice") << "Retry connection to voice service in " << timeout << " seconds" << LL_ENDL;
- llcoro::suspendUntilTimeout(timeout);
-
- if (mVoiceEnabled) // user may have switched it off
- {
- // try again
- LLVoiceVivoxStats::getInstance()->establishAttemptStart();
- connectorCreate();
- }
- else
- {
- // stop if they've turned off voice
- giving_up = true;
- }
- }
- else
- {
- giving_up=true;
- }
- }
- }
- LL_DEBUGS("Voice") << (connected ? "" : "not ") << "connected, "
- << (giving_up ? "" : "not ") << "giving up"
- << LL_ENDL;
- } while (!connected && !giving_up && !sShuttingDown);
-
- if (giving_up)
- {
- LLSD args;
- args["HOSTID"] = LLURI(mVoiceAccountServerURI).authority();
- LLNotificationsUtil::add("NoVoiceConnect", args);
- }
-
- return connected;
-}
-
-bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait)
-{
- LL_DEBUGS("Voice") << "( wait=" << corowait << ")" << LL_ENDL;
- bool retval(true);
-
- mShutdownComplete = false;
- connectorShutdown();
-
- if (corowait)
- {
- LLSD timeoutResult(LLSDMap("connector", "timeout"));
-
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
-
- retval = result.has("connector");
- }
- else
- {
- mRelogRequested = false; //stop the control coro
- // If we are not doing a corowait then we must sleep until the connector has responded
- // otherwise we may very well close the socket too early.
-#if LL_WINDOWS
- if (!mShutdownComplete)
- {
- // The situation that brings us here is a call from ::terminate()
- // At this point message system is already down so we can't wait for
- // the message, yet we need to receive "connector shutdown response".
- // Either wait a bit and emulate it or check gMessageSystem for specific message
- _sleep(1000);
- if (sConnected)
- {
- sConnected = false;
- LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false)));
- mVivoxPump.post(vivoxevent);
- }
- mShutdownComplete = true;
- }
-#endif
- }
-
- LL_DEBUGS("Voice") << "closing SLVoice socket" << LL_ENDL;
- closeSocket(); // Need to do this now -- bad things happen if the destructor does it later.
- cleanUp();
- sConnected = false;
-
- return retval;
-}
-
-bool LLVivoxVoiceClient::loginToVivox()
-{
- LLSD timeoutResult(LLSDMap("login", "timeout"));
-
- int loginRetryCount(0);
-
- bool response_ok(false);
- bool account_login(false);
- bool send_login(true);
-
- do
- {
- mIsLoggingIn = true;
- if (send_login)
- {
- loginSendMessage();
- send_login = false;
- }
-
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGIN_ATTEMPT_TIMEOUT, timeoutResult);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
-
- if (result.has("login"))
- {
- std::string loginresp = result["login"];
-
- if (((loginresp == "retry") || (loginresp == "timeout")) && !sShuttingDown)
- {
- LL_WARNS("Voice") << "login failed with status '" << loginresp << "' "
- << " count " << loginRetryCount << "/" << LOGIN_RETRY_MAX
- << LL_ENDL;
- if (++loginRetryCount > LOGIN_RETRY_MAX)
- {
- // We've run out of retries - tell the user
- LL_WARNS("Voice") << "too many login retries (" << loginRetryCount << "); giving up." << LL_ENDL;
- LLSD args;
- args["HOSTID"] = LLURI(mVoiceAccountServerURI).authority();
- mTerminateDaemon = true;
- LLNotificationsUtil::add("NoVoiceConnect", args);
-
- mIsLoggingIn = false;
- return false;
- }
- response_ok = false;
- account_login = false;
- send_login = true;
-
- // an exponential backoff gets too long too quickly; stretch it out, but not too much
- F32 timeout = loginRetryCount * LOGIN_ATTEMPT_TIMEOUT;
-
- // tell the user there is a problem
- LL_WARNS("Voice") << "login " << loginresp << " will retry login in " << timeout << " seconds." << LL_ENDL;
-
- if (!sShuttingDown)
- {
- // Todo: this is way to long, viewer can get stuck waiting during shutdown
- // either make it listen to pump or split in smaller waits with checks for shutdown
- llcoro::suspendUntilTimeout(timeout);
- }
- }
- else if (loginresp == "failed")
- {
- mIsLoggingIn = false;
- return false;
- }
- else if (loginresp == "response_ok")
- {
- response_ok = true;
- }
- else if (loginresp == "account_login")
- {
- account_login = true;
- }
- else if (sShuttingDown)
- {
- mIsLoggingIn = false;
- return false;
- }
- }
-
- } while ((!response_ok || !account_login) && !sShuttingDown);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- mRelogRequested = false;
- mIsLoggedIn = true;
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
-
- // Set up the mute list observer if it hasn't been set up already.
- if ((!sMuteListListener_listening))
- {
- LLMuteList::getInstance()->addObserver(&mutelist_listener);
- sMuteListListener_listening = true;
- }
-
- // Set the initial state of mic mute, local speaker volume, etc.
- sendLocalAudioUpdates();
- mIsLoggingIn = false;
-
- return true;
-}
-
-void LLVivoxVoiceClient::logoutOfVivox(bool wait)
-{
- if (mIsLoggedIn)
- {
- // Ensure that we'll re-request provisioning before logging in again
- mAccountPassword.clear();
- mVoiceAccountServerURI.clear();
-
- logoutSendMessage();
-
- if (wait)
- {
- LLSD timeoutResult(LLSDMap("logout", "timeout"));
- LLSD result;
-
- do
- {
- LL_DEBUGS("Voice")
- << "waiting for logout response on "
- << mVivoxPump.getName()
- << LL_ENDL;
-
- result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
-
- if (sShuttingDown)
- {
- break;
- }
-
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- // Don't get confused by prior queued events -- note that it's
- // very important that mVivoxPump is an LLEventMailDrop, which
- // does queue events.
- } while (! result["logout"]);
- }
- else
- {
- LL_DEBUGS("Voice") << "not waiting for logout" << LL_ENDL;
- }
-
- mIsLoggedIn = false;
- }
-}
-
-
-bool LLVivoxVoiceClient::retrieveVoiceFonts()
-{
- // Request the set of available voice fonts.
- refreshVoiceEffectLists(true);
-
- mIsWaitingForFonts = true;
- LLSD result;
- do
- {
- result = llcoro::suspendUntilEventOn(mVivoxPump);
-
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- if (result.has("voice_fonts"))
- break;
- } while (true);
- mIsWaitingForFonts = false;
-
- mVoiceFontExpiryTimer.start();
- mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL);
-
- return result["voice_fonts"].asBoolean();
-}
-
-bool LLVivoxVoiceClient::requestParcelVoiceInfo()
-{
- //_INFOS("Voice") << "Requesting voice info for Parcel" << LL_ENDL;
-
- LLViewerRegion * region = gAgent.getRegion();
- if (region == NULL || !region->capabilitiesReceived())
- {
- LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest capability not yet available, deferring" << LL_ENDL;
- return false;
- }
-
- // grab the cap.
- std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest");
- if (url.empty())
- {
- // Region dosn't have the cap. Stop probing.
- LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest capability not available in this region" << LL_ENDL;
- return false;
- }
-
- // update the parcel
- checkParcelChanged(true);
-
- LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
-
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("parcelVoiceInfoRequest", httpPolicy);
- LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
-
- LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD());
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
- {
- // if a terminate request has been received,
- // bail and go to the stateSessionTerminated
- // state. If the cap request is still pending,
- // the responder will check to see if we've moved
- // to a new session and won't change any state.
- LL_DEBUGS("Voice") << "terminate requested " << mSessionTerminateRequested
- << " enabled " << mVoiceEnabled
- << " initialized " << mIsInitialized
- << LL_ENDL;
- terminateAudioSession(true);
- return false;
- }
-
- if ((!status) || (mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized)))
- {
- if (mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
- {
- LL_WARNS("Voice") << "Session terminated." << LL_ENDL;
- }
-
- LL_WARNS("Voice") << "No voice on parcel" << LL_ENDL;
- sessionTerminate();
- return false;
- }
-
- if (!result.has("voice_credentials"))
- {
- if (LLViewerParcelMgr::getInstance()->allowAgentVoice())
- {
- LL_WARNS("Voice") << "No voice credentials" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Voice") << "No voice credentials" << LL_ENDL;
- }
- }
-
- // set the spatial channel. If no voice credentials or uri are
- // available, then we simply drop out of voice spatially.
- return setSpatialChannel(result["voice_credentials"]);
-}
-
-bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
-{
- mIsJoiningSession = true;
-
- sessionStatePtr_t oldSession = mAudioSession;
-
- LL_INFOS("Voice") << "Adding or joining voice session " << nextSession->mHandle << LL_ENDL;
-
- mAudioSession = nextSession;
- if (!mAudioSession || !mAudioSession->mReconnect)
- {
- mNextAudioSession.reset();
- }
-
- // The old session may now need to be deleted.
- reapSession(oldSession);
-
- if (mAudioSession)
- {
- if (!mAudioSession->mHandle.empty())
- {
- // Connect to a session by session handle
-
- sessionMediaConnectSendMessage(mAudioSession);
- }
- else
- {
- // Connect to a session by URI
- sessionCreateSendMessage(mAudioSession, true, false);
- }
- }
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
-
- llcoro::suspend();
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LLSD result;
-
- if (mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM)
- {
- // Notify observers to let them know there is problem with voice
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
- LL_WARNS() << "There seems to be problem with connection to voice server. Disabling voice chat abilities." << LL_ENDL;
- }
-
- // Increase mSpatialJoiningNum only for spatial sessions- it's normal to reach this case for
- // example for p2p many times while waiting for response, so it can't be used to detect errors
- if (mAudioSession && mAudioSession->mIsSpatial)
- {
- mSpatialJoiningNum++;
- }
-
- if (!mVoiceEnabled && mIsInitialized)
- {
- LL_DEBUGS("Voice") << "Voice no longer enabled. Exiting"
- << " enabled " << mVoiceEnabled
- << " initialized " << mIsInitialized
- << LL_ENDL;
- mIsJoiningSession = false;
- // User bailed out during connect -- jump straight to teardown.
- terminateAudioSession(true);
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
- return false;
- }
- else if (mSessionTerminateRequested)
- {
- LL_DEBUGS("Voice") << "Terminate requested" << LL_ENDL;
- if (mAudioSession && !mAudioSession->mHandle.empty())
- {
- // Only allow direct exits from this state in p2p calls (for cancelling an invite).
- // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
- if (mAudioSession->mIsP2P)
- {
- terminateAudioSession(true);
- mIsJoiningSession = false;
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
- return false;
- }
- }
- }
-
- bool added(true);
- bool joined(false);
-
- LLSD timeoutResult(LLSDMap("session", "timeout"));
-
- // We are about to start a whole new session. Anything that MIGHT still be in our
- // maildrop is going to be stale and cause us much wailing and gnashing of teeth.
- // Just flush it all out and start new.
- mVivoxPump.discard();
-
- // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
- // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
- // For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
- // This is a cheap way to make sure both have happened before proceeding.
- do
- {
- result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, SESSION_JOIN_TIMEOUT, timeoutResult);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LL_INFOS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- if (result.has("session"))
- {
- if (!mAudioSession)
- {
- LL_WARNS("Voice") << "Message for session handle \"" << result["handle"] << "\" while session is not initialized." << LL_ENDL;
- continue;
- }
- if (result.has("handle") && result["handle"] != mAudioSession->mHandle)
- {
- LL_WARNS("Voice") << "Message for session handle \"" << result["handle"] << "\" while waiting for \"" << mAudioSession->mHandle << "\"." << LL_ENDL;
- continue;
- }
-
- std::string message = result["session"].asString();
-
- if ((message == "added") || (message == "created"))
- {
- added = true;
- }
- else if (message == "joined")
- {
- joined = true;
- }
- else if ((message == "failed") || (message == "removed") || (message == "timeout"))
- { // we will get a removed message if a voice call is declined.
- LL_INFOS("Voice") << "Result:" << result << LL_ENDL;
- if (message == "failed")
- {
- int reason = result["reason"].asInteger();
- LL_WARNS("Voice") << "Add and join failed for reason " << reason << LL_ENDL;
-
- if ( (reason == ERROR_VIVOX_NOT_LOGGED_IN)
- || (reason == ERROR_VIVOX_OBJECT_NOT_FOUND))
- {
- LL_DEBUGS("Voice") << "Requesting reprovision and login." << LL_ENDL;
- requestRelog();
- }
- }
- else
- {
- LL_WARNS("Voice") << "session '" << message << "' "
- << LL_ENDL;
- }
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
- mIsJoiningSession = false;
- return false;
- }
- }
- } while (!added || !joined);
-
- mIsJoiningSession = false;
-
- if (mSpatialJoiningNum > 100)
- {
- LL_WARNS("Voice") << "There seems to be problem with connecting to a voice channel. Frames to join were " << mSpatialJoiningNum << LL_ENDL;
- }
-
- mSpatialJoiningNum = 0;
-
- // Events that need to happen when a session is joined could go here.
- // send an initial positional information immediately upon joining.
- //
- // do an initial update for position and the camera position, then send a
- // positional update.
- updatePosition();
- enforceTether();
-
- // Dirty state that may need to be sync'ed with the daemon.
- mMuteMicDirty = true;
- mSpeakerVolumeDirty = true;
- mSpatialCoordsDirty = true;
-
- sendPositionAndVolumeUpdate();
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
-
- return true;
-}
-
-bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
-{
-
- if (mAudioSession)
- {
- LL_INFOS("Voice") << "terminateAudioSession(" << wait << ") Terminating current voice session " << mAudioSession->mHandle << LL_ENDL;
-
- if (mIsLoggedIn)
- {
- if (!mAudioSession->mHandle.empty())
- {
-
-#if RECORD_EVERYTHING
- // HACK: for testing only
- // Save looped recording
- std::string savepath("/tmp/vivoxrecording");
- {
- time_t now = time(NULL);
- const size_t BUF_SIZE = 64;
- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
-
- strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
- savepath += time_str;
- }
- recordingLoopSave(savepath);
-#endif
-
- sessionMediaDisconnectSendMessage(mAudioSession);
-
- if (wait)
- {
- LLSD result;
- do
- {
- LLSD timeoutResult(LLSDMap("session", "timeout"));
-
- result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- if (result.has("session"))
- {
- if (result.has("handle"))
- {
- if (result["handle"] != mAudioSession->mHandle)
- {
- LL_WARNS("Voice") << "Message for session handle \"" << result["handle"] << "\" while waiting for \"" << mAudioSession->mHandle << "\"." << LL_ENDL;
- continue;
- }
- }
-
- std::string message = result["session"].asString();
- if (message == "removed" || message == "timeout")
- break;
- }
- } while (true);
-
- }
- }
- else
- {
- LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("Voice") << "Session " << mAudioSession->mHandle << " already terminated by logout." << LL_ENDL;
- }
-
- sessionStatePtr_t oldSession = mAudioSession;
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); // needs mAudioSession for uri
- mAudioSession.reset();
-
- // The old session may now need to be deleted.
- reapSession(oldSession);
- }
- else
- {
- LL_WARNS("Voice") << "terminateAudioSession(" << wait << ") with NULL mAudioSession" << LL_ENDL;
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
- }
-
-
- // Always reset the terminate request flag when we get here.
- // Some slower PCs have a race condition where they can switch to an incoming P2P call faster than the state machine leaves
- // the region chat.
- mSessionTerminateRequested = false;
-
- bool status=((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !sShuttingDown);
- LL_DEBUGS("Voice") << "exiting"
- << " VoiceEnabled " << mVoiceEnabled
- << " IsInitialized " << mIsInitialized
- << " RelogRequested " << mRelogRequested
- << " ShuttingDown " << (sShuttingDown ? "True" : "False")
- << " returning " << status
- << LL_ENDL;
- return status;
-}
-
-
-typedef enum e_voice_wait_for_channel_state
-{
- VOICE_CHANNEL_STATE_LOGIN = 0, // entry point
- VOICE_CHANNEL_STATE_CHECK_EFFECTS,
- VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING,
- VOICE_CHANNEL_STATE_PROCESS_CHANNEL,
- VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY,
- VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK,
- VOICE_CHANNEL_STATE_LOGOUT,
- VOICE_CHANNEL_STATE_RELOG,
- VOICE_CHANNEL_STATE_DONE,
-} EVoiceWaitForChannelState;
-
-bool LLVivoxVoiceClient::waitForChannel()
-{
- LL_INFOS("Voice") << "Waiting for channel" << LL_ENDL;
-
- EVoiceWaitForChannelState state = VOICE_CHANNEL_STATE_LOGIN;
-
- do
- {
- if (sShuttingDown)
- {
- // terminate() forcefully disconects voice, no need for cleanup
- return false;
- }
-
- switch (state)
- {
- case VOICE_CHANNEL_STATE_LOGIN:
- if (!loginToVivox())
- {
- return false;
- }
- state = VOICE_CHANNEL_STATE_CHECK_EFFECTS;
- break;
-
- case VOICE_CHANNEL_STATE_CHECK_EFFECTS:
- if (LLVoiceClient::instance().getVoiceEffectEnabled())
- {
- retrieveVoiceFonts();
-
- if (sShuttingDown)
- {
- return false;
- }
-
- // Request the set of available voice fonts.
- refreshVoiceEffectLists(false);
- }
-
-#if USE_SESSION_GROUPS
- // Rider: This code is completely unchanged from the original state machine
- // It does not seem to be in active use... but I'd rather not rip it out.
- // create the main session group
- setState(stateCreatingSessionGroup);
- sessionGroupCreateSendMessage();
-#endif
-
- state = VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING;
- break;
-
- case VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING:
- llcoro::suspend();
- state = VOICE_CHANNEL_STATE_PROCESS_CHANNEL;
- break;
-
- case VOICE_CHANNEL_STATE_PROCESS_CHANNEL:
- if (mTuningMode)
- {
- performMicTuning();
- }
- else if (mCaptureBufferMode)
- {
- recordingAndPlaybackMode();
- }
- else if (mProcessChannels && ((mNextAudioSession == NULL) || checkParcelChanged()))
- {
- // the parcel is changed, or we have no pending audio sessions,
- // so try to request the parcel voice info
- // if we have the cap, we move to the appropriate state
- requestParcelVoiceInfo(); //suspends for http reply
- }
- else if (sessionNeedsRelog(mNextAudioSession))
- {
- LL_INFOS("Voice") << "Session requesting reprovision and login." << LL_ENDL;
- requestRelog();
- break;
- }
- else if (mNextAudioSession)
- {
- if (!mNextAudioSession->mIsP2P && !mProcessChannels)
- {
- llcoro::suspend();
- break;
- }
-
- try
- {
- sessionStatePtr_t joinSession = mNextAudioSession;
- mNextAudioSession.reset();
- mIsProcessingChannels = true;
- if (!runSession(joinSession)) //suspends
- {
- mIsProcessingChannels = false;
- LL_DEBUGS("Voice") << "runSession returned false; leaving inner loop" << LL_ENDL;
- break;
- }
- else
- {
- mIsProcessingChannels = false;
- LL_DEBUGS("Voice")
- << "runSession returned true to inner loop"
- << " RelogRequested=" << mRelogRequested
- << " VoiceEnabled=" << mVoiceEnabled
- << LL_ENDL;
- }
- }
- catch (const LLCoros::Stop&)
- {
- LL_DEBUGS("LLVivoxVoiceClient") << "Received a shutdown exception" << LL_ENDL;
- }
- catch (const LLContinueError&)
- {
- LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient");
- }
- catch (...)
- {
- // Ideally for Windows need to log SEH exception instead or to set SEH
- // handlers but bugsplat shows local variables for windows, which should
- // be enough
- LL_WARNS("Voice") << "voiceControlStateMachine crashed in state VOICE_CHANNEL_STATE_PROCESS_CHANNEL"
- << " mRelogRequested " << mRelogRequested
- << " mVoiceEnabled " << mVoiceEnabled
- << " mIsProcessingChannels " << mIsProcessingChannels
- << " mProcessChannels " << mProcessChannels
- << LL_ENDL;
- throw;
- }
- }
-
- state = VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY;
- break;
-
- case VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY:
- if (!mNextAudioSession)
- {
- llcoro::suspendUntilTimeout(1.0);
- }
- state = VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK;
- break;
-
- case VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK:
- if (mVoiceEnabled && !mRelogRequested)
- {
- state = VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING;
- break;
- }
- else
- {
- mIsProcessingChannels = false;
- LL_DEBUGS("Voice")
- << "leaving inner waitForChannel loop"
- << " RelogRequested=" << mRelogRequested
- << " VoiceEnabled=" << mVoiceEnabled
- << LL_ENDL;
- state = VOICE_CHANNEL_STATE_LOGOUT;
- break;
- }
-
- case VOICE_CHANNEL_STATE_LOGOUT:
- logoutOfVivox(true /*bool wait*/);
- if (mRelogRequested)
- {
- state = VOICE_CHANNEL_STATE_RELOG;
- }
- else
- {
- state = VOICE_CHANNEL_STATE_DONE;
- }
- break;
-
- case VOICE_CHANNEL_STATE_RELOG:
- LL_DEBUGS("Voice") << "Relog Requested, restarting provisioning" << LL_ENDL;
- if (!provisionVoiceAccount())
- {
- if (sShuttingDown)
- {
- return false;
- }
- LL_WARNS("Voice") << "provisioning voice failed; giving up" << LL_ENDL;
- giveUp();
- return false;
- }
- if (mVoiceEnabled && mRelogRequested && isGatewayRunning())
- {
- state = VOICE_CHANNEL_STATE_LOGIN;
- }
- else
- {
- state = VOICE_CHANNEL_STATE_DONE;
- }
- break;
- case VOICE_CHANNEL_STATE_DONE:
- LL_DEBUGS("Voice")
- << "exiting"
- << " RelogRequested=" << mRelogRequested
- << " VoiceEnabled=" << mVoiceEnabled
- << LL_ENDL;
- return !sShuttingDown;
- }
- } while (true);
-}
-
-bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
-{
- LL_INFOS("Voice") << "running new voice session " << session->mHandle << LL_ENDL;
-
- if (sShuttingDown || !mProcessChannels)
- {
- return false;
- }
-
- bool joined_session = addAndJoinSession(session);
-
- if (!joined_session)
- {
- notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
-
- if (mSessionTerminateRequested)
- {
- LL_DEBUGS("Voice") << "runSession terminate requested " << LL_ENDL;
- terminateAudioSession(true);
- }
- // if a relog has been requested then addAndJoineSession
- // failed in a spectacular way and we need to back out.
- // If this is not the case then we were simply trying to
- // make a call and the other party rejected it.
- return !mRelogRequested;
- }
-
- notifyParticipantObservers();
- notifyVoiceFontObservers();
-
- LLSD timeoutEvent(LLSDMap("timeout", LLSD::Boolean(true)));
-
- mIsInChannel = true;
- mMuteMicDirty = true;
-
- while (!sShuttingDown
- && mVoiceEnabled
- && isGatewayRunning()
- && !mSessionTerminateRequested
- && !mTuningMode
- && mProcessChannels)
- {
- sendCaptureAndRenderDevices(); // suspends
-
- if (sShuttingDown)
- {
- return false;
- }
-
- if (mSessionTerminateRequested)
- {
- break;
- }
-
- if (mAudioSession && mAudioSession->mParticipantsChanged)
- {
- mAudioSession->mParticipantsChanged = false;
- notifyParticipantObservers();
- }
-
- if (!inSpatialChannel())
- {
- // When in a non-spatial channel, never send positional updates.
- mSpatialCoordsDirty = false;
- }
- else
- {
- updatePosition();
-
- if (checkParcelChanged())
- {
- // *RIDER: I think I can just return here if the parcel has changed
- // and grab the new voice channel from the outside loop.
- //
- // if the parcel has changed, attempted to request the
- // cap for the parcel voice info. If we can't request it
- // then we don't have the cap URL so we do nothing and will
- // recheck next time around
- if (requestParcelVoiceInfo()) // suspends
- { // The parcel voice URI has changed.. break out and reconnect.
- break;
- }
-
- if (sShuttingDown)
- {
- return false;
- }
- }
- // Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position)
- enforceTether();
- }
- sendPositionAndVolumeUpdate();
-
- // Do notifications for expiring Voice Fonts.
- if (mVoiceFontExpiryTimer.hasExpired())
- {
- expireVoiceFonts();
- mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL);
- }
-
- // send any requests to adjust mic and speaker settings if they have changed
- sendLocalAudioUpdates();
-
- mIsInitialized = true;
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, UPDATE_THROTTLE_SECONDS, timeoutEvent);
-
- if (sShuttingDown)
- {
- return false;
- }
-
- if (!result.has("timeout")) // logging the timeout event spams the log
- {
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- }
- if (result.has("session"))
- {
- if (result.has("handle"))
- {
- if (!mAudioSession)
- {
- LL_WARNS("Voice") << "Message for session handle \"" << result["handle"] << "\" while session is not initiated." << LL_ENDL;
- continue;
- }
- if (result["handle"] != mAudioSession->mHandle)
- {
- LL_WARNS("Voice") << "Message for session handle \"" << result["handle"] << "\" while waiting for \"" << mAudioSession->mHandle << "\"." << LL_ENDL;
- continue;
- }
- }
-
- std::string message = result["session"];
-
- if (message == "removed")
- {
- LL_DEBUGS("Voice") << "session removed" << LL_ENDL;
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
- break;
- }
- }
- else if (result.has("login"))
- {
- std::string message = result["login"];
- if (message == "account_logout")
- {
- LL_DEBUGS("Voice") << "logged out" << LL_ENDL;
- mIsLoggedIn = false;
- mRelogRequested = true;
- break;
- }
- }
- }
-
- if (sShuttingDown)
- {
- return false;
- }
-
- mIsInChannel = false;
- LL_DEBUGS("Voice") << "terminating at end of runSession" << LL_ENDL;
- terminateAudioSession(true);
-
- return true;
-}
-
-void LLVivoxVoiceClient::sendCaptureAndRenderDevices()
-{
- if (mCaptureDeviceDirty || mRenderDeviceDirty)
- {
- std::ostringstream stream;
-
- buildSetCaptureDevice(stream);
- buildSetRenderDevice(stream);
-
- if (!stream.str().empty())
- {
- writeString(stream.str());
- }
-
- llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
- }
-}
-
-void LLVivoxVoiceClient::recordingAndPlaybackMode()
-{
- LL_INFOS("Voice") << "In voice capture/playback mode." << LL_ENDL;
-
- while (true)
- {
- LLSD command;
- do
- {
- command = llcoro::suspendUntilEventOn(mVivoxPump);
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(command) << LL_ENDL;
- } while (!command.has("recplay"));
-
- if (command["recplay"].asString() == "quit")
- {
- mCaptureBufferMode = false;
- break;
- }
- else if (command["recplay"].asString() == "record")
- {
- voiceRecordBuffer();
- }
- else if (command["recplay"].asString() == "playback")
- {
- voicePlaybackBuffer();
- }
- }
-
- LL_INFOS("Voice") << "Leaving capture/playback mode." << LL_ENDL;
- mCaptureBufferRecording = false;
- mCaptureBufferRecorded = false;
- mCaptureBufferPlaying = false;
-
- return;
-}
-
-int LLVivoxVoiceClient::voiceRecordBuffer()
-{
- LLSD timeoutResult(LLSDMap("recplay", "stop"));
-
- LL_INFOS("Voice") << "Recording voice buffer" << LL_ENDL;
-
- LLSD result;
-
- captureBufferRecordStartSendMessage();
- notifyVoiceFontObservers();
-
- do
- {
- result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- } while (!result.has("recplay"));
-
- mCaptureBufferRecorded = true;
-
- captureBufferRecordStopSendMessage();
- mCaptureBufferRecording = false;
-
- // Update UI, should really use a separate callback.
- notifyVoiceFontObservers();
-
- return true;
- /*TODO expand return to move directly into play*/
-}
-
-int LLVivoxVoiceClient::voicePlaybackBuffer()
-{
- LLSD timeoutResult(LLSDMap("recplay", "stop"));
-
- LL_INFOS("Voice") << "Playing voice buffer" << LL_ENDL;
-
- LLSD result;
-
- do
- {
- captureBufferPlayStartSendMessage(mPreviewVoiceFont);
-
- // Store the voice font being previewed, so that we know to restart if it changes.
- mPreviewVoiceFontLast = mPreviewVoiceFont;
-
- do
- {
- // Update UI, should really use a separate callback.
- notifyVoiceFontObservers();
-
- result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, CAPTURE_BUFFER_MAX_TIME, timeoutResult);
- LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
- } while (!result.has("recplay"));
-
- if (result["recplay"] == "playback")
- continue; // restart playback... May be a font change.
-
- break;
- } while (true);
-
- // Stop playing.
- captureBufferPlayStopSendMessage();
- mCaptureBufferPlaying = false;
-
- // Update UI, should really use a separate callback.
- notifyVoiceFontObservers();
-
- return true;
-}
-
-
-bool LLVivoxVoiceClient::performMicTuning()
-{
- LL_INFOS("Voice") << "Entering voice tuning mode." << LL_ENDL;
- mIsInTuningMode = true;
-
- while (mTuningMode && !sShuttingDown)
- {
- llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
- }
-
- mIsInTuningMode = false;
-
- //---------------------------------------------------------------------
- return true;
-}
-
-//=========================================================================
-
-void LLVivoxVoiceClient::closeSocket(void)
-{
- mSocket.reset();
- sConnected = false;
- mConnectorEstablished = false;
- mAccountLoggedIn = false;
-}
-
-void LLVivoxVoiceClient::loginSendMessage()
-{
- std::ostringstream stream;
-
- bool autoPostCrashDumps = gSavedSettings.getBOOL("VivoxAutoPostCrashDumps");
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Login.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<AccountName>" << mAccountName << "</AccountName>"
- << "<AccountPassword>" << mAccountPassword << "</AccountPassword>"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>"
- << "<EnableBuddiesAndPresence>false</EnableBuddiesAndPresence>"
- << "<EnablePresencePersistence>0</EnablePresencePersistence>"
- << "<BuddyManagementMode>Application</BuddyManagementMode>"
- << "<ParticipantPropertyFrequency>5</ParticipantPropertyFrequency>"
- << (autoPostCrashDumps?"<AutopostCrashDumps>true</AutopostCrashDumps>":"")
- << "</Request>\n\n\n";
-
- LL_INFOS("Voice") << "Attempting voice login" << LL_ENDL;
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::logout()
-{
- // Ensure that we'll re-request provisioning before logging in again
- mAccountPassword.clear();
- mVoiceAccountServerURI.clear();
-
- logoutSendMessage();
-}
-
-void LLVivoxVoiceClient::logoutSendMessage()
-{
- if(mAccountLoggedIn)
- {
- LL_INFOS("Voice") << "Attempting voice logout" << LL_ENDL;
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Logout.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "</Request>"
- << "\n\n\n";
-
- mAccountLoggedIn = false;
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::sessionGroupCreateSendMessage()
-{
- if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Create.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "<Type>Normal</Type>"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::sessionCreateSendMessage(const sessionStatePtr_t &session, bool startAudio, bool startText)
-{
- S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
- LL_DEBUGS("Voice") << "Requesting create: " << session->mSIPURI
- << " with voice font: " << session->mVoiceFontID << " (" << font_index << ")"
- << LL_ENDL;
-
- session->mCreateInProgress = true;
- if(startAudio)
- {
- session->mMediaConnectInProgress = true;
- }
-
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << session->mSIPURI << "\" action=\"Session.Create.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "<URI>" << session->mSIPURI << "</URI>";
-
- static const std::string allowed_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-._~";
-
- if(!session->mHash.empty())
- {
- stream
- << "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"
- << "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";
- }
-
- stream
- << "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
- << "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
- << "<Name>" << mChannelName << "</Name>"
- << "</Request>\n\n\n";
- LL_WARNS("Voice") << "Session.Create: " << stream.str() << LL_ENDL;
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionGroupAddSessionSendMessage(const sessionStatePtr_t &session, bool startAudio, bool startText)
-{
- LL_DEBUGS("Voice") << "Requesting create: " << session->mSIPURI << LL_ENDL;
-
- S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
- LL_DEBUGS("Voice") << "With voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL;
-
- session->mCreateInProgress = true;
- if(startAudio)
- {
- session->mMediaConnectInProgress = true;
- }
-
- std::string password;
- if(!session->mHash.empty())
- {
- static const std::string allowed_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-._~"
- ;
- password = LLURI::escape(session->mHash, allowed_chars);
- }
-
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << session->mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
- << "<URI>" << session->mSIPURI << "</URI>"
- << "<Name>" << mChannelName << "</Name>"
- << "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
- << "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
- << "<Password>" << password << "</Password>"
- << "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"
- << "</Request>\n\n\n"
- ;
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionMediaConnectSendMessage(const sessionStatePtr_t &session)
-{
- S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
- LL_DEBUGS("Voice") << "Connecting audio to session handle: " << session->mHandle
- << " with voice font: " << session->mVoiceFontID << " (" << font_index << ")"
- << LL_ENDL;
-
- session->mMediaConnectInProgress = true;
-
- std::ostringstream stream;
-
- stream
- << "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"
- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
- << "<Media>Audio</Media>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionTextConnectSendMessage(const sessionStatePtr_t &session)
-{
- LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
-
- std::ostringstream stream;
-
- stream
- << "<Request requestId=\"" << session->mHandle << "\" action=\"Session.TextConnect.1\">"
- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionTerminate()
-{
- mSessionTerminateRequested = true;
-}
-
-void LLVivoxVoiceClient::requestRelog()
-{
- mSessionTerminateRequested = true;
- mRelogRequested = true;
-}
-
-
-void LLVivoxVoiceClient::leaveAudioSession()
-{
- if(mAudioSession)
- {
- LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
-
- if(!mAudioSession->mHandle.empty())
- {
-
-#if RECORD_EVERYTHING
- // HACK: for testing only
- // Save looped recording
- std::string savepath("/tmp/vivoxrecording");
- {
- time_t now = time(NULL);
- const size_t BUF_SIZE = 64;
- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
-
- strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
- savepath += time_str;
- }
- recordingLoopSave(savepath);
-#endif
-
- sessionMediaDisconnectSendMessage(mAudioSession);
- }
- else
- {
- LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
- }
- sessionTerminate();
-}
-
-void LLVivoxVoiceClient::sessionTerminateSendMessage(const sessionStatePtr_t &session)
-{
- std::ostringstream stream;
-
- sessionGroupTerminateSendMessage(session);
- return;
- /*
- LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">"
- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- */
-}
-
-void LLVivoxVoiceClient::sessionGroupTerminateSendMessage(const sessionStatePtr_t &session)
-{
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">"
- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionMediaDisconnectSendMessage(const sessionStatePtr_t &session)
-{
- std::ostringstream stream;
- sessionGroupTerminateSendMessage(session);
- return;
- /*
- LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">"
- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
- << "<Media>Audio</Media>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- */
-
-}
-
-
-void LLVivoxVoiceClient::getCaptureDevicesSendMessage()
-{
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetCaptureDevices.1\">"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::getRenderDevicesSendMessage()
-{
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetRenderDevices.1\">"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::clearCaptureDevices()
-{
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
- mCaptureDevices.clear();
-}
-
-void LLVivoxVoiceClient::addCaptureDevice(const LLVoiceDevice& device)
-{
- LL_DEBUGS("Voice") << "display: '" << device.display_name << "' device: '" << device.full_name << "'" << LL_ENDL;
- mCaptureDevices.push_back(device);
-}
-
-LLVoiceDeviceList& LLVivoxVoiceClient::getCaptureDevices()
-{
- return mCaptureDevices;
-}
-
-void LLVivoxVoiceClient::setCaptureDevice(const std::string& name)
-{
- if(name == "Default")
- {
- if(!mCaptureDevice.empty())
- {
- mCaptureDevice.clear();
- mCaptureDeviceDirty = true;
- }
- }
- else
- {
- if(mCaptureDevice != name)
- {
- mCaptureDevice = name;
- mCaptureDeviceDirty = true;
- }
- }
-}
-void LLVivoxVoiceClient::setDevicesListUpdated(bool state)
-{
- mDevicesListUpdated = state;
-}
-
-void LLVivoxVoiceClient::clearRenderDevices()
-{
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
- mRenderDevices.clear();
-}
-
-void LLVivoxVoiceClient::addRenderDevice(const LLVoiceDevice& device)
-{
- LL_DEBUGS("Voice") << "display: '" << device.display_name << "' device: '" << device.full_name << "'" << LL_ENDL;
- mRenderDevices.push_back(device);
-}
-
-LLVoiceDeviceList& LLVivoxVoiceClient::getRenderDevices()
-{
- return mRenderDevices;
-}
-
-void LLVivoxVoiceClient::setRenderDevice(const std::string& name)
-{
- if(name == "Default")
- {
- if(!mRenderDevice.empty())
- {
- mRenderDevice.clear();
- mRenderDeviceDirty = true;
- }
- }
- else
- {
- if(mRenderDevice != name)
- {
- mRenderDevice = name;
- mRenderDeviceDirty = true;
- }
- }
-
-}
-
-void LLVivoxVoiceClient::tuningStart()
-{
- LL_DEBUGS("Voice") << "Starting tuning" << LL_ENDL;
- mTuningMode = true;
- if (!mIsCoroutineActive)
- {
- LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
- boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
- }
- else if (mIsInChannel)
- {
- LL_DEBUGS("Voice") << "no channel" << LL_ENDL;
- sessionTerminate();
- }
-}
-
-void LLVivoxVoiceClient::tuningStop()
-{
- mTuningMode = false;
- // force a renegotiation.
- mCurrentParcelLocalID = 0;
- mCurrentRegionName = "";
-}
-
-bool LLVivoxVoiceClient::inTuningMode()
-{
- return mIsInTuningMode;
-}
-
-void LLVivoxVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop)
-{
- mTuningAudioFile = name;
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStart.1\">"
- << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
- << "<Loop>" << (loop?"1":"0") << "</Loop>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningRenderStopSendMessage()
-{
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">"
- << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningCaptureStartSendMessage(int loop)
-{
- LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL;
-
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStart.1\">"
- << "<Duration>-1</Duration>"
- << "<LoopToRenderDevice>" << loop << "</LoopToRenderDevice>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningCaptureStopSendMessage()
-{
- LL_DEBUGS("Voice") << "sending CaptureAudioStop" << LL_ENDL;
-
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-
- mTuningEnergy = 0.0f;
-}
-
-void LLVivoxVoiceClient::tuningSetMicVolume(float volume)
-{
- int scaled_volume = scale_mic_volume(volume);
-
- if(scaled_volume != mTuningMicVolume)
- {
- mTuningMicVolume = scaled_volume;
- mTuningMicVolumeDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::tuningSetSpeakerVolume(float volume)
-{
- int scaled_volume = scale_speaker_volume(volume);
-
- if(scaled_volume != mTuningSpeakerVolume)
- {
- mTuningSpeakerVolume = scaled_volume;
- mTuningSpeakerVolumeDirty = true;
- }
-}
-
-float LLVivoxVoiceClient::tuningGetEnergy(void)
-{
- return mTuningEnergy;
-}
-
-bool LLVivoxVoiceClient::deviceSettingsAvailable()
-{
- bool result = true;
-
- if(!sConnected)
- result = false;
-
- if(mRenderDevices.empty())
- result = false;
-
- return result;
-}
-bool LLVivoxVoiceClient::deviceSettingsUpdated()
-{
- bool updated = mDevicesListUpdated;
- if (mDevicesListUpdated)
- {
- // a hot swap event or a polling of the audio devices has been parsed since the last redraw of the input and output device panel.
- mDevicesListUpdated = false; // toggle the setting
- }
- return updated;
-}
-
-void LLVivoxVoiceClient::refreshDeviceLists(bool clearCurrentList)
-{
- if(clearCurrentList)
- {
- clearCaptureDevices();
- clearRenderDevices();
- }
- getCaptureDevicesSendMessage();
- getRenderDevicesSendMessage();
-}
-
-void LLVivoxVoiceClient::daemonDied()
-{
- // The daemon died, so the connection is gone. Reset everything and start over.
- LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL;
-
- //TODO: Try to relaunch the daemon
-}
-
-void LLVivoxVoiceClient::giveUp()
-{
- // All has failed. Clean up and stop trying.
- LL_WARNS("Voice") << "Terminating Voice Service" << LL_ENDL;
- closeSocket();
- cleanUp();
-}
-
-static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
-{
- F32 nat[3], nup[3], nl[3]; // the new at, up, left vectors and the new position and velocity
-// F32 nvel[3];
- F64 npos[3];
-
- // The original XML command was sent like this:
- /*
- << "<Position>"
- << "<X>" << pos[VX] << "</X>"
- << "<Y>" << pos[VZ] << "</Y>"
- << "<Z>" << pos[VY] << "</Z>"
- << "</Position>"
- << "<Velocity>"
- << "<X>" << mAvatarVelocity[VX] << "</X>"
- << "<Y>" << mAvatarVelocity[VZ] << "</Y>"
- << "<Z>" << mAvatarVelocity[VY] << "</Z>"
- << "</Velocity>"
- << "<AtOrientation>"
- << "<X>" << l.mV[VX] << "</X>"
- << "<Y>" << u.mV[VX] << "</Y>"
- << "<Z>" << a.mV[VX] << "</Z>"
- << "</AtOrientation>"
- << "<UpOrientation>"
- << "<X>" << l.mV[VZ] << "</X>"
- << "<Y>" << u.mV[VY] << "</Y>"
- << "<Z>" << a.mV[VZ] << "</Z>"
- << "</UpOrientation>"
- << "<LeftOrientation>"
- << "<X>" << l.mV [VY] << "</X>"
- << "<Y>" << u.mV [VZ] << "</Y>"
- << "<Z>" << a.mV [VY] << "</Z>"
- << "</LeftOrientation>";
- */
-
-#if 1
- // This was the original transform done when building the XML command
- nat[0] = left.mV[VX];
- nat[1] = up.mV[VX];
- nat[2] = at.mV[VX];
-
- nup[0] = left.mV[VZ];
- nup[1] = up.mV[VY];
- nup[2] = at.mV[VZ];
-
- nl[0] = left.mV[VY];
- nl[1] = up.mV[VZ];
- nl[2] = at.mV[VY];
-
- npos[0] = pos.mdV[VX];
- npos[1] = pos.mdV[VZ];
- npos[2] = pos.mdV[VY];
-
-// nvel[0] = vel.mV[VX];
-// nvel[1] = vel.mV[VZ];
-// nvel[2] = vel.mV[VY];
-
- for(int i=0;i<3;++i) {
- at.mV[i] = nat[i];
- up.mV[i] = nup[i];
- left.mV[i] = nl[i];
- pos.mdV[i] = npos[i];
- }
-
- // This was the original transform done in the SDK
- nat[0] = at.mV[2];
- nat[1] = 0; // y component of at vector is always 0, this was up[2]
- nat[2] = -1 * left.mV[2];
-
- // We override whatever the application gives us
- nup[0] = 0; // x component of up vector is always 0
- nup[1] = 1; // y component of up vector is always 1
- nup[2] = 0; // z component of up vector is always 0
-
- nl[0] = at.mV[0];
- nl[1] = 0; // y component of left vector is always zero, this was up[0]
- nl[2] = -1 * left.mV[0];
-
- npos[2] = pos.mdV[2] * -1.0;
- npos[1] = pos.mdV[1];
- npos[0] = pos.mdV[0];
-
- for(int i=0;i<3;++i) {
- at.mV[i] = nat[i];
- up.mV[i] = nup[i];
- left.mV[i] = nl[i];
- pos.mdV[i] = npos[i];
- }
-#else
- // This is the compose of the two transforms (at least, that's what I'm trying for)
- nat[0] = at.mV[VX];
- nat[1] = 0; // y component of at vector is always 0, this was up[2]
- nat[2] = -1 * up.mV[VZ];
-
- // We override whatever the application gives us
- nup[0] = 0; // x component of up vector is always 0
- nup[1] = 1; // y component of up vector is always 1
- nup[2] = 0; // z component of up vector is always 0
-
- nl[0] = left.mV[VX];
- nl[1] = 0; // y component of left vector is always zero, this was up[0]
- nl[2] = -1 * left.mV[VY];
-
- npos[0] = pos.mdV[VX];
- npos[1] = pos.mdV[VZ];
- npos[2] = pos.mdV[VY] * -1.0;
-
- nvel[0] = vel.mV[VX];
- nvel[1] = vel.mV[VZ];
- nvel[2] = vel.mV[VY];
-
- for(int i=0;i<3;++i) {
- at.mV[i] = nat[i];
- up.mV[i] = nup[i];
- left.mV[i] = nl[i];
- pos.mdV[i] = npos[i];
- }
-
-#endif
-}
-
-void LLVivoxVoiceClient::setHidden(bool hidden)
-{
- mHidden = hidden;
-
- if (mHidden && inSpatialChannel())
- {
- // get out of the channel entirely
- leaveAudioSession();
- }
- else
- {
- sendPositionAndVolumeUpdate();
- }
-}
-
-void LLVivoxVoiceClient::sendPositionAndVolumeUpdate(void)
-{
- std::ostringstream stream;
-
- if (mSpatialCoordsDirty && inSpatialChannel())
- {
- LLVector3 l, u, a, vel;
- LLVector3d pos;
-
- mSpatialCoordsDirty = false;
-
- // Always send both speaker and listener positions together.
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Set3DPosition.1\">"
- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>";
-
- stream << "<SpeakerPosition>";
-
- LLMatrix3 avatarRot = mAvatarRot.getMatrix3();
-
-// LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
- l = avatarRot.getLeftRow();
- u = avatarRot.getUpRow();
- a = avatarRot.getFwdRow();
-
- pos = mAvatarPosition;
- vel = mAvatarVelocity;
-
- // SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
- // The old transform is replicated by this function.
- oldSDKTransform(l, u, a, pos, vel);
-
- if (mHidden)
- {
- for (int i=0;i<3;++i)
- {
- pos.mdV[i] = VX_NULL_POSITION;
- }
- }
-
- stream
- << "<Position>"
- << "<X>" << pos.mdV[VX] << "</X>"
- << "<Y>" << pos.mdV[VY] << "</Y>"
- << "<Z>" << pos.mdV[VZ] << "</Z>"
- << "</Position>"
- << "<Velocity>"
- << "<X>" << vel.mV[VX] << "</X>"
- << "<Y>" << vel.mV[VY] << "</Y>"
- << "<Z>" << vel.mV[VZ] << "</Z>"
- << "</Velocity>"
- << "<AtOrientation>"
- << "<X>" << a.mV[VX] << "</X>"
- << "<Y>" << a.mV[VY] << "</Y>"
- << "<Z>" << a.mV[VZ] << "</Z>"
- << "</AtOrientation>"
- << "<UpOrientation>"
- << "<X>" << u.mV[VX] << "</X>"
- << "<Y>" << u.mV[VY] << "</Y>"
- << "<Z>" << u.mV[VZ] << "</Z>"
- << "</UpOrientation>"
- << "<LeftOrientation>"
- << "<X>" << l.mV [VX] << "</X>"
- << "<Y>" << l.mV [VY] << "</Y>"
- << "<Z>" << l.mV [VZ] << "</Z>"
- << "</LeftOrientation>"
- ;
-
- stream << "</SpeakerPosition>";
-
- stream << "<ListenerPosition>";
-
- LLVector3d earPosition;
- LLVector3 earVelocity;
- LLMatrix3 earRot;
-
- switch(mEarLocation)
- {
- case earLocCamera:
- default:
- earPosition = mCameraPosition;
- earVelocity = mCameraVelocity;
- earRot = mCameraRot;
- break;
-
- case earLocAvatar:
- earPosition = mAvatarPosition;
- earVelocity = mAvatarVelocity;
- earRot = avatarRot;
- break;
-
- case earLocMixed:
- earPosition = mAvatarPosition;
- earVelocity = mAvatarVelocity;
- earRot = mCameraRot;
- break;
- }
-
- l = earRot.getLeftRow();
- u = earRot.getUpRow();
- a = earRot.getFwdRow();
-
- pos = earPosition;
- vel = earVelocity;
-
-
- oldSDKTransform(l, u, a, pos, vel);
-
- if (mHidden)
- {
- for (int i=0;i<3;++i)
- {
- pos.mdV[i] = VX_NULL_POSITION;
- }
- }
-
- stream
- << "<Position>"
- << "<X>" << pos.mdV[VX] << "</X>"
- << "<Y>" << pos.mdV[VY] << "</Y>"
- << "<Z>" << pos.mdV[VZ] << "</Z>"
- << "</Position>"
- << "<Velocity>"
- << "<X>" << vel.mV[VX] << "</X>"
- << "<Y>" << vel.mV[VY] << "</Y>"
- << "<Z>" << vel.mV[VZ] << "</Z>"
- << "</Velocity>"
- << "<AtOrientation>"
- << "<X>" << a.mV[VX] << "</X>"
- << "<Y>" << a.mV[VY] << "</Y>"
- << "<Z>" << a.mV[VZ] << "</Z>"
- << "</AtOrientation>"
- << "<UpOrientation>"
- << "<X>" << u.mV[VX] << "</X>"
- << "<Y>" << u.mV[VY] << "</Y>"
- << "<Z>" << u.mV[VZ] << "</Z>"
- << "</UpOrientation>"
- << "<LeftOrientation>"
- << "<X>" << l.mV [VX] << "</X>"
- << "<Y>" << l.mV [VY] << "</Y>"
- << "<Z>" << l.mV [VZ] << "</Z>"
- << "</LeftOrientation>"
- ;
-
- stream << "</ListenerPosition>";
-
- stream << "<ReqDispositionType>1</ReqDispositionType>"; //do not generate responses for update requests
- stream << "</Request>\n\n\n";
- }
-
- if(mAudioSession && (mAudioSession->mVolumeDirty || mAudioSession->mMuteDirty))
- {
- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
-
- mAudioSession->mVolumeDirty = false;
- mAudioSession->mMuteDirty = false;
-
- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
- {
- participantStatePtr_t p(iter->second);
-
- if(p->mVolumeDirty)
- {
- // Can't set volume/mute for yourself
- if(!p->mIsSelf)
- {
- // scale from the range 0.0-1.0 to vivox volume in the range 0-100
- S32 volume = ll_round(p->mVolume / VOLUME_SCALE_VIVOX);
- bool mute = p->mOnMuteList;
-
- if(mute)
- {
- // SetParticipantMuteForMe doesn't work in p2p sessions.
- // If we want the user to be muted, set their volume to 0 as well.
- // This isn't perfect, but it will at least reduce their volume to a minimum.
- volume = 0;
- // Mark the current volume level as set to prevent incoming events
- // changing it to 0, so that we can return to it when unmuting.
- p->mVolumeSet = true;
- }
-
- if(volume == 0)
- {
- mute = true;
- }
-
- LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
-
- // SLIM SDK: Send both volume and mute commands.
-
- // Send a "volume for me" command for the user.
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantVolumeForMe.1\">"
- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
- << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
- << "<Volume>" << volume << "</Volume>"
- << "</Request>\n\n\n";
-
- if(!mAudioSession->mIsP2P)
- {
- // Send a "mute for me" command for the user
- // Doesn't work in P2P sessions
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantMuteForMe.1\">"
- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
- << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
- << "<Mute>" << (mute?"1":"0") << "</Mute>"
- << "<Scope>Audio</Scope>"
- << "</Request>\n\n\n";
- }
- }
-
- p->mVolumeDirty = false;
- }
- }
- }
-
- std::string update(stream.str());
- if(!update.empty())
- {
- LL_DEBUGS("VoiceUpdate") << "sending update " << update << LL_ENDL;
- writeString(update);
- }
-
-}
-
-void LLVivoxVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
-{
- if(mCaptureDeviceDirty)
- {
- LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">"
- << "<CaptureDeviceSpecifier>" << mCaptureDevice << "</CaptureDeviceSpecifier>"
- << "</Request>"
- << "\n\n\n";
-
- mCaptureDeviceDirty = false;
- }
-}
-
-void LLVivoxVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
-{
- if(mRenderDeviceDirty)
- {
- LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetRenderDevice.1\">"
- << "<RenderDeviceSpecifier>" << mRenderDevice << "</RenderDeviceSpecifier>"
- << "</Request>"
- << "\n\n\n";
- mRenderDeviceDirty = false;
- }
-}
-
-void LLVivoxVoiceClient::sendLocalAudioUpdates()
-{
- // Check all of the dirty states and then send messages to those needing to be changed.
- // Tuningmode hands its own mute settings.
- std::ostringstream stream;
-
- if (mMuteMicDirty && !mTuningMode)
- {
- mMuteMicDirty = false;
-
- // Send a local mute command.
-
- LL_INFOS("Voice") << "Sending MuteLocalMic command with parameter " << (mMuteMic ? "true" : "false") << LL_ENDL;
-
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>" << (mMuteMic ? "true" : "false") << "</Value>"
- << "</Request>\n\n\n";
-
- }
-
- if (mSpeakerMuteDirty && !mTuningMode)
- {
- const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0)) ? "true" : "false");
-
- mSpeakerMuteDirty = false;
-
- LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL;
-
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalSpeaker.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>" << muteval << "</Value>"
- << "</Request>\n\n\n";
-
- }
-
- if (mSpeakerVolumeDirty)
- {
- mSpeakerVolumeDirty = false;
-
- LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL;
-
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalSpeakerVolume.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>" << mSpeakerVolume << "</Value>"
- << "</Request>\n\n\n";
-
- }
-
- if (mMicVolumeDirty)
- {
- mMicVolumeDirty = false;
-
- LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL;
-
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalMicVolume.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>" << mMicVolume << "</Value>"
- << "</Request>\n\n\n";
- }
-
-
- if (!stream.str().empty())
- {
- writeString(stream.str());
- }
-}
-
-/**
- * Because of the recurring voice cutout issues (SL-15072) we are going to try
- * to disable the automatic VAD (Voice Activity Detection) and set the associated
- * parameters directly. We will expose them via Debug Settings and that should
- * let us iterate on a collection of values that work for us. Hopefully!
- *
- * From the VIVOX Docs:
- *
- * VadAuto: A flag indicating if the automatic VAD is enabled (1) or disabled (0)
- *
- * VadHangover: The time (in milliseconds) that it takes
- * for the VAD to switch back to silence from speech mode after the last speech
- * frame has been detected.
- *
- * VadNoiseFloor: A dimensionless value between 0 and
- * 20000 (default 576) that controls the maximum level at which the noise floor
- * may be set at by the VAD's noise tracking. Too low of a value will make noise
- * tracking ineffective (A value of 0 disables noise tracking and the VAD then
- * relies purely on the sensitivity property). Too high of a value will make
- * long speech classifiable as noise.
- *
- * VadSensitivity: A dimensionless value between 0 and
- * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds
- * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive,
- * while 100 is 'least sensitive')
- */
-void LLVivoxVoiceClient::setupVADParams(unsigned int vad_auto,
- unsigned int vad_hangover,
- unsigned int vad_noise_floor,
- unsigned int vad_sensitivity)
-{
- std::ostringstream stream;
-
- LL_INFOS("Voice") << "Setting the automatic VAD to "
- << (vad_auto ? "True" : "False")
- << " and discrete values to"
- << " VadHangover = " << vad_hangover
- << ", VadSensitivity = " << vad_sensitivity
- << ", VadNoiseFloor = " << vad_noise_floor
- << LL_ENDL;
-
- // Create a request to set the VAD parameters:
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
- << "<VadAuto>" << vad_auto << "</VadAuto>"
- << "<VadHangover>" << vad_hangover << "</VadHangover>"
- << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>"
- << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>"
- << "</Request>\n\n\n";
-
- if (!stream.str().empty())
- {
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::onVADSettingsChange()
-{
- // pick up the VAD variables (one of which was changed)
- unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
- unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
- unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
- unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
-
- // build a VAD params change request and send it to SLVoice
- setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
-}
-
-/////////////////////////////
-// Response/Event handlers
-
-void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
-{
- LLSD result = LLSD::emptyMap();
-
- if(statusCode == 0)
- {
- // Connector created, move forward.
- if (connectorHandle == LLVivoxSecurity::getInstance()->connectorHandle())
- {
- LL_INFOS("Voice") << "Voice connector succeeded, Vivox SDK version is " << versionID << " connector handle " << connectorHandle << LL_ENDL;
- mVoiceVersion.serverVersion = versionID;
- mConnectorEstablished = true;
- mTerminateDaemon = false;
-
- result["connector"] = LLSD::Boolean(true);
- }
- else
- {
- // This shouldn't happen - we are somehow out of sync with SLVoice
- // or possibly there are two things trying to run SLVoice at once
- // or someone is trying to hack into it.
- LL_WARNS("Voice") << "Connector returned wrong handle "
- << "(" << connectorHandle << ")"
- << " expected (" << LLVivoxSecurity::getInstance()->connectorHandle() << ")"
- << LL_ENDL;
- result["connector"] = LLSD::Boolean(false);
- // Give up.
- mTerminateDaemon = true;
- }
- }
- else if (statusCode == 10028) // web request timeout prior to login
- {
- // this is usually fatal, but a long timeout might work
- result["connector"] = LLSD::Boolean(false);
- result["retry"] = LLSD::Real(CONNECT_ATTEMPT_TIMEOUT);
-
- LL_WARNS("Voice") << "Voice connection failed" << LL_ENDL;
- }
- else if (statusCode == 10006) // name resolution failure - a shorter retry may work
- {
- // some networks have slower DNS, but a short timeout might let it catch up
- result["connector"] = LLSD::Boolean(false);
- result["retry"] = LLSD::Real(CONNECT_DNS_TIMEOUT);
-
- LL_WARNS("Voice") << "Voice connection DNS lookup failed" << LL_ENDL;
- }
- else // unknown failure - give up
- {
- LL_WARNS("Voice") << "Voice connection failure ("<< statusCode << "): " << statusString << LL_ENDL;
- mTerminateDaemon = true;
- result["connector"] = LLSD::Boolean(false);
- }
-
- mVivoxPump.post(result);
-}
-
-void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
-{
- LLSD result = LLSD::emptyMap();
-
- LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
-
- // Status code of 20200 means "bad password". We may want to special-case that at some point.
-
- if ( statusCode == HTTP_UNAUTHORIZED )
- {
- // Login failure which is probably caused by the delay after a user's password being updated.
- LL_INFOS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
- result["login"] = LLSD::String("retry");
- }
- else if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
- result["login"] = LLSD::String("failed");
- }
- else
- {
- // Login succeeded, move forward.
- mAccountLoggedIn = true;
- mNumberOfAliases = numberOfAliases;
- result["login"] = LLSD::String("response_ok");
- }
-
- mVivoxPump.post(result);
-
-}
-
-void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
-{
- sessionStatePtr_t session(findSessionBeingCreatedByURI(requestId));
-
- if(session)
- {
- session->mCreateInProgress = false;
- }
-
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
- if(session)
- {
- session->mErrorStatusCode = statusCode;
- session->mErrorStatusString = statusString;
- if(session == mAudioSession)
- {
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
- ("session", "failed")
- ("reason", LLSD::Integer(statusCode)));
-
- mVivoxPump.post(vivoxevent);
- }
- else
- {
- reapSession(session);
- }
- }
- }
- else
- {
- LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
- if(session)
- {
- setSessionHandle(session, sessionHandle);
- }
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
- ("session", "created"));
-
- mVivoxPump.post(vivoxevent);
- }
-}
-
-void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
-{
- sessionStatePtr_t session(findSessionBeingCreatedByURI(requestId));
-
- if(session)
- {
- session->mCreateInProgress = false;
- }
-
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
- if(session)
- {
- session->mErrorStatusCode = statusCode;
- session->mErrorStatusString = statusString;
- if(session == mAudioSession)
- {
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
- ("session", "failed"));
-
- mVivoxPump.post(vivoxevent);
- }
- else
- {
- reapSession(session);
- }
- }
- }
- else
- {
- LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
- if(session)
- {
- setSessionHandle(session, sessionHandle);
- }
-
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle))
- ("session", "added"));
-
- mVivoxPump.post(vivoxevent);
-
- }
-}
-
-void LLVivoxVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
-{
- sessionStatePtr_t session(findSession(requestId));
- // 1026 is session already has media, somehow mediaconnect was called twice on the same session.
- // set the session info to reflect that the user is already connected.
- if (statusCode == 1026)
- {
- session->mVoiceActive = true;
- session->mMediaConnectInProgress = false;
- session->mMediaStreamState = streamStateConnected;
- //session->mTextStreamState = streamStateConnected;
- session->mErrorStatusCode = 0;
- }
- else if (statusCode != 0)
- {
- LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
- if (session)
- {
- session->mMediaConnectInProgress = false;
- session->mErrorStatusCode = statusCode;
- session->mErrorStatusString = statusString;
- }
- }
- else
- {
- LL_DEBUGS("Voice") << "Session.Connect response received (success)" << LL_ENDL;
- }
-}
-
-void LLVivoxVoiceClient::logoutResponse(int statusCode, std::string &statusString)
-{
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
- // Should this ever fail? do we care if it does?
- }
- LLSD vivoxevent(LLSDMap("logout", LLSD::Boolean(true)));
-
- mVivoxPump.post(vivoxevent);
-}
-
-void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString)
-{
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
- // Should this ever fail? do we care if it does?
- }
-
- sConnected = false;
- mShutdownComplete = true;
-
- LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false)));
-
- mVivoxPump.post(vivoxevent);
-}
-
-void LLVivoxVoiceClient::sessionAddedEvent(
- std::string &uriString,
- std::string &alias,
- std::string &sessionHandle,
- std::string &sessionGroupHandle,
- bool isChannel,
- bool incoming,
- std::string &nameString,
- std::string &applicationString)
-{
- sessionStatePtr_t session;
-
- LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
-
- session = addSession(uriString, sessionHandle);
- if(session)
- {
- session->mGroupHandle = sessionGroupHandle;
- session->mIsChannel = isChannel;
- session->mIncoming = incoming;
- session->mAlias = alias;
-
- // Generate a caller UUID -- don't need to do this for channels
- if(!session->mIsChannel)
- {
- if(IDFromName(session->mSIPURI, session->mCallerID))
- {
- // Normal URI(base64-encoded UUID)
- }
- else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
- {
- // Wrong URI, but an alias is available. Stash the incoming URI as an alternate
- session->mAlternateSIPURI = session->mSIPURI;
-
- // and generate a proper URI from the ID.
- setSessionURI(session, sipURIFromID(session->mCallerID));
- }
- else
- {
- LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL;
- session->mCallerID.generate(session->mSIPURI);
- session->mSynthesizedCallerID = true;
-
- // Can't look up the name in this case -- we have to extract it from the URI.
- std::string namePortion = nameFromsipURI(session->mSIPURI);
- if(namePortion.empty())
- {
- // Didn't seem to be a SIP URI, just use the whole provided name.
- namePortion = nameString;
- }
-
- // Some incoming names may be separated with an underscore instead of a space. Fix this.
- LLStringUtil::replaceChar(namePortion, '_', ' ');
-
- // Act like we just finished resolving the name (this stores it in all the right places)
- avatarNameResolved(session->mCallerID, namePortion);
- }
-
- LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
-
- if(!session->mSynthesizedCallerID)
- {
- // If we got here, we don't have a proper name. Initiate a lookup.
- lookupName(session->mCallerID);
- }
- }
- }
-}
-
-void LLVivoxVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
-{
- LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
-
-#if USE_SESSION_GROUPS
- if(mMainSessionGroupHandle.empty())
- {
- // This is the first (i.e. "main") session group. Save its handle.
- mMainSessionGroupHandle = sessionGroupHandle;
- }
- else
- {
- LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
- }
-#endif
-}
-
-void LLVivoxVoiceClient::joinedAudioSession(const sessionStatePtr_t &session)
-{
- LL_DEBUGS("Voice") << "Joined Audio Session" << LL_ENDL;
- if(mAudioSession != session)
- {
- sessionStatePtr_t oldSession = mAudioSession;
-
- mAudioSession = session;
-
- // The old session may now need to be deleted.
- reapSession(oldSession);
- }
-
- // This is the session we're joining.
- if(mIsJoiningSession)
- {
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle))
- ("session", "joined"));
-
- mVivoxPump.post(vivoxevent);
-
- // Add the current user as a participant here.
- participantStatePtr_t participant(session->addParticipant(sipURIFromName(mAccountName)));
- if(participant)
- {
- participant->mIsSelf = true;
- lookupName(participant->mAvatarID);
-
- LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName
- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
- }
-
- if(!session->mIsChannel)
- {
- // this is a p2p session. Make sure the other end is added as a participant.
- participantStatePtr_t participant(session->addParticipant(session->mSIPURI));
- if(participant)
- {
- if(participant->mAvatarIDValid)
- {
- lookupName(participant->mAvatarID);
- }
- else if(!session->mName.empty())
- {
- participant->mDisplayName = session->mName;
- avatarNameResolved(participant->mAvatarID, session->mName);
- }
-
- // TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
- LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName
- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
- }
- }
- }
-}
-
-void LLVivoxVoiceClient::sessionRemovedEvent(
- std::string &sessionHandle,
- std::string &sessionGroupHandle)
-{
- LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
-
- sessionStatePtr_t session(findSession(sessionHandle));
- if(session)
- {
- leftAudioSession(session);
-
- // This message invalidates the session's handle. Set it to empty.
- clearSessionHandle(session);
-
- // This also means that the session's session group is now empty.
- // Terminate the session group so it doesn't leak.
- sessionGroupTerminateSendMessage(session);
-
- // Reset the media state (we now have no info)
- session->mMediaStreamState = streamStateUnknown;
- //session->mTextStreamState = streamStateUnknown;
-
- // Conditionally delete the session
- reapSession(session);
- }
- else
- {
- // Already reaped this session.
- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
- }
-
-}
-
-void LLVivoxVoiceClient::reapSession(const sessionStatePtr_t &session)
-{
- if(session)
- {
-
- if(session->mCreateInProgress)
- {
- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
- }
- else if(session->mMediaConnectInProgress)
- {
- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
- }
- else if(session == mAudioSession)
- {
- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
- }
- else if(session == mNextAudioSession)
- {
- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
- }
- else
- {
- // We don't have a reason to keep tracking this session, so just delete it.
- LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
- deleteSession(session);
- }
- }
- else
- {
-// LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
- }
-}
-
-// Returns true if the session seems to indicate we've moved to a region on a different voice server
-bool LLVivoxVoiceClient::sessionNeedsRelog(const sessionStatePtr_t &session)
-{
- bool result = false;
-
- if(session)
- {
- // Only make this check for spatial channels (so it won't happen for group or p2p calls)
- if(session->mIsSpatial)
- {
- std::string::size_type atsign;
-
- atsign = session->mSIPURI.find("@");
-
- if(atsign != std::string::npos)
- {
- std::string urihost = session->mSIPURI.substr(atsign + 1);
- if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
- {
- // The hostname in this URI is different from what we expect. This probably means we need to relog.
-
- // We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
- // mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
-
- result = true;
- }
- }
- }
- }
-
- return result;
-}
-
-void LLVivoxVoiceClient::leftAudioSession(const sessionStatePtr_t &session)
-{
- if (mAudioSession == session)
- {
- LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle))
- ("session", "removed"));
-
- mVivoxPump.post(vivoxevent);
- }
-}
-
-void LLVivoxVoiceClient::accountLoginStateChangeEvent(
- std::string &accountHandle,
- int statusCode,
- std::string &statusString,
- int state)
-{
- LLSD levent = LLSD::emptyMap();
-
- /*
- According to Mike S., status codes for this event are:
- login_state_logged_out=0,
- login_state_logged_in = 1,
- login_state_logging_in = 2,
- login_state_logging_out = 3,
- login_state_resetting = 4,
- login_state_error=100
- */
-
- LL_DEBUGS("Voice") << "state change event: " << state << LL_ENDL;
- switch(state)
- {
- case 1:
- levent["login"] = LLSD::String("account_login");
-
- mVivoxPump.post(levent);
- break;
- case 2:
- break;
-
- case 3:
- levent["login"] = LLSD::String("account_loggingOut");
-
- mVivoxPump.post(levent);
- break;
-
- case 4:
- break;
-
- case 100:
- LL_WARNS("Voice") << "account state event error" << LL_ENDL;
- break;
-
- case 0:
- levent["login"] = LLSD::String("account_logout");
-
- mVivoxPump.post(levent);
- break;
-
- default:
- //Used to be a commented out warning
- LL_WARNS("Voice") << "unknown account state event: " << state << LL_ENDL;
- break;
- }
-}
-
-void LLVivoxVoiceClient::mediaCompletionEvent(std::string &sessionGroupHandle, std::string &mediaCompletionType)
-{
- LLSD result;
-
- if (mediaCompletionType == "AuxBufferAudioCapture")
- {
- mCaptureBufferRecording = false;
- result["recplay"] = "end";
- }
- else if (mediaCompletionType == "AuxBufferAudioRender")
- {
- // Ignore all but the last stop event
- if (--mPlayRequestCount <= 0)
- {
- mCaptureBufferPlaying = false;
- result["recplay"] = "end";
-// result["recplay"] = "done";
- }
- }
- else
- {
- LL_WARNS("Voice") << "Unknown MediaCompletionType: " << mediaCompletionType << LL_ENDL;
- }
-
- if (!result.isUndefined())
- mVivoxPump.post(result);
-}
-
-void LLVivoxVoiceClient::mediaStreamUpdatedEvent(
- std::string &sessionHandle,
- std::string &sessionGroupHandle,
- int statusCode,
- std::string &statusString,
- int state,
- bool incoming)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
-
- LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
-
- if(session)
- {
- // We know about this session
-
- // Save the state for later use
- session->mMediaStreamState = state;
-
- switch(statusCode)
- {
- case 0:
- case HTTP_OK:
- // generic success
- // Don't change the saved error code (it may have been set elsewhere)
- break;
- default:
- // save the status code for later
- session->mErrorStatusCode = statusCode;
- break;
- }
-
- switch(state)
- {
- case streamStateDisconnecting:
- case streamStateIdle:
- // Standard "left audio session", Vivox state 'disconnected'
- session->mVoiceActive = false;
- session->mMediaConnectInProgress = false;
- leftAudioSession(session);
- break;
-
- case streamStateConnected:
- session->mVoiceActive = true;
- session->mMediaConnectInProgress = false;
- joinedAudioSession(session);
- case streamStateConnecting: // do nothing, but prevents a warning getting into the logs.
- break;
-
- case streamStateRinging:
- if(incoming)
- {
- // Send the voice chat invite to the GUI layer
- // TODO: Question: Should we correlate with the mute list here?
- session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
- session->mVoiceInvitePending = true;
- if(session->mName.empty())
- {
- lookupName(session->mCallerID);
- }
- else
- {
- // Act like we just finished resolving the name
- avatarNameResolved(session->mCallerID, session->mName);
- }
- }
- break;
-
- default:
- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
- break;
-
- }
-
- }
- else
- {
- // session disconnectintg and disconnected events arriving after we have already left the session.
- LL_DEBUGS("Voice") << "session " << sessionHandle << " not found"<< LL_ENDL;
- }
-}
-
-void LLVivoxVoiceClient::participantAddedEvent(
- std::string &sessionHandle,
- std::string &sessionGroupHandle,
- std::string &uriString,
- std::string &alias,
- std::string &nameString,
- std::string &displayNameString,
- int participantType)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
- if(session)
- {
- participantStatePtr_t participant(session->addParticipant(uriString));
- if(participant)
- {
- participant->mAccountName = nameString;
-
- LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName
- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-
- if(participant->mAvatarIDValid)
- {
- // Initiate a lookup
- lookupName(participant->mAvatarID);
- }
- else
- {
- // If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
- std::string namePortion = nameFromsipURI(uriString);
- if(namePortion.empty())
- {
- // Problem with the SIP URI, fall back to the display name
- namePortion = displayNameString;
- }
- if(namePortion.empty())
- {
- // Problems with both of the above, fall back to the account name
- namePortion = nameString;
- }
-
- // Set the display name (which is a hint to the active speakers window not to do its own lookup)
- participant->mDisplayName = namePortion;
- avatarNameResolved(participant->mAvatarID, namePortion);
- }
- }
- }
-}
-
-void LLVivoxVoiceClient::participantRemovedEvent(
- std::string &sessionHandle,
- std::string &sessionGroupHandle,
- std::string &uriString,
- std::string &alias,
- std::string &nameString)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
- if(session)
- {
- participantStatePtr_t participant(session->findParticipant(uriString));
- if(participant)
- {
- session->removeParticipant(participant);
- }
- else
- {
- LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
- }
- }
- else
- {
- // a late arriving event on a session we have already left.
- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
- }
-}
-
-
-void LLVivoxVoiceClient::participantUpdatedEvent(
- std::string &sessionHandle,
- std::string &sessionGroupHandle,
- std::string &uriString,
- std::string &alias,
- bool isModeratorMuted,
- bool isSpeaking,
- int volume,
- F32 energy)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
- if(session)
- {
- participantStatePtr_t participant(session->findParticipant(uriString));
-
- if(participant)
- {
- //LL_INFOS("Voice") << "Participant Update for " << participant->mDisplayName << LL_ENDL;
-
- participant->mIsSpeaking = isSpeaking;
- participant->mIsModeratorMuted = isModeratorMuted;
-
- // SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
- if (isSpeaking)
- {
- participant->mSpeakingTimeout.reset();
- participant->mPower = energy;
- }
- else
- {
- participant->mPower = 0.0f;
- }
-
- // Ignore incoming volume level if it has been explicitly set, or there
- // is a volume or mute change pending.
- if ( !participant->mVolumeSet && !participant->mVolumeDirty)
- {
- participant->mVolume = (F32)volume * VOLUME_SCALE_VIVOX;
- }
-
- // *HACK: mantipov: added while working on EXT-3544
- /*
- Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE
- LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER.
-
- participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted
- Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug.
- Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates.
-
- But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post()
- voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
- and event is not fired.
-
- So, we have to call LLSpeakerMgr::update() here.
- */
- LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
-
- // ignore session ID of local chat
- if (voice_cnl && voice_cnl->getSessionID().notNull())
- {
- LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID());
- if (speaker_manager)
- {
- speaker_manager->update(true);
-
- // also initialize voice moderate_mode depend on Agent's participant. See EXT-6937.
- // *TODO: remove once a way to request the current voice channel moderation mode is implemented.
- if (gAgent.getID() == participant->mAvatarID)
- {
- speaker_manager->initVoiceModerateMode();
- }
- }
- }
- }
- else
- {
- LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
- }
-}
-
-void LLVivoxVoiceClient::messageEvent(
- std::string &sessionHandle,
- std::string &uriString,
- std::string &alias,
- std::string &messageHeader,
- std::string &messageBody,
- std::string &applicationString)
-{
- LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
-// LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
-
- LL_INFOS("Voice") << "Vivox raw message:" << std::endl << messageBody << LL_ENDL;
-
- if(messageHeader.find(HTTP_CONTENT_TEXT_HTML) != std::string::npos)
- {
- std::string message;
-
- {
- const std::string startMarker = "<body";
- const std::string startMarker2 = ">";
- const std::string endMarker = "</body>";
- const std::string startSpan = "<span";
- const std::string endSpan = "</span>";
- std::string::size_type start;
- std::string::size_type end;
-
- // Default to displaying the raw string, so the message gets through.
- message = messageBody;
-
- // Find the actual message text within the XML fragment
- start = messageBody.find(startMarker);
- start = messageBody.find(startMarker2, start);
- end = messageBody.find(endMarker);
-
- if(start != std::string::npos)
- {
- start += startMarker2.size();
-
- if(end != std::string::npos)
- end -= start;
-
- message.assign(messageBody, start, end);
- }
- else
- {
- // Didn't find a <body>, try looking for a <span> instead.
- start = messageBody.find(startSpan);
- start = messageBody.find(startMarker2, start);
- end = messageBody.find(endSpan);
-
- if(start != std::string::npos)
- {
- start += startMarker2.size();
-
- if(end != std::string::npos)
- end -= start;
-
- message.assign(messageBody, start, end);
- }
- }
- }
-
-// LL_DEBUGS("Voice") << " raw message = \n" << message << LL_ENDL;
-
- // strip formatting tags
- {
- std::string::size_type start;
- std::string::size_type end;
-
- while((start = message.find('<')) != std::string::npos)
- {
- if((end = message.find('>', start + 1)) != std::string::npos)
- {
- // Strip out the tag
- message.erase(start, (end + 1) - start);
- }
- else
- {
- // Avoid an infinite loop
- break;
- }
- }
- }
-
- // Decode ampersand-escaped chars
- {
- std::string::size_type mark = 0;
-
- // The text may contain text encoded with &lt;, &gt;, and &amp;
- mark = 0;
- while((mark = message.find("&lt;", mark)) != std::string::npos)
- {
- message.replace(mark, 4, "<");
- mark += 1;
- }
-
- mark = 0;
- while((mark = message.find("&gt;", mark)) != std::string::npos)
- {
- message.replace(mark, 4, ">");
- mark += 1;
- }
-
- mark = 0;
- while((mark = message.find("&amp;", mark)) != std::string::npos)
- {
- message.replace(mark, 5, "&");
- mark += 1;
- }
- }
-
- // strip leading/trailing whitespace (since we always seem to get a couple newlines)
- LLStringUtil::trim(message);
-
-// LL_DEBUGS("Voice") << " stripped message = \n" << message << LL_ENDL;
-
- sessionStatePtr_t session(findSession(sessionHandle));
- if(session)
- {
- bool is_do_not_disturb = gAgent.isDoNotDisturb();
- bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
- bool is_linden = LLMuteList::isLinden(session->mName);
- LLChat chat;
-
- chat.mMuted = is_muted && !is_linden;
-
- if(!chat.mMuted)
- {
- chat.mFromID = session->mCallerID;
- chat.mFromName = session->mName;
- chat.mSourceType = CHAT_SOURCE_AGENT;
-
- if(is_do_not_disturb && !is_linden)
- {
- // TODO: Question: Return do not disturb mode response here? Or maybe when session is started instead?
- }
-
- LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
- LLIMMgr::getInstance()->addMessage(session->mIMSessionID,
- session->mCallerID,
- session->mName.c_str(),
- message.c_str(),
- false,
- LLStringUtil::null, // default arg
- IM_NOTHING_SPECIAL, // default arg
- 0, // default arg
- LLUUID::null, // default arg
- LLVector3::zero); // default arg
- }
- }
- }
-}
-
-void LLVivoxVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
-
- if(session)
- {
- participantStatePtr_t participant(session->findParticipant(uriString));
- if(participant)
- {
- if (!stricmp(notificationType.c_str(), "Typing"))
- {
- // Other end started typing
- // TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
- // It requires some info for the message, which we don't have here.
- }
- else if (!stricmp(notificationType.c_str(), "NotTyping"))
- {
- // Other end stopped typing
- // TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
- // It requires some info for the message, which we don't have here.
- }
- else
- {
- LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
- }
-}
-
-void LLVivoxVoiceClient::voiceServiceConnectionStateChangedEvent(int statusCode, std::string &statusString, std::string &build_id)
-{
- // We don't generally need to process this. However, one occurence is when we first connect, and so it is the
- // earliest opportunity to learn what we're connected to.
- if (statusCode)
- {
- LL_WARNS("Voice") << "VoiceServiceConnectionStateChangedEvent statusCode: " << statusCode <<
- "statusString: " << statusString << LL_ENDL;
- return;
- }
- if (build_id.empty())
- {
- return;
- }
- mVoiceVersion.mBuildVersion = build_id;
-}
-
-void LLVivoxVoiceClient::auxAudioPropertiesEvent(F32 energy)
-{
- LL_DEBUGS("VoiceEnergy") << "got energy " << energy << LL_ENDL;
- mTuningEnergy = energy;
-}
-
-void LLVivoxVoiceClient::muteListChanged()
-{
- // The user's mute list has been updated. Go through the current participant list and sync it with the mute list.
- if(mAudioSession)
- {
- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
-
- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
- {
- participantStatePtr_t p(iter->second);
-
- // Check to see if this participant is on the mute list already
- if(p->updateMuteState())
- mAudioSession->mVolumeDirty = true;
- }
- }
-}
-
-/////////////////////////////
-// Managing list of participants
-LLVivoxVoiceClient::participantState::participantState(const std::string &uri) :
- mURI(uri),
- mPTT(false),
- mIsSpeaking(false),
- mIsModeratorMuted(false),
- mLastSpokeTimestamp(0.f),
- mPower(0.f),
- mVolume(LLVoiceClient::VOLUME_DEFAULT),
- mUserVolume(0),
- mOnMuteList(false),
- mVolumeSet(false),
- mVolumeDirty(false),
- mAvatarIDValid(false),
- mIsSelf(false)
-{
-}
-
-LLVivoxVoiceClient::participantStatePtr_t LLVivoxVoiceClient::sessionState::addParticipant(const std::string &uri)
-{
- participantStatePtr_t result;
- bool useAlternateURI = false;
-
- // Note: this is mostly the body of LLVivoxVoiceClient::sessionState::findParticipant(), but since we need to know if it
- // matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
- {
- participantMap::iterator iter = mParticipantsByURI.find(uri);
-
- if(iter == mParticipantsByURI.end())
- {
- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
- {
- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
- // Use mSIPURI instead, since it will be properly encoded.
- iter = mParticipantsByURI.find(mSIPURI);
- useAlternateURI = true;
- }
- }
-
- if(iter != mParticipantsByURI.end())
- {
- result = iter->second;
- }
- }
-
- if(!result)
- {
- // participant isn't already in one list or the other.
- result = std::make_shared<participantState>(useAlternateURI?mSIPURI:uri);
- mParticipantsByURI.insert(participantMap::value_type(result->mURI, result));
- mParticipantsChanged = true;
-
- // Try to do a reverse transform on the URI to get the GUID back.
- {
- LLUUID id;
- if(LLVivoxVoiceClient::getInstance()->IDFromName(result->mURI, id))
- {
- result->mAvatarIDValid = true;
- result->mAvatarID = id;
- }
- else
- {
- // Create a UUID by hashing the URI, but do NOT set mAvatarIDValid.
- // This indicates that the ID will not be in the name cache.
- result->mAvatarID.generate(uri);
- }
- }
-
- if(result->updateMuteState())
- {
- mMuteDirty = true;
- }
-
- mParticipantsByUUID.insert(participantUUIDMap::value_type(result->mAvatarID, result));
-
- if (LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume))
- {
- result->mVolumeDirty = true;
- mVolumeDirty = true;
- }
-
- LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
- }
-
- return result;
-}
-
-bool LLVivoxVoiceClient::participantState::updateMuteState()
-{
- bool result = false;
-
- bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
- if(mOnMuteList != isMuted)
- {
- mOnMuteList = isMuted;
- mVolumeDirty = true;
- result = true;
- }
- return result;
-}
-
-bool LLVivoxVoiceClient::participantState::isAvatar()
-{
- return mAvatarIDValid;
-}
-
-void LLVivoxVoiceClient::sessionState::removeParticipant(const LLVivoxVoiceClient::participantStatePtr_t &participant)
-{
- if(participant)
- {
- participantMap::iterator iter = mParticipantsByURI.find(participant->mURI);
- participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(participant->mAvatarID);
-
- LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
-
- if(iter == mParticipantsByURI.end())
- {
- LL_WARNS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
- }
- else if(iter2 == mParticipantsByUUID.end())
- {
- LL_WARNS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
- }
- else if(iter->second != iter2->second)
- {
- LL_WARNS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
- }
- else
- {
- mParticipantsByURI.erase(iter);
- mParticipantsByUUID.erase(iter2);
-
- mParticipantsChanged = true;
- }
- }
-}
-
-void LLVivoxVoiceClient::sessionState::removeAllParticipants()
-{
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
-
- while(!mParticipantsByURI.empty())
- {
- removeParticipant(mParticipantsByURI.begin()->second);
- }
-
- if(!mParticipantsByUUID.empty())
- {
- LL_WARNS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL;
- }
-}
-
-/*static*/
-void LLVivoxVoiceClient::sessionState::VerifySessions()
-{
- std::set<wptr_t>::iterator it = mSession.begin();
- while (it != mSession.end())
- {
- if ((*it).expired())
- {
- LL_WARNS("Voice") << "Expired session found! removing" << LL_ENDL;
- it = mSession.erase(it);
- }
- else
- ++it;
- }
-}
-
-
-void LLVivoxVoiceClient::getParticipantList(std::set<LLUUID> &participants)
-{
- if(mProcessChannels && mAudioSession)
- {
- for(participantUUIDMap::iterator iter = mAudioSession->mParticipantsByUUID.begin();
- iter != mAudioSession->mParticipantsByUUID.end();
- iter++)
- {
- participants.insert(iter->first);
- }
- }
-}
-
-bool LLVivoxVoiceClient::isParticipant(const LLUUID &speaker_id)
-{
- if(mProcessChannels && mAudioSession)
- {
- return (mAudioSession->mParticipantsByUUID.find(speaker_id) != mAudioSession->mParticipantsByUUID.end());
- }
- return false;
-}
-
-
-LLVivoxVoiceClient::participantStatePtr_t LLVivoxVoiceClient::sessionState::findParticipant(const std::string &uri)
-{
- participantStatePtr_t result;
-
- participantMap::iterator iter = mParticipantsByURI.find(uri);
-
- if(iter == mParticipantsByURI.end())
- {
- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
- {
- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
- // Look up the other URI
- iter = mParticipantsByURI.find(mSIPURI);
- }
- }
-
- if(iter != mParticipantsByURI.end())
- {
- result = iter->second;
- }
-
- return result;
-}
-
-LLVivoxVoiceClient::participantStatePtr_t LLVivoxVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
-{
- participantStatePtr_t result;
- participantUUIDMap::iterator iter = mParticipantsByUUID.find(id);
-
- if(iter != mParticipantsByUUID.end())
- {
- result = iter->second;
- }
-
- return result;
-}
-
-LLVivoxVoiceClient::participantStatePtr_t LLVivoxVoiceClient::findParticipantByID(const LLUUID& id)
-{
- participantStatePtr_t result;
-
- if(mAudioSession)
- {
- result = mAudioSession->findParticipantByID(id);
- }
-
- return result;
-}
-
-
-
-// Check for parcel boundary crossing
-bool LLVivoxVoiceClient::checkParcelChanged(bool update)
-{
- LLViewerRegion *region = gAgent.getRegion();
- LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-
- if(region && parcel)
- {
- S32 parcelLocalID = parcel->getLocalID();
- std::string regionName = region->getName();
-
- // LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL;
-
- // The region name starts out empty and gets filled in later.
- // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
- // If either is empty, wait for the next time around.
- if(!regionName.empty())
- {
- if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName))
- {
- // We have changed parcels. Initiate a parcel channel lookup.
- if (update)
- {
- mCurrentParcelLocalID = parcelLocalID;
- mCurrentRegionName = regionName;
- }
- return true;
- }
- }
- }
- return false;
-}
-
-bool LLVivoxVoiceClient::switchChannel(
- std::string uri,
- bool spatial,
- bool no_reconnect,
- bool is_p2p,
- std::string hash)
-{
- bool needsSwitch = !mIsInChannel;
-
- if (mIsInChannel)
- {
- if (mSessionTerminateRequested)
- {
- // If a terminate has been requested, we need to compare against where the URI we're already headed to.
- if(mNextAudioSession)
- {
- if (mNextAudioSession->mSIPURI != uri)
- {
- needsSwitch = true;
- }
- }
- else
- {
- // mNextAudioSession is null -- this probably means we're on our way back to spatial.
- if(!uri.empty())
- {
- // We do want to process a switch in this case.
- needsSwitch = true;
- }
- }
- }
- else
- {
- // Otherwise, compare against the URI we're in now.
- if(mAudioSession)
- {
- if(mAudioSession->mSIPURI != uri)
- {
- needsSwitch = true;
- }
- }
- else
- {
- if(!uri.empty())
- {
- // mAudioSession is null -- it's not clear what case would cause this.
- // For now, log it as a warning and see if it ever crops up.
- LL_WARNS("Voice") << "No current audio session... Forcing switch" << LL_ENDL;
- needsSwitch = true;
- }
- }
- }
- }
-
- if(needsSwitch)
- {
- if(uri.empty())
- {
- // Leave any channel we may be in
- LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
-
- sessionStatePtr_t oldSession = mNextAudioSession;
- mNextAudioSession.reset();
-
- // The old session may now need to be deleted.
- reapSession(oldSession);
-
- // If voice was on, turn it off
- if (LLVoiceClient::getInstance()->getUserPTTState())
- {
- LLVoiceClient::getInstance()->setUserPTTState(false);
- }
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
- }
- else
- {
- LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
-
- mNextAudioSession = addSession(uri);
- mNextAudioSession->mHash = hash;
- mNextAudioSession->mIsSpatial = spatial;
- mNextAudioSession->mReconnect = !no_reconnect;
- mNextAudioSession->mIsP2P = is_p2p;
- }
-
- if (mIsInChannel)
- {
- // If we're already in a channel, or if we're joining one, terminate
- // so we can rejoin with the new session data.
- sessionTerminate();
- }
- }
-
- return needsSwitch;
-}
-
-void LLVivoxVoiceClient::joinSession(const sessionStatePtr_t &session)
-{
- mNextAudioSession = session;
-
- if (mIsInChannel)
- {
- // If we're already in a channel, or if we're joining one, terminate
- // so we can rejoin with the new session data.
- sessionTerminate();
- }
-}
-
-void LLVivoxVoiceClient::setNonSpatialChannel(const LLSD& channelInfo, bool notify_on_first_join, bool hangup_on_last_leave)
-{
- switchChannel(channelInfo["channel_uri"].asString(), false, false, false, channelInfo["channel_credentials"].asString());
-}
-
-bool LLVivoxVoiceClient::setSpatialChannel(const LLSD& channelInfo)
-{
- mSpatialSessionURI = channelInfo["channel_uri"].asString();
- mSpatialSessionCredentials = channelInfo["channel_credentials"].asString();
- if (!mProcessChannels)
- {
- // we're not even processing channels (another provider is) so
- // save the credentials aside and exit
- return false;
- }
-
- LL_DEBUGS("Voice") << "got spatial channel uri: \"" << mSpatialSessionURI << "\"" << LL_ENDL;
-
- if((mIsInChannel && mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
- {
- // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels.
- LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
- return false;
- }
- else
- {
- return switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
- }
-}
-
-void LLVivoxVoiceClient::callUser(const LLUUID &uuid)
-{
- std::string userURI = sipURIFromID(uuid);
- mProcessChannels = true;
-
- switchChannel(userURI, false, true, true);
-}
-
-void LLVivoxVoiceClient::hangup() { leaveChannel(); }
-
-
-LLVoiceP2PIncomingCallInterfacePtr LLVivoxVoiceClient::getIncomingCallInterface(const LLSD &voice_call_info)
-{
- return std::make_shared<LLVivoxVoiceP2PIncomingCall>(voice_call_info);
-}
-
-bool LLVivoxVoiceClient::answerInvite(const std::string &sessionHandle)
-{
- // this is only ever used to answer incoming p2p call invites.
-
- sessionStatePtr_t session(findSession(sessionHandle));
- if (session)
- {
- session->mIsSpatial = false;
- session->mReconnect = false;
- session->mIsP2P = true;
- mProcessChannels = true;
- joinSession(session);
- return true;
- }
-
- return false;
-}
-
-void LLVivoxVoiceClient::declineInvite(const std::string &sessionHandle)
-{
- sessionStatePtr_t session(findSession(sessionHandle));
- if (session)
- {
- sessionMediaDisconnectSendMessage(session);
- }
-}
-
-bool LLVivoxVoiceClient::isVoiceWorking() const
-{
-
- //Added stateSessionTerminated state to avoid problems with call in parcels with disabled voice (EXT-4758)
- // Condition with joining spatial num was added to take into account possible problems with connection to voice
- // server(EXT-4313). See bug descriptions and comments for MAX_NORMAL_JOINING_SPATIAL_NUM for more info.
- return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && mIsLoggedIn;
-}
-
-// Returns true if the indicated participant in the current audio session is really an SL avatar.
-// Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls.
-bool LLVivoxVoiceClient::isParticipantAvatar(const LLUUID &id)
-{
- bool result = true;
- sessionStatePtr_t session(findSession(id));
-
- if(session)
- {
- // this is a p2p session with the indicated caller, or the session with the specified UUID.
- if(session->mSynthesizedCallerID)
- result = false;
- }
- else
- {
- // Didn't find a matching session -- check the current audio session for a matching participant
- if(mAudioSession)
- {
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- result = participant->isAvatar();
- }
- }
- }
-
- return result;
-}
-
-// Returns true if calling back the session URI after the session has closed is possible.
-// Currently this will be false only for PSTN P2P calls.
-bool LLVivoxVoiceClient::isSessionCallBackPossible(const LLUUID &session_id)
-{
- bool result = true;
- sessionStatePtr_t session(findSession(session_id));
-
- if(session != NULL)
- {
- result = session->isCallBackPossible();
- }
-
- return result;
-}
-
-// Returns true if the session can accept text IM's.
-// Currently this will be false only for PSTN P2P calls.
-bool LLVivoxVoiceClient::isSessionTextIMPossible(const LLUUID &session_id)
-{
- bool result = true;
- sessionStatePtr_t session(findSession(session_id));
-
- if(session != NULL)
- {
- result = session->isTextIMPossible();
- }
-
- return result;
-}
-
-void LLVivoxVoiceClient::leaveNonSpatialChannel()
-{
- LL_DEBUGS("Voice") << "Request to leave spacial channel." << LL_ENDL;
-
- // Make sure we don't rejoin the current session.
- sessionStatePtr_t oldNextSession(mNextAudioSession);
- mNextAudioSession.reset();
-
- // Most likely this will still be the current session at this point, but check it anyway.
- reapSession(oldNextSession);
-
- verifySessionState();
-
- sessionTerminate();
-}
-
-void LLVivoxVoiceClient::processChannels(bool process)
-{
- mCurrentParcelLocalID = -1;
- mCurrentRegionName.clear();
- mProcessChannels = process;
-}
-
-bool LLVivoxVoiceClient::isCurrentChannel(const LLSD &channelInfo)
-{
- if (!mProcessChannels
- || (channelInfo.has("voice_server_type") && channelInfo["voice_server_type"].asString() != VIVOX_VOICE_SERVER_TYPE)
- || mSessionTerminateRequested)
- {
- return false;
- }
- // favor the next audio session, as that's the one we're bringing up.
- sessionStatePtr_t session = mNextAudioSession;
- if (!session)
- {
- session = mAudioSession;
- }
- if (session)
- {
- if (!channelInfo["session_handle"].asString().empty())
- {
- return session->mHandle == channelInfo["session_handle"].asString();
- }
- return channelInfo["channel_uri"].asString() == session->mSIPURI;
- }
- return false;
-}
-
-bool LLVivoxVoiceClient::compareChannels(const LLSD& channelInfo1, const LLSD& channelInfo2)
-{
- return (!channelInfo1.has("voice_server_type") || (channelInfo1["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
- (!channelInfo2.has("voice_server_type") || (channelInfo2["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
- (channelInfo1["channel_uri"] == channelInfo2["channel_uri"]);
-}
-
-bool LLVivoxVoiceClient::inProximalChannel()
-{
- bool result = false;
-
- if (mIsInChannel && !mSessionTerminateRequested)
- {
- result = inSpatialChannel();
- }
-
- return result;
-}
-
-std::string LLVivoxVoiceClient::sipURIFromID(const LLUUID &id) const
-{
- std::string result;
- result = "sip:";
- result += nameFromID(id);
- result += "@";
- result += mVoiceSIPURIHostName;
-
- return result;
-}
-
-LLSD LLVivoxVoiceClient::getP2PChannelInfoTemplate(const LLUUID& id) const
-{
- LLSD result;
- result["channel_uri"] = sipURIFromID(id);
- result["voice_server_type"] = VIVOX_VOICE_SERVER_TYPE;
- return result;
-}
-
-std::string LLVivoxVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
-{
- std::string result;
- if(avatar)
- {
- result = "sip:";
- result += nameFromID(avatar->getID());
- result += "@";
- result += mVoiceSIPURIHostName;
- }
-
- return result;
-}
-
-std::string LLVivoxVoiceClient::nameFromID(const LLUUID &uuid) const
-{
- std::string result;
-
- if (uuid.isNull()) {
- //VIVOX, the uuid emtpy look for the mURIString and return that instead.
- //result.assign(uuid.mURIStringName);
- LLStringUtil::replaceChar(result, '_', ' ');
- return result;
- }
- // Prepending this apparently prevents conflicts with reserved names inside the vivox code.
- result = "x";
-
- // Base64 encode and replace the pieces of base64 that are less compatible
- // with e-mail local-parts.
- // See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet"
- result += LLBase64::encode(uuid.mData, UUID_BYTES);
- LLStringUtil::replaceChar(result, '+', '-');
- LLStringUtil::replaceChar(result, '/', '_');
-
- // If you need to transform a GUID to this form on the macOS command line, this will do so:
- // echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
-
- // The reverse transform can be done with:
- // echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
-
- return result;
-}
-
-bool LLVivoxVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
-{
- bool result = false;
-
- // SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
- // If it is, convert to a bare name before doing the transform.
- std::string name = nameFromsipURI(inName);
-
- // Doesn't look like a SIP URI, assume it's an actual name.
- if(name.empty())
- name = inName;
-
- // This will only work if the name is of the proper form.
- // As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
- // "xFnPP04IpREWNkuw1cOXlhw=="
-
- if((name.size() == 25) && (name[0] == 'x') && (name[23] == '=') && (name[24] == '='))
- {
- // The name appears to have the right form.
-
- // Reverse the transforms done by nameFromID
- std::string temp = name;
- LLStringUtil::replaceChar(temp, '-', '+');
- LLStringUtil::replaceChar(temp, '_', '/');
-
- U8 rawuuid[UUID_BYTES + 1];
- int len = apr_base64_decode_binary(rawuuid, temp.c_str() + 1);
- if(len == UUID_BYTES)
- {
- // The decode succeeded. Stuff the bits into the result's UUID
- memcpy(uuid.mData, rawuuid, UUID_BYTES);
- result = true;
- }
- }
-
- if(!result)
- {
- // VIVOX: not a standard account name, just copy the URI name mURIString field
- // and hope for the best. bpj
- uuid.setNull(); // VIVOX, set the uuid field to nulls
- }
-
- return result;
-}
-
-std::string LLVivoxVoiceClient::sipURIFromName(std::string &name)
-{
- std::string result;
- result = "sip:";
- result += name;
- result += "@";
- result += mVoiceSIPURIHostName;
-
-// LLStringUtil::toLower(result);
-
- return result;
-}
-
-std::string LLVivoxVoiceClient::nameFromsipURI(const std::string &uri)
-{
- std::string result;
-
- std::string::size_type sipOffset, atOffset;
- sipOffset = uri.find("sip:");
- atOffset = uri.find("@");
- if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
- {
- result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
- }
-
- return result;
-}
-
-bool LLVivoxVoiceClient::inSpatialChannel(void)
-{
- bool result = false;
-
- if(mAudioSession)
- {
- result = mAudioSession->mIsSpatial;
- }
-
- return result;
-}
-
-
-LLSD LLVivoxVoiceClient::getAudioSessionChannelInfo()
-{
- LLSD result;
-
- if (mAudioSession)
- {
- result = mAudioSession->getVoiceChannelInfo();
- }
-
- return result;
-}
-
-std::string LLVivoxVoiceClient::getAudioSessionHandle()
-{
- std::string result;
-
- if(mAudioSession)
- result = mAudioSession->mHandle;
-
- return result;
-}
-
-
-/////////////////////////////
-// Sending updates of current state
-
-void LLVivoxVoiceClient::enforceTether(void)
-{
- LLVector3d tethered = mCameraRequestedPosition;
-
- // constrain 'tethered' to within 50m of mAvatarPosition.
- {
- F32 max_dist = 50.0f;
- LLVector3d camera_offset = mCameraRequestedPosition - mAvatarPosition;
- F32 camera_distance = (F32)camera_offset.magVec();
- if(camera_distance > max_dist)
- {
- tethered = mAvatarPosition +
- (max_dist / camera_distance) * camera_offset;
- }
- }
-
- if(dist_vec_squared(mCameraPosition, tethered) > 0.01)
- {
- mCameraPosition = tethered;
- mSpatialCoordsDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::updatePosition(void)
-{
-
- LLViewerRegion *region = gAgent.getRegion();
- if(region && isAgentAvatarValid())
- {
- LLMatrix3 rot;
- LLVector3d pos;
- LLQuaternion qrot;
-
- // TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
- // They're currently always set to zero.
-
- // Send the current camera position to the voice code
- rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (), LLViewerCamera::getInstance()->getUpAxis());
- pos = gAgent.getRegion()->getPosGlobalFromRegion(LLViewerCamera::getInstance()->getOrigin());
-
- LLVivoxVoiceClient::getInstance()->setCameraPosition(
- pos, // position
- LLVector3::zero, // velocity
- rot); // rotation matrix
-
- // Send the current avatar position to the voice code
- qrot = gAgentAvatarp->getRootJoint()->getWorldRotation();
- pos = gAgentAvatarp->getPositionGlobal();
-
- // TODO: Can we get the head offset from outside the LLVOAvatar?
- // pos += LLVector3d(mHeadOffset);
- pos += LLVector3d(0.f, 0.f, 1.f);
-
- LLVivoxVoiceClient::getInstance()->setAvatarPosition(
- pos, // position
- LLVector3::zero, // velocity
- qrot); // rotation matrix
- }
-}
-
-void LLVivoxVoiceClient::setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot)
-{
- mCameraRequestedPosition = position;
-
- if(mCameraVelocity != velocity)
- {
- mCameraVelocity = velocity;
- mSpatialCoordsDirty = true;
- }
-
- if(mCameraRot != rot)
- {
- mCameraRot = rot;
- mSpatialCoordsDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot)
-{
- if(dist_vec_squared(mAvatarPosition, position) > 0.01)
- {
- mAvatarPosition = position;
- mSpatialCoordsDirty = true;
- }
-
- if(mAvatarVelocity != velocity)
- {
- mAvatarVelocity = velocity;
- mSpatialCoordsDirty = true;
- }
-
- // If the two rotations are not exactly equal test their dot product
- // to get the cos of the angle between them.
- // If it is too small, don't update.
- F32 rot_cos_diff = llabs(dot(mAvatarRot, rot));
- if ((mAvatarRot != rot) && (rot_cos_diff < MINUSCULE_ANGLE_COS))
- {
- mAvatarRot = rot;
- mSpatialCoordsDirty = true;
- }
-}
-
-bool LLVivoxVoiceClient::channelFromRegion(LLViewerRegion *region, std::string &name)
-{
- bool result = false;
-
- if(region)
- {
- name = region->getName();
- }
-
- if(!name.empty())
- result = true;
-
- return result;
-}
-
-void LLVivoxVoiceClient::leaveChannel(void)
-{
- if (mIsInChannel)
- {
- LL_DEBUGS("Voice") << "leaving channel for teleport/logout" << LL_ENDL;
- mChannelName.clear();
- }
- sessionTerminate();
-}
-
-void LLVivoxVoiceClient::setMuteMic(bool muted)
-{
- if(mMuteMic != muted)
- {
- mMuteMic = muted;
- mMuteMicDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
-{
- LL_DEBUGS("Voice")
- << "( " << (enabled ? "enabled" : "disabled") << " )"
- << " was "<< (mVoiceEnabled ? "enabled" : "disabled")
- << " coro "<< (mIsCoroutineActive ? "active" : "inactive")
- << LL_ENDL;
-
- if (enabled != mVoiceEnabled)
- {
- // TODO: Refactor this so we don't call into LLVoiceChannel, but simply
- // use the status observer
- mVoiceEnabled = enabled;
- LLVoiceClientStatusObserver::EStatusType status;
-
- if (enabled)
- {
- LL_DEBUGS("Voice") << "enabling" << LL_ENDL;
- LLVoiceChannel::getCurrentVoiceChannel()->activate();
- status = LLVoiceClientStatusObserver::STATUS_VOICE_ENABLED;
-
- if (!mIsCoroutineActive)
- {
- LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro",
- boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance()));
- }
- else
- {
- LL_DEBUGS("Voice") << "coro should be active.. not launching" << LL_ENDL;
- }
- }
- else
- {
- // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
- LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
- gAgent.setVoiceConnected(false);
- status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
- mCurrentParcelLocalID = -1;
- mCurrentRegionName.clear();
- }
-
- notifyStatusObservers(status);
- }
- else
- {
- LL_DEBUGS("Voice") << " no-op" << LL_ENDL;
- }
-}
-
-
-void LLVivoxVoiceClient::setEarLocation(S32 loc)
-{
- if(mEarLocation != loc)
- {
- LL_DEBUGS("Voice") << "Setting mEarLocation to " << loc << LL_ENDL;
-
- mEarLocation = loc;
- mSpatialCoordsDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::setVoiceVolume(F32 volume)
-{
- int scaled_volume = scale_speaker_volume(volume);
-
- if(scaled_volume != mSpeakerVolume)
- {
- int min_volume = scale_speaker_volume(0);
- if((scaled_volume == min_volume) || (mSpeakerVolume == min_volume))
- {
- mSpeakerMuteDirty = true;
- }
-
- mSpeakerVolume = scaled_volume;
- mSpeakerVolumeDirty = true;
- }
-}
-
-void LLVivoxVoiceClient::setMicGain(F32 volume)
-{
- int scaled_volume = scale_mic_volume(volume);
-
- if(scaled_volume != mMicVolume)
- {
- mMicVolume = scaled_volume;
- mMicVolumeDirty = true;
- }
-}
-
-/////////////////////////////
-// Accessors for data related to nearby speakers
-
-std::string LLVivoxVoiceClient::getDisplayName(const LLUUID& id)
-{
- std::string result;
- if (mProcessChannels)
- {
- participantStatePtr_t participant(findParticipantByID(id));
- if (participant)
- {
- result = participant->mDisplayName;
- }
- }
-
- return result;
-}
-
-
-
-bool LLVivoxVoiceClient::getIsSpeaking(const LLUUID& id)
-{
- bool result = false;
- if (mProcessChannels)
- {
- participantStatePtr_t participant(findParticipantByID(id));
- if (participant)
- {
- if (participant->mSpeakingTimeout.getElapsedTimeF32() > SPEAKING_TIMEOUT)
- {
- participant->mIsSpeaking = false;
- }
- result = participant->mIsSpeaking;
- }
- }
-
- return result;
-}
-
-bool LLVivoxVoiceClient::getIsModeratorMuted(const LLUUID& id)
-{
- bool result = false;
- if (!mProcessChannels)
- {
- return false;
- }
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- result = participant->mIsModeratorMuted;
- }
-
- return result;
-}
-
-F32 LLVivoxVoiceClient::getCurrentPower(const LLUUID& id)
-{
- F32 result = 0;
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- result = participant->mPower;
- }
-
- return result;
-}
-
-
-
-bool LLVivoxVoiceClient::getUsingPTT(const LLUUID& id)
-{
- bool result = false;
-
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- // I'm not sure what the semantics of this should be.
- // Does "using PTT" mean they're configured with a push-to-talk button?
- // For now, we know there's no PTT mechanism in place, so nobody is using it.
- }
-
- return result;
-}
-
-// External accessors.
-F32 LLVivoxVoiceClient::getUserVolume(const LLUUID& id)
-{
- // Minimum volume will be returned for users with voice disabled
- F32 result = LLVoiceClient::VOLUME_MIN;
-
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- result = participant->mVolume;
-
- // Enable this when debugging voice slider issues. It's way to spammy even for debug-level logging.
- // LL_DEBUGS("Voice") << "mVolume = " << result << " for " << id << LL_ENDL;
- }
-
- return result;
-}
-
-void LLVivoxVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
-{
- if(mAudioSession)
- {
- participantStatePtr_t participant(findParticipantByID(id));
- if (participant && !participant->mIsSelf)
- {
- if (!is_approx_equal(volume, LLVoiceClient::VOLUME_DEFAULT))
- {
- // Store this volume setting for future sessions if it has been
- // changed from the default
- LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, volume);
- }
- else
- {
- // Remove stored volume setting if it is returned to the default
- LLSpeakerVolumeStorage::getInstance()->removeSpeakerVolume(id);
- }
-
- participant->mVolume = llclamp(volume, LLVoiceClient::VOLUME_MIN, LLVoiceClient::VOLUME_MAX);
- participant->mVolumeDirty = true;
- mAudioSession->mVolumeDirty = true;
- }
- }
-}
-
-std::string LLVivoxVoiceClient::getGroupID(const LLUUID& id)
-{
- std::string result;
-
- participantStatePtr_t participant(findParticipantByID(id));
- if(participant)
- {
- result = participant->mGroupID;
- }
-
- return result;
-}
-
-void LLVivoxVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
-{
-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
-
- if(!mMainSessionGroupHandle.empty())
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
- << "<RecordingControlType>Start</RecordingControlType>"
- << "<DeltaFramesPerControlFrame>" << deltaFramesPerControlFrame << "</DeltaFramesPerControlFrame>"
- << "<Filename>" << "" << "</Filename>"
- << "<EnableAudioRecordingEvents>false</EnableAudioRecordingEvents>"
- << "<LoopModeDurationSeconds>" << seconds << "</LoopModeDurationSeconds>"
- << "</Request>\n\n\n";
-
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::recordingLoopSave(const std::string& filename)
-{
-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
-
- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
- << "<RecordingControlType>Flush</RecordingControlType>"
- << "<Filename>" << filename << "</Filename>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::recordingStop()
-{
-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
-
- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
- << "<RecordingControlType>Stop</RecordingControlType>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::filePlaybackStart(const std::string& filename)
-{
-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
-
- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
- << "<RecordingControlType>Start</RecordingControlType>"
- << "<Filename>" << filename << "</Filename>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::filePlaybackStop()
-{
-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
-
- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
- {
- std::ostringstream stream;
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
- << "<RecordingControlType>Stop</RecordingControlType>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::filePlaybackSetPaused(bool paused)
-{
- // TODO: Implement once Vivox gives me a sample
-}
-
-void LLVivoxVoiceClient::filePlaybackSetMode(bool vox, float speed)
-{
- // TODO: Implement once Vivox gives me a sample
-}
-
-//------------------------------------------------------------------------
-std::set<LLVivoxVoiceClient::sessionState::wptr_t, std::owner_less<LLVivoxVoiceClient::sessionState::wptr_t>> LLVivoxVoiceClient::sessionState::mSession;
-
-
-LLVivoxVoiceClient::sessionState::sessionState() :
- mErrorStatusCode(0),
- mMediaStreamState(streamStateUnknown),
- mCreateInProgress(false),
- mMediaConnectInProgress(false),
- mVoiceInvitePending(false),
- mTextInvitePending(false),
- mSynthesizedCallerID(false),
- mIsChannel(false),
- mIsSpatial(false),
- mIsP2P(false),
- mIncoming(false),
- mVoiceActive(false),
- mReconnect(false),
- mVolumeDirty(false),
- mMuteDirty(false),
- mParticipantsChanged(false)
-{
-}
-
-LLSD LLVivoxVoiceClient::sessionState::getVoiceChannelInfo()
-{
- LLSD result;
-
- result["voice_server_type"] = VIVOX_VOICE_SERVER_TYPE;
- result["channel_credentials"] = mHash;
- result["channel_uri"] = mSIPURI;
- result["session_handle"] = mHandle;
-
- return result;
-}
-
-/*static*/
-LLVivoxVoiceClient::sessionState::ptr_t LLVivoxVoiceClient::sessionState::createSession()
-{
- sessionState::ptr_t ptr(new sessionState());
-
- std::pair<std::set<wptr_t>::iterator, bool> result = mSession.insert(ptr);
-
- if (result.second)
- ptr->mMyIterator = result.first;
-
- return ptr;
-}
-
-LLVivoxVoiceClient::sessionState::~sessionState()
-{
- LL_INFOS("Voice") << "Destroying session handle=" << mHandle << " SIP=" << mSIPURI << LL_ENDL;
- if (mMyIterator != mSession.end())
- mSession.erase(mMyIterator);
-
- removeAllParticipants();
-}
-
-bool LLVivoxVoiceClient::sessionState::isCallBackPossible()
-{
- // This may change to be explicitly specified by vivox in the future...
- // Currently, only PSTN P2P calls cannot be returned.
- // Conveniently, this is also the only case where we synthesize a caller UUID.
- return !mSynthesizedCallerID;
-}
-
-bool LLVivoxVoiceClient::sessionState::isTextIMPossible()
-{
- // This may change to be explicitly specified by vivox in the future...
- return !mSynthesizedCallerID;
-}
-
-
-/*static*/
-LLVivoxVoiceClient::sessionState::ptr_t LLVivoxVoiceClient::sessionState::matchSessionByHandle(const std::string &handle)
-{
- sessionStatePtr_t result;
-
- // *TODO: My kingdom for a lambda!
- std::set<wptr_t>::iterator it = std::find_if(mSession.begin(), mSession.end(), boost::bind(testByHandle, _1, handle));
-
- if (it != mSession.end())
- result = (*it).lock();
-
- return result;
-}
-
-/*static*/
-LLVivoxVoiceClient::sessionState::ptr_t LLVivoxVoiceClient::sessionState::matchCreatingSessionByURI(const std::string &uri)
-{
- sessionStatePtr_t result;
-
- // *TODO: My kingdom for a lambda!
- std::set<wptr_t>::iterator it = std::find_if(mSession.begin(), mSession.end(), boost::bind(testByCreatingURI, _1, uri));
-
- if (it != mSession.end())
- result = (*it).lock();
-
- return result;
-}
-
-/*static*/
-LLVivoxVoiceClient::sessionState::ptr_t LLVivoxVoiceClient::sessionState::matchSessionByURI(const std::string &uri)
-{
- sessionStatePtr_t result;
-
- // *TODO: My kingdom for a lambda!
- std::set<wptr_t>::iterator it = std::find_if(mSession.begin(), mSession.end(), boost::bind(testBySIPOrAlterateURI, _1, uri));
-
- if (it != mSession.end())
- result = (*it).lock();
-
- return result;
-}
-
-/*static*/
-LLVivoxVoiceClient::sessionState::ptr_t LLVivoxVoiceClient::sessionState::matchSessionByParticipant(const LLUUID &participant_id)
-{
- sessionStatePtr_t result;
-
- // *TODO: My kingdom for a lambda!
- std::set<wptr_t>::iterator it = std::find_if(mSession.begin(), mSession.end(), boost::bind(testByCallerId, _1, participant_id));
-
- if (it != mSession.end())
- result = (*it).lock();
-
- return result;
-}
-
-void LLVivoxVoiceClient::sessionState::for_each(sessionFunc_t func)
-{
- std::for_each(mSession.begin(), mSession.end(), boost::bind(for_eachPredicate, _1, func));
-}
-
-// simple test predicates.
-// *TODO: These should be made into lambdas when we can pull the trigger on newer C++ features.
-bool LLVivoxVoiceClient::sessionState::testByHandle(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string handle)
-{
- ptr_t aLock(a.lock());
-
- return aLock ? aLock->mHandle == handle : false;
-}
-
-bool LLVivoxVoiceClient::sessionState::testByCreatingURI(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string uri)
-{
- ptr_t aLock(a.lock());
-
- return aLock ? (aLock->mCreateInProgress && (aLock->mSIPURI == uri)) : false;
-}
-
-bool LLVivoxVoiceClient::sessionState::testBySIPOrAlterateURI(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string uri)
-{
- ptr_t aLock(a.lock());
-
- return aLock ? ((aLock->mSIPURI == uri) || (aLock->mAlternateSIPURI == uri)) : false;
-}
-
-
-bool LLVivoxVoiceClient::sessionState::testByCallerId(const LLVivoxVoiceClient::sessionState::wptr_t &a, LLUUID participantId)
-{
- ptr_t aLock(a.lock());
-
- return aLock ? ((aLock->mCallerID == participantId) || (aLock->mIMSessionID == participantId)) : false;
-}
-
-/*static*/
-void LLVivoxVoiceClient::sessionState::for_eachPredicate(const LLVivoxVoiceClient::sessionState::wptr_t &a, sessionFunc_t func)
-{
- ptr_t aLock(a.lock());
-
- if (aLock)
- func(aLock);
- else
- {
- LL_WARNS("Voice") << "Stale handle in session map!" << LL_ENDL;
- }
-}
-
-
-
-LLVivoxVoiceClient::sessionStatePtr_t LLVivoxVoiceClient::findSession(const std::string &handle)
-{
- sessionStatePtr_t result;
- sessionMap::iterator iter = mSessionsByHandle.find(handle);
- if(iter != mSessionsByHandle.end())
- {
- result = iter->second;
- }
-
- return result;
-}
-
-LLVivoxVoiceClient::sessionStatePtr_t LLVivoxVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
-{
- sessionStatePtr_t result = sessionState::matchCreatingSessionByURI(uri);
-
- return result;
-}
-
-LLVivoxVoiceClient::sessionStatePtr_t LLVivoxVoiceClient::findSession(const LLUUID &participant_id)
-{
- sessionStatePtr_t result = sessionState::matchSessionByParticipant(participant_id);
-
- return result;
-}
-
-LLVivoxVoiceClient::sessionStatePtr_t LLVivoxVoiceClient::addSession(const std::string &uri, const std::string &handle)
-{
- sessionStatePtr_t result;
-
- if(handle.empty())
- {
- // No handle supplied.
- // Check whether there's already a session with this URI
- result = sessionState::matchSessionByURI(uri);
- }
- else // (!handle.empty())
- {
- // Check for an existing session with this handle
- sessionMap::iterator iter = mSessionsByHandle.find(handle);
-
- if(iter != mSessionsByHandle.end())
- {
- result = iter->second;
- }
- }
-
- if(!result)
- {
- // No existing session found.
-
- LL_DEBUGS("Voice") << "adding new session: handle \"" << handle << "\" URI " << uri << LL_ENDL;
- result = sessionState::createSession();
- result->mSIPURI = uri;
- result->mHandle = handle;
-
- if (LLVoiceClient::instance().getVoiceEffectEnabled())
- {
- result->mVoiceFontID = LLVoiceClient::instance().getVoiceEffectDefault();
- }
-
- if(!result->mHandle.empty())
- {
- // *TODO: Rider: This concerns me. There is a path (via switchChannel) where
- // we do not track the session. In theory this means that we could end up with
- // a mAuidoSession that does not match the session tracked in mSessionsByHandle
- mSessionsByHandle.insert(sessionMap::value_type(result->mHandle, result));
- }
- }
- else
- {
- // Found an existing session
-
- if(uri != result->mSIPURI)
- {
- // TODO: Should this be an internal error?
- LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
- setSessionURI(result, uri);
- }
-
- if(handle != result->mHandle)
- {
- if(handle.empty())
- {
- // There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break.
- LL_DEBUGS("Voice") << "NOT clearing handle " << result->mHandle << LL_ENDL;
- }
- else
- {
- // TODO: Should this be an internal error?
- LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
- setSessionHandle(result, handle);
- }
- }
-
- LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
- }
-
- verifySessionState();
-
- return result;
-}
-
-void LLVivoxVoiceClient::clearSessionHandle(const sessionStatePtr_t &session)
-{
- if (session)
- {
- if (!session->mHandle.empty())
- {
- sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
- if (iter != mSessionsByHandle.end())
- {
- mSessionsByHandle.erase(iter);
- }
- }
- else
- {
- LL_WARNS("Voice") << "Session has empty handle!" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("Voice") << "Attempt to clear NULL session!" << LL_ENDL;
- }
-
-}
-
-void LLVivoxVoiceClient::setSessionHandle(const sessionStatePtr_t &session, const std::string &handle)
-{
- // Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
-
- if(!session->mHandle.empty())
- {
- // Remove session from the map if it should have been there.
- sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
- if(iter != mSessionsByHandle.end())
- {
- if(iter->second != session)
- {
- LL_WARNS("Voice") << "Internal error: session mismatch! Session may have been duplicated. Removing version in map." << LL_ENDL;
- }
-
- mSessionsByHandle.erase(iter);
- }
- else
- {
- LL_WARNS("Voice") << "Attempt to remove session with handle " << session->mHandle << " not found in map!" << LL_ENDL;
- }
- }
-
- session->mHandle = handle;
-
- if(!handle.empty())
- {
- mSessionsByHandle.insert(sessionMap::value_type(session->mHandle, session));
- }
-
- verifySessionState();
-}
-
-void LLVivoxVoiceClient::setSessionURI(const sessionStatePtr_t &session, const std::string &uri)
-{
- // There used to be a map of session URIs to sessions, which made this complex....
- session->mSIPURI = uri;
-
- verifySessionState();
-}
-
-void LLVivoxVoiceClient::deleteSession(const sessionStatePtr_t &session)
-{
- // Remove the session from the handle map
- if(!session->mHandle.empty())
- {
- sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
- if(iter != mSessionsByHandle.end())
- {
- if(iter->second != session)
- {
- LL_WARNS("Voice") << "Internal error: session mismatch, removing session in map." << LL_ENDL;
- }
- mSessionsByHandle.erase(iter);
- }
- }
-
- // At this point, the session should be unhooked from all lists and all state should be consistent.
- verifySessionState();
-
- // If this is the current audio session, clean up the pointer which will soon be dangling.
- if(mAudioSession == session)
- {
- mAudioSession.reset();
- }
-
- // ditto for the next audio session
- if(mNextAudioSession == session)
- {
- mNextAudioSession.reset();
- }
-
-}
-
-void LLVivoxVoiceClient::deleteAllSessions()
-{
- LL_DEBUGS("Voice") << LL_ENDL;
-
- while (!mSessionsByHandle.empty())
- {
- const sessionStatePtr_t session = mSessionsByHandle.begin()->second;
- deleteSession(session);
- }
-
-}
-
-void LLVivoxVoiceClient::verifySessionState(void)
-{
- LL_DEBUGS("Voice") << "Sessions in handle map=" << mSessionsByHandle.size() << LL_ENDL;
- sessionState::VerifySessions();
-}
-
-void LLVivoxVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
-{
- mParticipantObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
-{
- mParticipantObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyParticipantObservers()
-{
- for (observer_set_t::iterator it = mParticipantObservers.begin();
- it != mParticipantObservers.end();
- )
- {
- LLVoiceClientParticipantObserver* observer = *it;
- observer->onParticipantsChanged();
- // In case onParticipantsChanged() deleted an entry.
- it = mParticipantObservers.upper_bound(observer);
- }
-}
-
-void LLVivoxVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
-{
- mStatusObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
-{
- mStatusObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
-{
- LL_DEBUGS("Voice") << "( " << LLVoiceClientStatusObserver::status2string(status) << " )"
- << " mAudioSession=" << mAudioSession
- << LL_ENDL;
-
- if(mAudioSession)
- {
- if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
- {
- switch(mAudioSession->mErrorStatusCode)
- {
- case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
- case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
- case 20715:
- //invalid channel, we may be using a set of poorly cached
- //info
- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
- break;
- case 1009:
- //invalid username and password
- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
- break;
- }
-
- // Reset the error code to make sure it won't be reused later by accident.
- mAudioSession->mErrorStatusCode = 0;
- }
- else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
- {
- switch(mAudioSession->mErrorStatusCode)
- {
- case HTTP_NOT_FOUND: // NOT_FOUND
- // *TODO: Should this be 503?
- case 480: // TEMPORARILY_UNAVAILABLE
- case HTTP_REQUEST_TIME_OUT: // REQUEST_TIMEOUT
- // call failed because other user was not available
- // treat this as an error case
- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-
- // Reset the error code to make sure it won't be reused later by accident.
- mAudioSession->mErrorStatusCode = 0;
- break;
- }
- }
- }
-
- LLSD channel_info = getAudioSessionChannelInfo();
- LL_DEBUGS("Voice")
- << " " << LLVoiceClientStatusObserver::status2string(status)
- << ", session channelInfo " << channel_info
- << ", proximal is " << inSpatialChannel()
- << LL_ENDL;
-
- if (!mProcessChannels)
- {
- // we're not processing...another voice module is.
- // so nobody wants to hear from us.
- return;
- }
- for (status_observer_set_t::iterator it = mStatusObservers.begin();
- it != mStatusObservers.end();
- )
- {
- LLVoiceClientStatusObserver* observer = *it;
- observer->onChange(status, channel_info, inSpatialChannel());
- // In case onError() deleted an entry.
- it = mStatusObservers.upper_bound(observer);
- }
-
- // skipped to avoid speak button blinking
- if ( status != LLVoiceClientStatusObserver::STATUS_JOINING
- && status != LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL
- && status != LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED)
- {
- bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
-
- LL_WARNS("Voice") << "Setting voice connected " << (voice_status ? "True" : "False") << LL_ENDL;
- gAgent.setVoiceConnected(voice_status);
-
- if (voice_status)
- {
- LLAppViewer::instance()->postToMainCoro([=]() { LLFirstUse::speak(true); });
- }
- }
-}
-
-void LLVivoxVoiceClient::addObserver(LLFriendObserver* observer)
-{
- mFriendObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLFriendObserver* observer)
-{
- mFriendObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyFriendObservers()
-{
- for (friend_observer_set_t::iterator it = mFriendObservers.begin();
- it != mFriendObservers.end();
- )
- {
- LLFriendObserver* observer = *it;
- it++;
- // The only friend-related thing we notify on is online/offline transitions.
- observer->changed(LLFriendObserver::ONLINE);
- }
-}
-
-void LLVivoxVoiceClient::lookupName(const LLUUID &id)
-{
- if (mAvatarNameCacheConnection.connected())
- {
- mAvatarNameCacheConnection.disconnect();
- }
- mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLVivoxVoiceClient::onAvatarNameCache, this, _1, _2));
-}
-
-void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name)
-{
- mAvatarNameCacheConnection.disconnect();
- std::string display_name = av_name.getDisplayName();
- avatarNameResolved(agent_id, display_name);
-}
-
-void LLVivoxVoiceClient::predAvatarNameResolution(const LLVivoxVoiceClient::sessionStatePtr_t &session, LLUUID id, std::string name)
-{
- participantStatePtr_t participant(session->findParticipantByID(id));
- if (participant)
- {
- // Found -- fill in the name
- participant->mAccountName = name;
- // and post a "participants updated" message to listeners later.
- session->mParticipantsChanged = true;
- }
-
- // Check whether this is a p2p session whose caller name just resolved
- if (session->mCallerID == id)
- {
- // this session's "caller ID" just resolved. Fill in the name.
- session->mName = name;
- if (session->mTextInvitePending)
- {
- session->mTextInvitePending = false;
-
- // We don't need to call LLIMMgr::getInstance()->addP2PSession() here. The first incoming message will create the panel.
- }
- if (session->mVoiceInvitePending)
- {
- session->mVoiceInvitePending = false;
- LLIMMgr::getInstance()->inviteToSession(
- session->mIMSessionID,
- session->mName,
- session->mCallerID,
- session->mName,
- IM_SESSION_P2P_INVITE,
- LLIMMgr::INVITATION_TYPE_VOICE,
- session->getVoiceChannelInfo());
- }
- }
-}
-
-void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
-{
- sessionState::for_each(boost::bind(predAvatarNameResolution, _1, id, name));
-}
-
-bool LLVivoxVoiceClient::setVoiceEffect(const LLUUID& id)
-{
- if (!mAudioSession)
- {
- return false;
- }
-
- if (!id.isNull())
- {
- if (mVoiceFontMap.empty())
- {
- LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL;
- return false;
- }
- else if (mVoiceFontMap.find(id) == mVoiceFontMap.end())
- {
- LL_DEBUGS("Voice") << "Invalid voice font " << id << LL_ENDL;
- return false;
- }
- }
-
- // *TODO: Check for expired fonts?
- mAudioSession->mVoiceFontID = id;
-
- // *TODO: Separate voice font defaults for spatial chat and IM?
- gSavedPerAccountSettings.setString("VoiceEffectDefault", id.asString());
-
- sessionSetVoiceFontSendMessage(mAudioSession);
- notifyVoiceFontObservers();
-
- return true;
-}
-
-const LLUUID LLVivoxVoiceClient::getVoiceEffect()
-{
- return mAudioSession ? mAudioSession->mVoiceFontID : LLUUID::null;
-}
-
-LLSD LLVivoxVoiceClient::getVoiceEffectProperties(const LLUUID& id)
-{
- LLSD sd;
-
- voice_font_map_t::iterator iter = mVoiceFontMap.find(id);
- if (iter != mVoiceFontMap.end())
- {
- sd["template_only"] = false;
- }
- else
- {
- // Voice effect is not in the voice font map, see if there is a template
- iter = mVoiceFontTemplateMap.find(id);
- if (iter == mVoiceFontTemplateMap.end())
- {
- LL_WARNS("Voice") << "Voice effect " << id << "not found." << LL_ENDL;
- return sd;
- }
- sd["template_only"] = true;
- }
-
- voiceFontEntry *font = iter->second;
- sd["name"] = font->mName;
- sd["expiry_date"] = font->mExpirationDate;
- sd["is_new"] = font->mIsNew;
-
- return sd;
-}
-
-LLVivoxVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) :
- mID(id),
- mFontIndex(0),
- mFontType(VOICE_FONT_TYPE_NONE),
- mFontStatus(VOICE_FONT_STATUS_NONE),
- mIsNew(false)
-{
- mExpiryTimer.stop();
-}
-
-LLVivoxVoiceClient::voiceFontEntry::~voiceFontEntry()
-{
-}
-
-void LLVivoxVoiceClient::refreshVoiceEffectLists(bool clear_lists)
-{
- if (clear_lists)
- {
- mVoiceFontsReceived = false;
- deleteAllVoiceFonts();
- deleteVoiceFontTemplates();
- }
-
- accountGetSessionFontsSendMessage();
- accountGetTemplateFontsSendMessage();
-}
-
-const voice_effect_list_t& LLVivoxVoiceClient::getVoiceEffectList() const
-{
- return mVoiceFontList;
-}
-
-const voice_effect_list_t& LLVivoxVoiceClient::getVoiceEffectTemplateList() const
-{
- return mVoiceFontTemplateList;
-}
-
-void LLVivoxVoiceClient::addVoiceFont(const S32 font_index,
- const std::string &name,
- const std::string &description,
- const LLDate &expiration_date,
- bool has_expired,
- const S32 font_type,
- const S32 font_status,
- const bool template_font)
-{
- // Vivox SessionFontIDs are not guaranteed to remain the same between
- // sessions or grids so use a UUID for the name.
-
- // If received name is not a UUID, fudge one by hashing the name and type.
- LLUUID font_id;
- if (LLUUID::validate(name))
- {
- font_id = LLUUID(name);
- }
- else
- {
- font_id.generate(STRINGIZE(font_type << ":" << name));
- }
-
- voiceFontEntry *font = NULL;
-
- voice_font_map_t& font_map = template_font ? mVoiceFontTemplateMap : mVoiceFontMap;
- voice_effect_list_t& font_list = template_font ? mVoiceFontTemplateList : mVoiceFontList;
-
- // Check whether we've seen this font before.
- voice_font_map_t::iterator iter = font_map.find(font_id);
- bool new_font = (iter == font_map.end());
-
- // Override the has_expired flag if we have passed the expiration_date as a double check.
- if (expiration_date.secondsSinceEpoch() < (LLDate::now().secondsSinceEpoch() + VOICE_FONT_EXPIRY_INTERVAL))
- {
- has_expired = true;
- }
-
- if (has_expired)
- {
- LL_DEBUGS("VoiceFont") << "Expired " << (template_font ? "Template " : "")
- << expiration_date.asString() << " " << font_id
- << " (" << font_index << ") " << name << LL_ENDL;
-
- // Remove existing session fonts that have expired since we last saw them.
- if (!new_font && !template_font)
- {
- deleteVoiceFont(font_id);
- }
- return;
- }
-
- if (new_font)
- {
- // If it is a new font create a new entry.
- font = new voiceFontEntry(font_id);
- }
- else
- {
- // Not a new font, update the existing entry
- font = iter->second;
- }
-
- if (font)
- {
- font->mFontIndex = font_index;
- // Use the description for the human readable name if available, as the
- // "name" may be a UUID.
- font->mName = description.empty() ? name : description;
- font->mFontType = font_type;
- font->mFontStatus = font_status;
-
- // If the font is new or the expiration date has changed the expiry timers need updating.
- if (!template_font && (new_font || font->mExpirationDate != expiration_date))
- {
- font->mExpirationDate = expiration_date;
-
- // Set the expiry timer to trigger a notification when the voice font can no longer be used.
- font->mExpiryTimer.start();
- font->mExpiryTimer.setExpiryAt(expiration_date.secondsSinceEpoch() - VOICE_FONT_EXPIRY_INTERVAL);
-
- // Only flag new session fonts after the first time we have fetched the list.
- if (mVoiceFontsReceived)
- {
- font->mIsNew = true;
- mVoiceFontsNew = true;
- }
- }
-
- LL_DEBUGS("VoiceFont") << (template_font ? "Template " : "")
- << font->mExpirationDate.asString() << " " << font->mID
- << " (" << font->mFontIndex << ") " << name << LL_ENDL;
-
- if (new_font)
- {
- font_map.insert(voice_font_map_t::value_type(font->mID, font));
- font_list.insert(voice_effect_list_t::value_type(font->mName, font->mID));
- }
-
- mVoiceFontListDirty = true;
-
- // Debugging stuff
-
- if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN)
- {
- LL_WARNS("VoiceFont") << "Unknown voice font type: " << font_type << LL_ENDL;
- }
- if (font_status < VOICE_FONT_STATUS_NONE || font_status >= VOICE_FONT_STATUS_UNKNOWN)
- {
- LL_WARNS("VoiceFont") << "Unknown voice font status: " << font_status << LL_ENDL;
- }
- }
-}
-
-void LLVivoxVoiceClient::expireVoiceFonts()
-{
- // *TODO: If we are selling voice fonts in packs, there are probably
- // going to be a number of fonts with the same expiration time, so would
- // be more efficient to just keep a list of expiration times rather
- // than checking each font individually.
-
- bool have_expired = false;
- bool expired_in_use = false;
-
- LLUUID current_effect = LLVoiceClient::instance().getVoiceEffectDefault();
-
- voice_font_map_t::iterator iter;
- for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter)
- {
- voiceFontEntry* voice_font = iter->second;
- LLFrameTimer& expiry_timer = voice_font->mExpiryTimer;
-
- // Check for expired voice fonts
- if (expiry_timer.getStarted() && expiry_timer.hasExpired())
- {
- // Check whether it is the active voice font
- if (voice_font->mID == current_effect)
- {
- // Reset to no voice effect.
- setVoiceEffect(LLUUID::null);
- expired_in_use = true;
- }
-
- LL_DEBUGS("Voice") << "Voice Font " << voice_font->mName << " has expired." << LL_ENDL;
- deleteVoiceFont(voice_font->mID);
- have_expired = true;
- }
- }
-
- LLSD args;
- args["URL"] = LLTrans::getString("voice_morphing_url");
- args["PREMIUM_URL"] = LLTrans::getString("premium_voice_morphing_url");
-
- // Give a notification if any voice fonts have expired.
- if (have_expired)
- {
- if (expired_in_use)
- {
- LLNotificationsUtil::add("VoiceEffectsExpiredInUse", args);
- }
- else
- {
- LLNotificationsUtil::add("VoiceEffectsExpired", args);
- }
-
- // Refresh voice font lists in the UI.
- notifyVoiceFontObservers();
- }
-}
-
-void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id)
-{
- // Remove the entry from the voice font list.
- voice_effect_list_t::iterator list_iter = mVoiceFontList.begin();
- while (list_iter != mVoiceFontList.end())
- {
- if (list_iter->second == id)
- {
- LL_DEBUGS("VoiceFont") << "Removing " << id << " from the voice font list." << LL_ENDL;
- list_iter = mVoiceFontList.erase(list_iter);
- mVoiceFontListDirty = true;
- }
- else
- {
- ++list_iter;
- }
- }
-
- // Find the entry in the voice font map and erase its data.
- voice_font_map_t::iterator map_iter = mVoiceFontMap.find(id);
- if (map_iter != mVoiceFontMap.end())
- {
- delete map_iter->second;
- }
-
- // Remove the entry from the voice font map.
- mVoiceFontMap.erase(map_iter);
-}
-
-void LLVivoxVoiceClient::deleteAllVoiceFonts()
-{
- mVoiceFontList.clear();
-
- voice_font_map_t::iterator iter;
- for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter)
- {
- delete iter->second;
- }
- mVoiceFontMap.clear();
-}
-
-void LLVivoxVoiceClient::deleteVoiceFontTemplates()
-{
- mVoiceFontTemplateList.clear();
-
- voice_font_map_t::iterator iter;
- for (iter = mVoiceFontTemplateMap.begin(); iter != mVoiceFontTemplateMap.end(); ++iter)
- {
- delete iter->second;
- }
- mVoiceFontTemplateMap.clear();
-}
-
-S32 LLVivoxVoiceClient::getVoiceFontIndex(const LLUUID& id) const
-{
- S32 result = 0;
- if (!id.isNull())
- {
- voice_font_map_t::const_iterator it = mVoiceFontMap.find(id);
- if (it != mVoiceFontMap.end())
- {
- result = it->second->mFontIndex;
- }
- else
- {
- LL_WARNS("VoiceFont") << "Selected voice font " << id << " is not available." << LL_ENDL;
- }
- }
- return result;
-}
-
-S32 LLVivoxVoiceClient::getVoiceFontTemplateIndex(const LLUUID& id) const
-{
- S32 result = 0;
- if (!id.isNull())
- {
- voice_font_map_t::const_iterator it = mVoiceFontTemplateMap.find(id);
- if (it != mVoiceFontTemplateMap.end())
- {
- result = it->second->mFontIndex;
- }
- else
- {
- LL_WARNS("VoiceFont") << "Selected voice font template " << id << " is not available." << LL_ENDL;
- }
- }
- return result;
-}
-
-void LLVivoxVoiceClient::accountGetSessionFontsSendMessage()
-{
- if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("VoiceFont") << "Requesting voice font list." << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetSessionFonts.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::accountGetTemplateFontsSendMessage()
-{
- if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("VoiceFont") << "Requesting voice font template list." << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetTemplateFonts.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::sessionSetVoiceFontSendMessage(const sessionStatePtr_t &session)
-{
- S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
- LL_DEBUGS("VoiceFont") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << "), session handle: " << session->mHandle << LL_ENDL;
-
- std::ostringstream stream;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetVoiceFont.1\">"
- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
- << "<SessionFontID>" << font_index << "</SessionFontID>"
- << "</Request>\n\n\n";
-
- writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString)
-{
- if (mIsWaitingForFonts)
- {
- // *TODO: We seem to get multiple events of this type. Should figure a way to advance only after
- // receiving the last one.
- LLSD result(LLSDMap("voice_fonts", LLSD::Boolean(true)));
-
- mVivoxPump.post(result);
- }
- notifyVoiceFontObservers();
- mVoiceFontsReceived = true;
-}
-
-void LLVivoxVoiceClient::accountGetTemplateFontsResponse(int statusCode, const std::string &statusString)
-{
- // Voice font list entries were updated via addVoiceFont() during parsing.
- notifyVoiceFontObservers();
-}
-void LLVivoxVoiceClient::addObserver(LLVoiceEffectObserver* observer)
-{
- mVoiceFontObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer)
-{
- mVoiceFontObservers.erase(observer);
-}
-
-// method checks the item in VoiceMorphing menu for appropriate current voice font
-bool LLVivoxVoiceClient::onCheckVoiceEffect(const std::string& voice_effect_name)
-{
- LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
- if (NULL != effect_interfacep)
- {
- const LLUUID& currect_voice_effect_id = effect_interfacep->getVoiceEffect();
-
- if (currect_voice_effect_id.isNull())
- {
- if (voice_effect_name == "NoVoiceMorphing")
- {
- return true;
- }
- }
- else
- {
- const LLSD& voice_effect_props = effect_interfacep->getVoiceEffectProperties(currect_voice_effect_id);
- if (voice_effect_props["name"].asString() == voice_effect_name)
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-// method changes voice font for selected VoiceMorphing menu item
-void LLVivoxVoiceClient::onClickVoiceEffect(const std::string& voice_effect_name)
-{
- LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
- if (NULL != effect_interfacep)
- {
- if (voice_effect_name == "NoVoiceMorphing")
- {
- effect_interfacep->setVoiceEffect(LLUUID());
- return;
- }
- const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList();
- if (!effect_list.empty())
- {
- for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it)
- {
- if (voice_effect_name == it->first)
- {
- effect_interfacep->setVoiceEffect(it->second);
- return;
- }
- }
- }
- }
-}
-
-// it updates VoiceMorphing menu items in accordance with purchased properties
-void LLVivoxVoiceClient::updateVoiceMorphingMenu()
-{
- if (mVoiceFontListDirty)
- {
- LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
- if (effect_interfacep)
- {
- const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList();
- if (!effect_list.empty())
- {
- LLMenuGL * voice_morphing_menup = gMenuBarView->findChildMenuByName("VoiceMorphing", true);
-
- if (NULL != voice_morphing_menup)
- {
- S32 items = voice_morphing_menup->getItemCount();
- if (items > 0)
- {
- voice_morphing_menup->erase(1, items - 3, false);
-
- S32 pos = 1;
- for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it)
- {
- LLMenuItemCheckGL::Params p;
- p.name = it->first;
- p.label = it->first;
- p.on_check.function(boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, this, it->first));
- p.on_click.function(boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, this, it->first));
- LLMenuItemCheckGL * voice_effect_itemp = LLUICtrlFactory::create<LLMenuItemCheckGL>(p);
- voice_morphing_menup->insert(pos++, voice_effect_itemp, false);
- }
-
- voice_morphing_menup->needsArrange();
- }
- }
- }
- }
- }
-}
-void LLVivoxVoiceClient::notifyVoiceFontObservers()
-{
- LL_DEBUGS("VoiceFont") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL;
-
- updateVoiceMorphingMenu();
-
- for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin();
- it != mVoiceFontObservers.end();)
- {
- LLVoiceEffectObserver* observer = *it;
- observer->onVoiceEffectChanged(mVoiceFontListDirty);
- // In case onVoiceEffectChanged() deleted an entry.
- it = mVoiceFontObservers.upper_bound(observer);
- }
- mVoiceFontListDirty = false;
-
- // If new Voice Fonts have been added notify the user.
- if (mVoiceFontsNew)
- {
- if (mVoiceFontsReceived)
- {
- LLNotificationsUtil::add("VoiceEffectsNew");
- }
- mVoiceFontsNew = false;
- }
-}
-
-void LLVivoxVoiceClient::enablePreviewBuffer(bool enable)
-{
- LLSD result;
- mCaptureBufferMode = enable;
-
- if (enable)
- result["recplay"] = "start";
- else
- result["recplay"] = "quit";
-
- mVivoxPump.post(result);
-
- if(mCaptureBufferMode && mIsInChannel)
- {
- LL_DEBUGS("Voice") << "no channel" << LL_ENDL;
- sessionTerminate();
- }
-}
-
-void LLVivoxVoiceClient::recordPreviewBuffer()
-{
- if (!mCaptureBufferMode)
- {
- LL_DEBUGS("Voice") << "Not in voice effect preview mode, cannot start recording." << LL_ENDL;
- mCaptureBufferRecording = false;
- return;
- }
-
- mCaptureBufferRecording = true;
-
- LLSD result(LLSDMap("recplay", "record"));
- mVivoxPump.post(result);
-}
-
-void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id)
-{
- if (!mCaptureBufferMode)
- {
- LL_DEBUGS("Voice") << "Not in voice effect preview mode, no buffer to play." << LL_ENDL;
- mCaptureBufferRecording = false;
- return;
- }
-
- if (!mCaptureBufferRecorded)
- {
- // Can't play until we have something recorded!
- mCaptureBufferPlaying = false;
- return;
- }
-
- mPreviewVoiceFont = effect_id;
- mCaptureBufferPlaying = true;
-
- LLSD result(LLSDMap("recplay", "playback"));
- mVivoxPump.post(result);
-}
-
-void LLVivoxVoiceClient::stopPreviewBuffer()
-{
- mCaptureBufferRecording = false;
- mCaptureBufferPlaying = false;
-
- LLSD result(LLSDMap("recplay", "quit"));
- mVivoxPump.post(result);
-}
-
-bool LLVivoxVoiceClient::isPreviewRecording()
-{
- return (mCaptureBufferMode && mCaptureBufferRecording);
-}
-
-bool LLVivoxVoiceClient::isPreviewPlaying()
-{
- return (mCaptureBufferMode && mCaptureBufferPlaying);
-}
-
-void LLVivoxVoiceClient::captureBufferRecordStartSendMessage()
-{ if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "Starting audio capture to buffer." << LL_ENDL;
-
- // Start capture
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.StartBufferCapture.1\">"
- << "</Request>"
- << "\n\n\n";
-
- // Unmute the mic
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>false</Value>"
- << "</Request>\n\n\n";
-
- // Dirty the mute mic state so that it will get reset when we finishing previewing
- mMuteMicDirty = true;
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::captureBufferRecordStopSendMessage()
-{
- if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "Stopping audio capture to buffer." << LL_ENDL;
-
- // Mute the mic. Mic mute state was dirtied at recording start, so will be reset when finished previewing.
- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
- << "<ConnectorHandle>" << LLVivoxSecurity::getInstance()->connectorHandle() << "</ConnectorHandle>"
- << "<Value>true</Value>"
- << "</Request>\n\n\n";
-
- // Stop capture
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::captureBufferPlayStartSendMessage(const LLUUID& voice_font_id)
-{
- if(mAccountLoggedIn)
- {
- // Track how may play requests are sent, so we know how many stop events to
- // expect before play actually stops.
- ++mPlayRequestCount;
-
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "Starting audio buffer playback." << LL_ENDL;
-
- S32 font_index = getVoiceFontTemplateIndex(voice_font_id);
- LL_DEBUGS("Voice") << "With voice font: " << voice_font_id << " (" << font_index << ")" << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.PlayAudioBuffer.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "<TemplateFontID>" << font_index << "</TemplateFontID>"
- << "<FontDelta />"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-void LLVivoxVoiceClient::captureBufferPlayStopSendMessage()
-{
- if(mAccountLoggedIn)
- {
- std::ostringstream stream;
-
- LL_DEBUGS("Voice") << "Stopping audio buffer playback." << LL_ENDL;
-
- stream
- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">"
- << "<AccountHandle>" << LLVivoxSecurity::getInstance()->accountHandle() << "</AccountHandle>"
- << "</Request>"
- << "\n\n\n";
-
- writeString(stream.str());
- }
-}
-
-LLVivoxProtocolParser::LLVivoxProtocolParser()
-{
- parser = XML_ParserCreate(NULL);
-
- reset();
-}
-
-void LLVivoxProtocolParser::reset()
-{
- responseDepth = 0;
- ignoringTags = false;
- accumulateText = false;
- energy = 0.f;
- hasText = false;
- hasAudio = false;
- hasVideo = false;
- terminated = false;
- ignoreDepth = 0;
- isChannel = false;
- incoming = false;
- enabled = false;
- isEvent = false;
- isLocallyMuted = false;
- isModeratorMuted = false;
- isSpeaking = false;
- participantType = 0;
- returnCode = -1;
- state = 0;
- statusCode = 0;
- volume = 0;
- textBuffer.clear();
- alias.clear();
- numberOfAliases = 0;
- applicationString.clear();
-}
-
-//virtual
-LLVivoxProtocolParser::~LLVivoxProtocolParser()
-{
- if (parser)
- XML_ParserFree(parser);
-}
-
-static LLTrace::BlockTimerStatHandle FTM_VIVOX_PROCESS("Vivox Process");
-
-// virtual
-LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
-{
- LL_RECORD_BLOCK_TIME(FTM_VIVOX_PROCESS);
- LLBufferStream istr(channels, buffer.get());
- std::ostringstream ostr;
- while (istr.good())
- {
- char buf[1024];
- istr.read(buf, sizeof(buf));
- mInput.append(buf, istr.gcount());
- }
-
- // Look for input delimiter(s) in the input buffer. If one is found, send the message to the xml parser.
- size_t start = 0;
- size_t delim;
- while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
- {
-
- // Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
- reset();
-
- XML_ParserReset(parser, NULL);
- XML_SetElementHandler(parser, ExpatStartTag, ExpatEndTag);
- XML_SetCharacterDataHandler(parser, ExpatCharHandler);
- XML_SetUserData(parser, this);
- XML_Parse(parser, mInput.data() + start, static_cast<int>(delim - start), false);
-
-
- LL_DEBUGS("VivoxProtocolParser") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
- start = delim + 3;
- }
-
- if(start != 0)
- mInput = mInput.substr(start);
-
- LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
-
- if(!LLVivoxVoiceClient::sConnected)
- {
- // If voice has been disabled, we just want to close the socket. This does so.
- LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
- return STATUS_STOP;
- }
-
- return STATUS_OK;
-}
-
-void XMLCALL LLVivoxProtocolParser::ExpatStartTag(void *data, const char *el, const char **attr)
-{
- if (data)
- {
- LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data;
- object->StartTag(el, attr);
- }
-}
-
-// --------------------------------------------------------------------------------
-
-void XMLCALL LLVivoxProtocolParser::ExpatEndTag(void *data, const char *el)
-{
- if (data)
- {
- LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data;
- object->EndTag(el);
- }
-}
-
-// --------------------------------------------------------------------------------
-
-void XMLCALL LLVivoxProtocolParser::ExpatCharHandler(void *data, const XML_Char *s, int len)
-{
- if (data)
- {
- LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data;
- object->CharData(s, len);
- }
-}
-
-// --------------------------------------------------------------------------------
-
-
-void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
-{
- // Reset the text accumulator. We shouldn't have strings that are inturrupted by new tags
- textBuffer.clear();
- // only accumulate text if we're not ignoring tags.
- accumulateText = !ignoringTags;
-
- if (responseDepth == 0)
- {
- isEvent = !stricmp("Event", tag);
-
- if (!stricmp("Response", tag) || isEvent)
- {
- // Grab the attributes
- while (*attr)
- {
- const char *key = *attr++;
- const char *value = *attr++;
-
- if (!stricmp("requestId", key))
- {
- requestId = value;
- }
- else if (!stricmp("action", key))
- {
- actionString = value;
- }
- else if (!stricmp("type", key))
- {
- eventTypeString = value;
- }
- }
- }
- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
- }
- else
- {
- if (ignoringTags)
- {
- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
-
- // Ignore the InputXml stuff so we don't get confused
- if (!stricmp("InputXml", tag))
- {
- ignoringTags = true;
- ignoreDepth = responseDepth;
- accumulateText = false;
-
- LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
- }
- else if (!stricmp("CaptureDevices", tag))
- {
- LLVivoxVoiceClient::getInstance()->clearCaptureDevices();
- }
- else if (!stricmp("RenderDevices", tag))
- {
- LLVivoxVoiceClient::getInstance()->clearRenderDevices();
- }
- else if (!stricmp("CaptureDevice", tag))
- {
- deviceString.clear();
- }
- else if (!stricmp("RenderDevice", tag))
- {
- deviceString.clear();
- }
- else if (!stricmp("SessionFont", tag))
- {
- id = 0;
- nameString.clear();
- descriptionString.clear();
- expirationDate = LLDate();
- hasExpired = false;
- fontType = 0;
- fontStatus = 0;
- }
- else if (!stricmp("TemplateFont", tag))
- {
- id = 0;
- nameString.clear();
- descriptionString.clear();
- expirationDate = LLDate();
- hasExpired = false;
- fontType = 0;
- fontStatus = 0;
- }
- else if (!stricmp("MediaCompletionType", tag))
- {
- mediaCompletionType.clear();
- }
- }
- }
- responseDepth++;
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::EndTag(const char *tag)
-{
- const std::string& string = textBuffer;
-
- responseDepth--;
-
- if (ignoringTags)
- {
- if (ignoreDepth == responseDepth)
- {
- LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
- ignoringTags = false;
- }
- else
- {
- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
- }
- }
-
- if (!ignoringTags)
- {
- LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-
- // Closing a tag. Finalize the text we've accumulated and reset
- if (!stricmp("ReturnCode", tag))
- returnCode = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("SessionHandle", tag))
- sessionHandle = string;
- else if (!stricmp("SessionGroupHandle", tag))
- sessionGroupHandle = string;
- else if (!stricmp("StatusCode", tag))
- statusCode = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("StatusString", tag))
- statusString = string;
- else if (!stricmp("ParticipantURI", tag))
- uriString = string;
- else if (!stricmp("Volume", tag))
- volume = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("Energy", tag))
- energy = (F32)strtod(string.c_str(), NULL);
- else if (!stricmp("IsModeratorMuted", tag))
- isModeratorMuted = !stricmp(string.c_str(), "true");
- else if (!stricmp("IsSpeaking", tag))
- isSpeaking = !stricmp(string.c_str(), "true");
- else if (!stricmp("Alias", tag))
- alias = string;
- else if (!stricmp("NumberOfAliases", tag))
- numberOfAliases = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("Application", tag))
- applicationString = string;
- else if (!stricmp("ConnectorHandle", tag))
- connectorHandle = string;
- else if (!stricmp("VersionID", tag))
- versionID = string;
- else if (!stricmp("Version", tag))
- mBuildID = string;
- else if (!stricmp("AccountHandle", tag))
- accountHandle = string;
- else if (!stricmp("State", tag))
- state = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("URI", tag))
- uriString = string;
- else if (!stricmp("IsChannel", tag))
- isChannel = !stricmp(string.c_str(), "true");
- else if (!stricmp("Incoming", tag))
- incoming = !stricmp(string.c_str(), "true");
- else if (!stricmp("Enabled", tag))
- enabled = !stricmp(string.c_str(), "true");
- else if (!stricmp("Name", tag))
- nameString = string;
- else if (!stricmp("AudioMedia", tag))
- audioMediaString = string;
- else if (!stricmp("ChannelName", tag))
- nameString = string;
- else if (!stricmp("DisplayName", tag))
- displayNameString = string;
- else if (!stricmp("Device", tag))
- deviceString = string;
- else if (!stricmp("AccountName", tag))
- nameString = string;
- else if (!stricmp("ParticipantType", tag))
- participantType = strtol(string.c_str(), NULL, 10);
- else if (!stricmp("IsLocallyMuted", tag))
- isLocallyMuted = !stricmp(string.c_str(), "true");
- else if (!stricmp("MicEnergy", tag))
- energy = (F32)strtod(string.c_str(), NULL);
- else if (!stricmp("ChannelName", tag))
- nameString = string;
- else if (!stricmp("ChannelURI", tag))
- uriString = string;
- else if (!stricmp("BuddyURI", tag))
- uriString = string;
- else if (!stricmp("Presence", tag))
- statusString = string;
- else if (!stricmp("CaptureDevices", tag))
- {
- LLVivoxVoiceClient::getInstance()->setDevicesListUpdated(true);
- }
- else if (!stricmp("RenderDevices", tag))
- {
- LLVivoxVoiceClient::getInstance()->setDevicesListUpdated(true);
- }
- else if (!stricmp("CaptureDevice", tag))
- {
- LLVivoxVoiceClient::getInstance()->addCaptureDevice(LLVoiceDevice(displayNameString, deviceString));
- }
- else if (!stricmp("RenderDevice", tag))
- {
- LLVivoxVoiceClient::getInstance()->addRenderDevice(LLVoiceDevice(displayNameString, deviceString));
- }
- else if (!stricmp("BlockMask", tag))
- blockMask = string;
- else if (!stricmp("PresenceOnly", tag))
- presenceOnly = string;
- else if (!stricmp("AutoAcceptMask", tag))
- autoAcceptMask = string;
- else if (!stricmp("AutoAddAsBuddy", tag))
- autoAddAsBuddy = string;
- else if (!stricmp("MessageHeader", tag))
- messageHeader = string;
- else if (!stricmp("MessageBody", tag))
- messageBody = string;
- else if (!stricmp("NotificationType", tag))
- notificationType = string;
- else if (!stricmp("HasText", tag))
- hasText = !stricmp(string.c_str(), "true");
- else if (!stricmp("HasAudio", tag))
- hasAudio = !stricmp(string.c_str(), "true");
- else if (!stricmp("HasVideo", tag))
- hasVideo = !stricmp(string.c_str(), "true");
- else if (!stricmp("Terminated", tag))
- terminated = !stricmp(string.c_str(), "true");
- else if (!stricmp("SubscriptionHandle", tag))
- subscriptionHandle = string;
- else if (!stricmp("SubscriptionType", tag))
- subscriptionType = string;
- else if (!stricmp("SessionFont", tag))
- {
- LLVivoxVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDate, hasExpired, fontType, fontStatus, false);
- }
- else if (!stricmp("TemplateFont", tag))
- {
- LLVivoxVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDate, hasExpired, fontType, fontStatus, true);
- }
- else if (!stricmp("ID", tag))
- {
- id = strtol(string.c_str(), NULL, 10);
- }
- else if (!stricmp("Description", tag))
- {
- descriptionString = string;
- }
- else if (!stricmp("ExpirationDate", tag))
- {
- expirationDate = expiryTimeStampToLLDate(string);
- }
- else if (!stricmp("Expired", tag))
- {
- hasExpired = !stricmp(string.c_str(), "1");
- }
- else if (!stricmp("Type", tag))
- {
- fontType = strtol(string.c_str(), NULL, 10);
- }
- else if (!stricmp("Status", tag))
- {
- fontStatus = strtol(string.c_str(), NULL, 10);
- }
- else if (!stricmp("MediaCompletionType", tag))
- {
- mediaCompletionType = string;;
- }
-
- textBuffer.clear();
- accumulateText= false;
-
- if (responseDepth == 0)
- {
- // We finished all of the XML, process the data
- processResponse(tag);
- }
- }
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::CharData(const char *buffer, int length)
-{
- /*
- This method is called for anything that isn't a tag, which can be text you
- want that lies between tags, and a lot of stuff you don't want like file formatting
- (tabs, spaces, CR/LF, etc).
-
- Only copy text if we are in accumulate mode...
- */
- if (accumulateText)
- textBuffer.append(buffer, length);
-}
-
-// --------------------------------------------------------------------------------
-
-LLDate LLVivoxProtocolParser::expiryTimeStampToLLDate(const std::string& vivox_ts)
-{
- // *HACK: Vivox reports the time incorrectly. LLDate also only parses a
- // subset of valid ISO 8601 dates (only handles Z, not offsets).
- // So just use the date portion and fix the time here.
- std::string time_stamp = vivox_ts.substr(0, 10);
- time_stamp += VOICE_FONT_EXPIRY_TIME;
-
- LL_DEBUGS("VivoxProtocolParser") << "Vivox timestamp " << vivox_ts << " modified to: " << time_stamp << LL_ENDL;
-
- return LLDate(time_stamp);
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::processResponse(std::string tag)
-{
- LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
-
- // SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success. This is a change vs. previous SDKs.
- // According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
- // so I believe this will give correct behavior.
-
- if(returnCode == 0)
- statusCode = 0;
-
- if (isEvent)
- {
- const char *eventTypeCstr = eventTypeString.c_str();
- LL_DEBUGS("LowVoice") << eventTypeCstr << LL_ENDL;
-
- if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
- {
- // These happen so often that logging them is pretty useless.
- LL_DEBUGS("LowVoice") << "Updated Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << isModeratorMuted << ", " << isSpeaking << ", " << volume << ", " << energy << LL_ENDL;
- LLVivoxVoiceClient::getInstance()->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
- }
- else if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
- {
- LLVivoxVoiceClient::getInstance()->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
- }
- else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
- {
- /*
- <Event type="SessionAddedEvent">
- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
- <Uri>sip:confctl-1408789@bhr.vivox.com</Uri>
- <IsChannel>true</IsChannel>
- <Incoming>false</Incoming>
- <ChannelName />
- </Event>
- */
- LLVivoxVoiceClient::getInstance()->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
- }
- else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
- {
- LLVivoxVoiceClient::getInstance()->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
- }
- else if (!stricmp(eventTypeCstr, "SessionGroupUpdatedEvent"))
- {
- //nothng useful to process for this event, but we should not WARN that we have received it.
- }
- else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
- {
- LLVivoxVoiceClient::getInstance()->sessionGroupAddedEvent(sessionGroupHandle);
- }
- else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
- {
- /*
- <Event type="MediaStreamUpdatedEvent">
- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
- <StatusCode>200</StatusCode>
- <StatusString>OK</StatusString>
- <State>2</State>
- <Incoming>false</Incoming>
- </Event>
- */
- LLVivoxVoiceClient::getInstance()->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
- }
- else if (!stricmp(eventTypeCstr, "MediaCompletionEvent"))
- {
- /*
- <Event type="MediaCompletionEvent">
- <SessionGroupHandle />
- <MediaCompletionType>AuxBufferAudioCapture</MediaCompletionType>
- </Event>
- */
- LLVivoxVoiceClient::getInstance()->mediaCompletionEvent(sessionGroupHandle, mediaCompletionType);
- }
- else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
- {
- /*
- <Event type="ParticipantAddedEvent">
- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
- <ParticipantUri>sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com</ParticipantUri>
- <AccountName>xI5auBZ60SJWIk606-1JGRQ==</AccountName>
- <DisplayName />
- <ParticipantType>0</ParticipantType>
- </Event>
- */
- LL_DEBUGS("LowVoice") << "Added Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << ", " << displayNameString << ", " << participantType << LL_ENDL;
- LLVivoxVoiceClient::getInstance()->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
- }
- else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
- {
- /*
- <Event type="ParticipantRemovedEvent">
- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
- <ParticipantUri>sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com</ParticipantUri>
- <AccountName>xtx7YNV-3SGiG7rA1fo5Ndw==</AccountName>
- </Event>
- */
- LL_DEBUGS("LowVoice") << "Removed params:" << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << LL_ENDL;
-
- LLVivoxVoiceClient::getInstance()->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
- }
- else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
- {
- // These are really spammy in tuning mode
- LLVivoxVoiceClient::getInstance()->auxAudioPropertiesEvent(energy);
- }
- else if (!stricmp(eventTypeCstr, "MessageEvent"))
- {
- //TODO: This probably is not received any more, it was used to support SLim clients
- LLVivoxVoiceClient::getInstance()->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
- }
- else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))
- {
- //TODO: This probably is not received any more, it was used to support SLim clients
- LLVivoxVoiceClient::getInstance()->sessionNotificationEvent(sessionHandle, uriString, notificationType);
- }
- else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))
- {
- /*
- <Event type="SessionUpdatedEvent">
- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
- <Uri>sip:confctl-9@bhd.vivox.com</Uri>
- <IsMuted>0</IsMuted>
- <Volume>50</Volume>
- <TransmitEnabled>1</TransmitEnabled>
- <IsFocused>0</IsFocused>
- <SpeakerPosition><Position><X>0</X><Y>0</Y><Z>0</Z></Position></SpeakerPosition>
- <SessionFontID>0</SessionFontID>
- </Event>
- */
- // We don't need to process this, but we also shouldn't warn on it, since that confuses people.
- }
- else if (!stricmp(eventTypeCstr, "SessionGroupRemovedEvent"))
- {
- // We don't need to process this, but we also shouldn't warn on it, since that confuses people.
- }
- else if (!stricmp(eventTypeCstr, "VoiceServiceConnectionStateChangedEvent"))
- {
- LLVivoxVoiceClient::getInstance()->voiceServiceConnectionStateChangedEvent(statusCode, statusString, mBuildID);
- }
- else if (!stricmp(eventTypeCstr, "AudioDeviceHotSwapEvent"))
- {
- /*
- <Event type = "AudioDeviceHotSwapEvent">
- <EventType>RenderDeviceChanged< / EventType>
- <RelevantDevice>
- <Device>Speakers(Turtle Beach P11 Headset)< / Device>
- <DisplayName>Speakers(Turtle Beach P11 Headset)< / DisplayName>
- <Type>SpecificDevice< / Type>
- < / RelevantDevice>
- < / Event>
- */
- // an audio device was removed or added, fetch and update the local list of audio devices.
- LLVivoxVoiceClient::getInstance()->getCaptureDevicesSendMessage();
- LLVivoxVoiceClient::getInstance()->getRenderDevicesSendMessage();
- }
- else
- {
- LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
- }
- }
- else
- {
- const char *actionCstr = actionString.c_str();
- LL_DEBUGS("LowVoice") << actionCstr << LL_ENDL;
-
- if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
- {
- // We don't need to process these
- }
- else if (!stricmp(actionCstr, "Connector.Create.1"))
- {
- LLVivoxVoiceClient::getInstance()->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
- }
- else if (!stricmp(actionCstr, "Account.Login.1"))
- {
- LLVivoxVoiceClient::getInstance()->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
- }
- else if (!stricmp(actionCstr, "Session.Create.1"))
- {
- LLVivoxVoiceClient::getInstance()->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);
- }
- else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
- {
- LLVivoxVoiceClient::getInstance()->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);
- }
- else if (!stricmp(actionCstr, "Session.Connect.1"))
- {
- LLVivoxVoiceClient::getInstance()->sessionConnectResponse(requestId, statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Account.Logout.1"))
- {
- LLVivoxVoiceClient::getInstance()->logoutResponse(statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
- {
- LLVivoxVoiceClient::getInstance()->connectorShutdownResponse(statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Account.GetSessionFonts.1"))
- {
- LLVivoxVoiceClient::getInstance()->accountGetSessionFontsResponse(statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Account.GetTemplateFonts.1"))
- {
- LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
- {
- // both values of statusCode (old and more recent) indicate valid requests
- if (statusCode != 0 && statusCode != 200)
- {
- LL_WARNS("Voice") << "Aux.SetVadProperties.1 request failed: "
- << "statusCode: " << statusCode
- << " and "
- << "statusString: " << statusString
- << LL_ENDL;
- }
- }
- /*
- else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
- {
- LLVoiceClient::getInstance()->channelGetListResponse(statusCode, statusString);
- }
- else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
- {
-
- }
- else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
- {
-
- }
- */
- }
-}
-
-LLVivoxSecurity::LLVivoxSecurity()
-{
- // This size is an arbitrary choice; Vivox does not care
- // Use a multiple of three so that there is no '=' padding in the base64 (purely an esthetic choice)
- #define VIVOX_TOKEN_BYTES 9
- U8 random_value[VIVOX_TOKEN_BYTES];
-
- for (int b = 0; b < VIVOX_TOKEN_BYTES; b++)
- {
- random_value[b] = ll_rand() & 0xff;
- }
- mConnectorHandle = LLBase64::encode(random_value, VIVOX_TOKEN_BYTES);
-
- for (int b = 0; b < VIVOX_TOKEN_BYTES; b++)
- {
- random_value[b] = ll_rand() & 0xff;
- }
- mAccountHandle = LLBase64::encode(random_value, VIVOX_TOKEN_BYTES);
-}
-
-LLVivoxSecurity::~LLVivoxSecurity()
-{
-}
-
-bool LLVivoxVoiceP2PIncomingCall::answerInvite() { return LLVivoxVoiceClient::getInstance()->answerInvite(mCallInfo["session_handle"]); }
-
-void LLVivoxVoiceP2PIncomingCall::declineInvite() { LLVivoxVoiceClient::getInstance()->declineInvite(mCallInfo["session_handle"]); }
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
deleted file mode 100644
index ca1258e05e..0000000000
--- a/indra/newview/llvoicevivox.h
+++ /dev/null
@@ -1,1095 +0,0 @@
-/**
- * @file llvoicevivox.h
- * @brief Declaration of LLDiamondwareVoiceClient class which is the interface to the voice client process.
- *
- * $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_VOICE_VIVOX_H
-#define LL_VOICE_VIVOX_H
-
-class LLVOAvatar;
-class LLVivoxProtocolParser;
-
-#include "lliopipe.h"
-#include "llpumpio.h"
-#include "llchainio.h"
-#include "lliosocket.h"
-#include "v3math.h"
-#include "llframetimer.h"
-#include "llviewerregion.h"
-#include "llcallingcard.h" // for LLFriendObserver
-#include "lleventcoro.h"
-#include "llcoros.h"
-#include "llparcel.h"
-#include "llmutelist.h"
-#include <queue>
-
-#if 1
-# include "expat.h"
-#else
-# include "expat/expat.h"
-#endif
-#include "llvoiceclient.h"
-
-class LLAvatarName;
-class LLVivoxVoiceClientMuteListObserver;
-
-extern const std::string VIVOX_VOICE_SERVER_TYPE;
-
-class LLVivoxVoiceP2PIncomingCall : public LLVoiceP2PIncomingCallInterface
-{
- public:
- LLVivoxVoiceP2PIncomingCall(const LLSD& call_info) : mCallInfo(call_info) {}
- ~LLVivoxVoiceP2PIncomingCall() override {}
-
- bool answerInvite() override;
- void declineInvite() override;
-
- protected:
- LLSD mCallInfo;
-};
-
-class LLVivoxVoiceClient : public LLSingleton<LLVivoxVoiceClient>,
- virtual public LLVoiceModuleInterface,
- virtual public LLVoiceEffectInterface,
- virtual public LLVoiceP2POutgoingCallInterface
-{
- LLSINGLETON(LLVivoxVoiceClient);
- LOG_CLASS(LLVivoxVoiceClient);
- virtual ~LLVivoxVoiceClient();
-
-public:
- /// @name LLVoiceModuleInterface virtual implementations
- /// @see LLVoiceModuleInterface
- //@{
- void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
- void terminate() override; // Call this to clean up during shutdown
-
- const LLVoiceVersionInfo& getVersion() override;
-
- void updateSettings() override; // call after loading settings and whenever they change
-
- // Returns true if vivox has successfully logged in and is not in error state
- bool isVoiceWorking() const override;
-
- void setHidden(bool hidden) override; // virtual
-
- /////////////////////
- /// @name Tuning
- //@{
- void tuningStart() override;
- void tuningStop() override;
- bool inTuningMode() override;
-
- void tuningSetMicVolume(float volume) override;
- void tuningSetSpeakerVolume(float volume) override;
- float tuningGetEnergy(void) override;
-
- //@}
-
- /////////////////////
- /// @name Devices
- //@{
- // This returns true when it's safe to bring up the "device settings" dialog in the prefs.
- // i.e. when the daemon is running and connected, and the device lists are populated.
- bool deviceSettingsAvailable() override;
- bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
-
- // Requery the vivox daemon for the current list of input/output devices.
- // If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
- // (use this if you want to know when it's done).
- // If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
- void refreshDeviceLists(bool clearCurrentList = true) override;
-
- void setCaptureDevice(const std::string& name) override;
- void setRenderDevice(const std::string& name) override;
-
- LLVoiceDeviceList& getCaptureDevices() override;
- LLVoiceDeviceList& getRenderDevices() override;
- //@}
-
- void getParticipantList(std::set<LLUUID> &participants) override;
- bool isParticipant(const LLUUID& speaker_id) override;
-
- // Send a text message to the specified user, initiating the session if necessary.
- // virtual bool sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};
-
- // Returns true if calling back the session URI after the session has closed is possible.
- // Currently this will be false only for PSTN P2P calls.
- // NOTE: this will return true if the session can't be found.
- bool isSessionCallBackPossible(const LLUUID &session_id) override;
-
- // Returns true if the session can accepte text IM's.
- // Currently this will be false only for PSTN P2P calls.
- // NOTE: this will return true if the session can't be found.
- bool isSessionTextIMPossible(const LLUUID &session_id) override;
-
- ////////////////////////////
- /// @name Channel stuff
- //@{
- // returns true iff the user is currently in a proximal (local spatial) channel.
- // Note that gestures should only fire if this returns true.
- bool inProximalChannel() override;
-
- void setNonSpatialChannel(const LLSD& channelInfo,
- bool notify_on_first_join,
- bool hangup_on_last_leave) override;
-
- bool setSpatialChannel(const LLSD& channelInfo) override;
-
- void leaveNonSpatialChannel() override;
-
- void processChannels(bool process) override;
-
- void leaveChannel(void);
-
- bool isCurrentChannel(const LLSD &channelInfo) override;
- bool compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) override;
-
- //@}
-
-
- //////////////////////////
- /// @name LLVoiceP2POutgoingCallInterface
- //@{
- // start a voice channel with the specified user
- void callUser(const LLUUID &uuid) override;
- void hangup() override;
-
- //@}
-
- LLVoiceP2POutgoingCallInterface *getOutgoingCallInterface() override { return this; }
-
- LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voice_call_info) override;
-
- bool answerInvite(const std::string &sessionHandle);
- void declineInvite(const std::string &sessionHandle);
-
- /////////////////////////
- /// @name Volume/gain
- //@{
- void setVoiceVolume(F32 volume) override;
- void setMicGain(F32 volume) override;
- //@}
-
- /////////////////////////
- /// @name enable disable voice and features
- //@{
- void setVoiceEnabled(bool enabled) override;
- void setMuteMic(bool muted) override; // Set the mute state of the local mic.
- //@}
-
- //////////////////////////
- /// @name nearby speaker accessors
- //@{
- std::string getDisplayName(const LLUUID& id) override;
- bool isParticipantAvatar(const LLUUID &id) override;
- bool getIsSpeaking(const LLUUID& id) override;
- bool getIsModeratorMuted(const LLUUID& id) override;
- F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
- F32 getUserVolume(const LLUUID& id) override;
- void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
- //@}
-
- // authorize the user
- void userAuthorized(const std::string& user_id,
- const LLUUID &agentID) override;
-
- //////////////////////////////
- /// @name Status notification
- //@{
- void addObserver(LLVoiceClientStatusObserver* observer) override;
- void removeObserver(LLVoiceClientStatusObserver* observer) override;
- void addObserver(LLFriendObserver* observer) override;
- void removeObserver(LLFriendObserver* observer) override;
- void addObserver(LLVoiceClientParticipantObserver* observer) override;
- void removeObserver(LLVoiceClientParticipantObserver* observer) override;
- //@}
-
- std::string sipURIFromID(const LLUUID &id) const override;
- LLSD getP2PChannelInfoTemplate(const LLUUID& id) const override;
- //@}
-
- /// @name LLVoiceEffectInterface virtual implementations
- /// @see LLVoiceEffectInterface
- //@{
-
- //////////////////////////
- /// @name Accessors
- //@{
- bool setVoiceEffect(const LLUUID& id) override;
- const LLUUID getVoiceEffect() override;
- LLSD getVoiceEffectProperties(const LLUUID& id) override;
-
- void refreshVoiceEffectLists(bool clear_lists) override;
- const voice_effect_list_t& getVoiceEffectList() const override;
- const voice_effect_list_t& getVoiceEffectTemplateList() const override;
- //@}
-
- //////////////////////////////
- /// @name Status notification
- //@{
- void addObserver(LLVoiceEffectObserver* observer) override;
- void removeObserver(LLVoiceEffectObserver* observer) override;
- //@}
-
- //////////////////////////////
- /// @name Effect preview buffer
- //@{
- void enablePreviewBuffer(bool enable) override;
- void recordPreviewBuffer() override;
- void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override;
- void stopPreviewBuffer() override;
-
- bool isPreviewRecording() override;
- bool isPreviewPlaying() override;
- //@}
-
- //@}
-
- bool onCheckVoiceEffect(const std::string& voice_effect_name);
- void onClickVoiceEffect(const std::string& voice_effect_name);
-
-protected:
- //////////////////////
- // Vivox Specific definitions
-
- friend class LLVivoxVoiceClientMuteListObserver;
- friend class LLVivoxVoiceClientFriendsObserver;
-
-
- enum streamState
- {
- streamStateUnknown = 0,
- streamStateIdle = 1,
- streamStateConnected = 2,
- streamStateRinging = 3,
- streamStateConnecting = 6, // same as Vivox session_media_connecting enum
- streamStateDisconnecting = 7, //Same as Vivox session_media_disconnecting enum
- };
-
- struct participantState
- {
- public:
- participantState(const std::string &uri);
-
- bool updateMuteState(); // true if mute state has changed
- bool isAvatar();
-
- std::string mURI;
- LLUUID mAvatarID;
- std::string mAccountName;
- std::string mDisplayName;
- LLFrameTimer mSpeakingTimeout;
- F32 mLastSpokeTimestamp;
- F32 mPower;
- F32 mVolume;
- std::string mGroupID;
- int mUserVolume;
- bool mPTT;
- bool mIsSpeaking;
- bool mIsModeratorMuted;
- bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted)
- bool mVolumeSet; // true if incoming volume messages should not change the volume
- bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
- bool mAvatarIDValid;
- bool mIsSelf;
- };
- typedef std::shared_ptr<participantState> participantStatePtr_t;
- typedef std::weak_ptr<participantState> participantStateWptr_t;
-
- typedef std::map<const std::string, participantStatePtr_t> participantMap;
- typedef std::map<const LLUUID, participantStatePtr_t> participantUUIDMap;
-
- struct sessionState
- {
- public:
- typedef std::shared_ptr<sessionState> ptr_t;
- typedef std::weak_ptr<sessionState> wptr_t;
-
- typedef std::function<void(const ptr_t &)> sessionFunc_t;
-
- static ptr_t createSession();
- ~sessionState();
-
- LLSD getVoiceChannelInfo();
-
- participantStatePtr_t addParticipant(const std::string &uri);
- void removeParticipant(const participantStatePtr_t &participant);
- void removeAllParticipants();
-
- participantStatePtr_t findParticipant(const std::string &uri);
- participantStatePtr_t findParticipantByID(const LLUUID& id);
-
- static ptr_t matchSessionByHandle(const std::string &handle);
- static ptr_t matchCreatingSessionByURI(const std::string &uri);
- static ptr_t matchSessionByURI(const std::string &uri);
- static ptr_t matchSessionByParticipant(const LLUUID &participant_id);
-
- bool isCallBackPossible();
- bool isTextIMPossible();
- bool isSpatial() { return mIsSpatial; }
-
- static void for_each(sessionFunc_t func);
-
- std::string mHandle;
- std::string mGroupHandle;
- std::string mSIPURI;
- std::string mAlias;
- std::string mName;
- std::string mAlternateSIPURI;
- std::string mHash; // Channel password
- std::string mErrorStatusString;
- std::queue<std::string> mTextMsgQueue;
-
- LLUUID mIMSessionID;
- LLUUID mCallerID;
- int mErrorStatusCode;
- int mMediaStreamState;
- bool mCreateInProgress; // True if a Session.Create has been sent for this session and no response has been received yet.
- bool mMediaConnectInProgress; // True if a Session.MediaConnect has been sent for this session and no response has been received yet.
- bool mVoiceInvitePending; // True if a voice invite is pending for this session (usually waiting on a name lookup)
- bool mTextInvitePending; // True if a text invite is pending for this session (usually waiting on a name lookup)
- bool mSynthesizedCallerID; // True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
- bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN)
- bool mIsSpatial; // True for spatial channels
- bool mIsP2P;
- bool mIncoming;
- bool mVoiceActive;
- bool mReconnect; // Whether we should try to reconnect to this session if it's dropped
-
- // Set to true when the volume/mute state of someone in the participant list changes.
- // The code will have to walk the list to find the changed participant(s).
- bool mVolumeDirty;
- bool mMuteDirty;
-
- bool mParticipantsChanged;
- participantMap mParticipantsByURI;
- participantUUIDMap mParticipantsByUUID;
-
- LLUUID mVoiceFontID;
-
- static void VerifySessions();
-
- private:
- sessionState();
-
- static std::set<wptr_t, std::owner_less<wptr_t>> mSession; // canonical list of outstanding sessions.
- std::set<wptr_t>::iterator mMyIterator; // used for delete
-
- static void for_eachPredicate(const wptr_t &a, sessionFunc_t func);
-
- static bool testByHandle(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string handle);
- static bool testByCreatingURI(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string uri);
- static bool testBySIPOrAlterateURI(const LLVivoxVoiceClient::sessionState::wptr_t &a, std::string uri);
- static bool testByCallerId(const LLVivoxVoiceClient::sessionState::wptr_t &a, LLUUID participantId);
-
- };
- typedef std::shared_ptr<sessionState> sessionStatePtr_t;
-
- typedef std::map<std::string, sessionStatePtr_t> sessionMap;
-
- ///////////////////////////////////////////////////////
- // Private Member Functions
- //////////////////////////////////////////////////////
-
-
-
- //////////////////////////////
- /// @name TVC/Server management and communication
- //@{
- // Call this if the connection to the daemon terminates unexpectedly. It will attempt to reset everything and relaunch.
- void daemonDied();
-
- // Call this if we're just giving up on voice (can't provision an account, etc.). It will clean up and go away.
- void giveUp();
-
- // write to the tvc
- bool writeString(const std::string &str);
-
- void connectorCreate();
- void connectorShutdown();
- void closeSocket(void);
-
-// void requestVoiceAccountProvision(S32 retries = 3);
- void setLoginInfo(
- const std::string& account_name,
- const std::string& password,
- const std::string& voice_sip_uri_hostname,
- const std::string& voice_account_server_uri);
- void loginSendMessage();
- void logout();
- void logoutSendMessage();
-
-
- //@}
-
- //------------------------------------
- // tuning
-
- void tuningRenderStartSendMessage(const std::string& name, bool loop);
- void tuningRenderStopSendMessage();
-
- void tuningCaptureStartSendMessage(int duration);
- void tuningCaptureStopSendMessage();
-
- //----------------------------------
- // devices
- void clearCaptureDevices();
- void addCaptureDevice(const LLVoiceDevice& device);
- void clearRenderDevices();
- void setDevicesListUpdated(bool state);
- void addRenderDevice(const LLVoiceDevice& device);
- void buildSetAudioDevices(std::ostringstream &stream);
-
- void getCaptureDevicesSendMessage();
- void getRenderDevicesSendMessage();
-
- // local audio updates, mic mute, speaker mute, mic volume and speaker volumes
- void sendLocalAudioUpdates();
-
- /////////////////////////////
- // Response/Event handlers
- void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
- void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
- void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
- void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
- void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
- void logoutResponse(int statusCode, std::string &statusString);
- void connectorShutdownResponse(int statusCode, std::string &statusString);
-
- void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
- void mediaCompletionEvent(std::string &sessionGroupHandle, std::string &mediaCompletionType);
- void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
- void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
- void sessionGroupAddedEvent(std::string &sessionGroupHandle);
- void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
- void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
- void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
- void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
- void voiceServiceConnectionStateChangedEvent(int statusCode, std::string &statusString, std::string &build_id);
- void auxAudioPropertiesEvent(F32 energy);
- void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
- void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType);
-
- void muteListChanged();
-
- /////////////////////////////
- // VAD changes
- // disable auto-VAD and configure VAD parameters explicitly
- void setupVADParams(unsigned int vad_auto, unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
- void onVADSettingsChange();
-
- /////////////////////////////
- // Sending updates of current state
- void updatePosition(void);
- void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
- void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot);
- bool channelFromRegion(LLViewerRegion *region, std::string &name);
-
- void setEarLocation(S32 loc);
-
-
- /////////////////////////////
- // Accessors for data related to nearby speakers
-
- // MBW -- XXX -- Not sure how to get this data out of the TVC
- bool getUsingPTT(const LLUUID& id);
- std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable)
-
- /////////////////////////////
- // Recording controls
- void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
- void recordingLoopSave(const std::string& filename);
- void recordingStop();
-
- // Playback controls
- void filePlaybackStart(const std::string& filename);
- void filePlaybackStop();
- void filePlaybackSetPaused(bool paused);
- void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
-
- participantStatePtr_t findParticipantByID(const LLUUID& id);
-
-
-#if 0
- ////////////////////////////////////////
- // voice sessions.
- typedef std::set<sessionStatePtr_t> sessionSet;
-
- typedef sessionSet::iterator sessionIterator;
- sessionIterator sessionsBegin(void);
- sessionIterator sessionsEnd(void);
-#endif
-
- sessionStatePtr_t findSession(const std::string &handle);
- sessionStatePtr_t findSessionBeingCreatedByURI(const std::string &uri);
- sessionStatePtr_t findSession(const LLUUID &participant_id);
-
- sessionStatePtr_t addSession(const std::string &uri, const std::string &handle = std::string());
- void clearSessionHandle(const sessionStatePtr_t &session);
- void setSessionHandle(const sessionStatePtr_t &session, const std::string &handle);
- void setSessionURI(const sessionStatePtr_t &session, const std::string &uri);
- void deleteSession(const sessionStatePtr_t &session);
- void deleteAllSessions(void);
-
- void verifySessionState(void);
-
- void joinedAudioSession(const sessionStatePtr_t &session);
- void leftAudioSession(const sessionStatePtr_t &session);
-
- // This is called in several places where the session _may_ need to be deleted.
- // It contains logic for whether to delete the session or keep it around.
- void reapSession(const sessionStatePtr_t &session);
-
- // Returns true if the session seems to indicate we've moved to a region on a different voice server
- bool sessionNeedsRelog(const sessionStatePtr_t &session);
-
-
- //////////////////////////////////////
- // buddy list stuff, needed for SLIM later
- struct buddyListEntry
- {
- buddyListEntry(const std::string &uri);
- std::string mURI;
- std::string mDisplayName;
- LLUUID mUUID;
- bool mOnlineSL;
- bool mOnlineSLim;
- bool mCanSeeMeOnline;
- bool mHasBlockListEntry;
- bool mHasAutoAcceptListEntry;
- bool mNameResolved;
- bool mInSLFriends;
- bool mInVivoxBuddies;
- };
-
- typedef std::map<std::string, buddyListEntry*> buddyListMap;
-
- /////////////////////////////
- // session control messages
-
- void accountListBlockRulesSendMessage();
- void accountListAutoAcceptRulesSendMessage();
-
- void sessionGroupCreateSendMessage();
- void sessionCreateSendMessage(const sessionStatePtr_t &session, bool startAudio = true, bool startText = false);
- void sessionGroupAddSessionSendMessage(const sessionStatePtr_t &session, bool startAudio = true, bool startText = false);
- void sessionMediaConnectSendMessage(const sessionStatePtr_t &session); // just joins the audio session
- void sessionTextConnectSendMessage(const sessionStatePtr_t &session); // just joins the text session
- void sessionTerminateSendMessage(const sessionStatePtr_t &session);
- void sessionGroupTerminateSendMessage(const sessionStatePtr_t &session);
- void sessionMediaDisconnectSendMessage(const sessionStatePtr_t &session);
- // void sessionTextDisconnectSendMessage(sessionState *session);
-
-
-
- // Pokes the state machine to leave the audio session next time around.
- void sessionTerminate();
-
- // Pokes the state machine to shut down the connector and restart it.
- void requestRelog();
-
- // Does the actual work to get out of the audio session
- void leaveAudioSession();
-
- friend class LLVivoxVoiceClientCapResponder;
-
-
- void lookupName(const LLUUID &id);
- void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
- void avatarNameResolved(const LLUUID &id, const std::string &name);
- static void predAvatarNameResolution(const LLVivoxVoiceClient::sessionStatePtr_t &session, LLUUID id, std::string name);
-
- boost::signals2::connection mAvatarNameCacheConnection;
-
- /////////////////////////////
- // Voice fonts
-
- void addVoiceFont(const S32 id,
- const std::string &name,
- const std::string &description,
- const LLDate &expiration_date,
- bool has_expired,
- const S32 font_type,
- const S32 font_status,
- const bool template_font = false);
- void accountGetSessionFontsResponse(int statusCode, const std::string &statusString);
- void accountGetTemplateFontsResponse(int statusCode, const std::string &statusString);
-
-private:
-
- LLVoiceVersionInfo mVoiceVersion;
-
- // Coroutine support methods
- //---
- void voiceControlCoro();
- void voiceControlStateMachine(S32 &coro_state);
-
- bool endAndDisconnectSession();
-
- bool callbackEndDaemon(const LLSD& data);
- bool startAndLaunchDaemon();
- bool provisionVoiceAccount();
- bool establishVoiceConnection();
- bool breakVoiceConnection(bool wait);
- bool loginToVivox();
- void logoutOfVivox(bool wait);
- bool retrieveVoiceFonts();
-
- bool requestParcelVoiceInfo();
-
- bool addAndJoinSession(const sessionStatePtr_t &nextSession);
- bool terminateAudioSession(bool wait);
-
- bool waitForChannel();
- bool runSession(const sessionStatePtr_t &session);
-
- void recordingAndPlaybackMode();
- int voiceRecordBuffer();
- int voicePlaybackBuffer();
-
- bool performMicTuning();
- //---
- /// Clean up objects created during a voice session.
- void cleanUp();
-
- bool mSessionTerminateRequested;
- bool mRelogRequested;
- // Number of times (in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine().
- // The larger it is the greater is possibility there is a problem with connection to voice server.
- // Introduced while fixing EXT-4313.
- int mSpatialJoiningNum;
-
- static void idle(void *user_data);
-
- LLHost mDaemonHost;
- LLSocket::ptr_t mSocket;
-
- // We should kill the voice daemon in case of connection alert
- bool mTerminateDaemon;
-
- friend class LLVivoxProtocolParser;
-
- std::string mAccountName;
- std::string mAccountPassword;
- std::string mAccountDisplayName;
-
- bool mTuningMode;
- float mTuningEnergy;
- std::string mTuningAudioFile;
- int mTuningMicVolume;
- bool mTuningMicVolumeDirty;
- int mTuningSpeakerVolume;
- bool mTuningSpeakerVolumeDirty;
- bool mDevicesListUpdated; // set to true when the device list has been updated
- // and false when the panelvoicedevicesettings has queried for an update status.
-
- std::string mSpatialSessionURI;
- std::string mSpatialSessionCredentials;
-
- std::string mMainSessionGroupHandle; // handle of the "main" session group.
-
- std::string mChannelName; // Name of the channel to be looked up
- sessionStatePtr_t mAudioSession; // Session state for the current audio session
-
- sessionStatePtr_t mNextAudioSession; // Session state for the audio session we're trying to join
-
- S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings
- std::string mCurrentRegionName; // Used to detect parcel boundary crossings
-
- bool mConnectorEstablished; // set by "Create Connector" response
- bool mAccountLoggedIn; // set by login message
- int mNumberOfAliases;
- U32 mCommandCookie;
-
- std::string mVoiceAccountServerURI;
- std::string mVoiceSIPURIHostName;
-
- int mLoginRetryCount;
-
- sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map.
-#if 0
- sessionSet mSessions; // All sessions, not indexed. This is the canonical session list.
-#endif
-
- bool mBuddyListMapPopulated;
- bool mBlockRulesListReceived;
- bool mAutoAcceptRulesListReceived;
- buddyListMap mBuddyListMap;
-
- LLVoiceDeviceList mCaptureDevices;
- LLVoiceDeviceList mRenderDevices;
-
- std::string mCaptureDevice;
- std::string mRenderDevice;
- bool mCaptureDeviceDirty;
- bool mRenderDeviceDirty;
-
- bool mIsInitialized;
- bool mShutdownComplete;
-
- bool checkParcelChanged(bool update = false);
- bool switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
- void joinSession(const sessionStatePtr_t &session);
-
- std::string nameFromID(const LLUUID &id) const;
- bool IDFromName(const std::string name, LLUUID &uuid);
- std::string sipURIFromAvatar(LLVOAvatar *avatar);
- std::string sipURIFromName(std::string &name);
-
- // Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
- std::string nameFromsipURI(const std::string &uri);
-
- bool inSpatialChannel(void);
- LLSD getAudioSessionChannelInfo();
- std::string getAudioSessionHandle();
-
- void sendPositionAndVolumeUpdate(void);
-
- void sendCaptureAndRenderDevices();
- void buildSetCaptureDevice(std::ostringstream &stream);
- void buildSetRenderDevice(std::ostringstream &stream);
-
-
- void sendFriendsListUpdates();
-
-#if 0
- // start a text IM session with the specified user
- // This will be asynchronous, the session may be established at a future time.
- sessionStatePtr_t startUserIMSession(const LLUUID& uuid);
-#endif
-
- void enforceTether(void);
-
- bool mSpatialCoordsDirty;
-
- LLVector3d mCameraPosition;
- LLVector3d mCameraRequestedPosition;
- LLVector3 mCameraVelocity;
- LLMatrix3 mCameraRot;
-
- LLVector3d mAvatarPosition;
- LLVector3 mAvatarVelocity;
- LLQuaternion mAvatarRot;
-
- bool mMuteMic;
- bool mMuteMicDirty;
- bool mHidden; //Set to true during teleport to hide the agent's position.
-
- // Set to true when the friends list is known to have changed.
- bool mFriendsListDirty;
-
- enum
- {
- earLocCamera = 0, // ear at camera
- earLocAvatar, // ear at avatar
- earLocMixed // ear at avatar location/camera direction
- };
-
- S32 mEarLocation;
-
- bool mSpeakerVolumeDirty;
- bool mSpeakerMuteDirty;
- int mSpeakerVolume;
-
- int mMicVolume;
- bool mMicVolumeDirty;
-
- bool mVoiceEnabled;
- bool mProcessChannels;
- bool mWriteInProgress;
- std::string mWriteString;
- size_t mWriteOffset;
-
- typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
- observer_set_t mParticipantObservers;
-
- void notifyParticipantObservers();
-
- typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
- status_observer_set_t mStatusObservers;
-
- void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
-
- typedef std::set<LLFriendObserver*> friend_observer_set_t;
- friend_observer_set_t mFriendObservers;
- void notifyFriendObservers();
-
- // Voice Fonts
-
- void expireVoiceFonts();
- void deleteVoiceFont(const LLUUID& id);
- void deleteAllVoiceFonts();
- void deleteVoiceFontTemplates();
-
- S32 getVoiceFontIndex(const LLUUID& id) const;
- S32 getVoiceFontTemplateIndex(const LLUUID& id) const;
-
- void accountGetSessionFontsSendMessage();
- void accountGetTemplateFontsSendMessage();
- void sessionSetVoiceFontSendMessage(const sessionStatePtr_t &session);
-
- void updateVoiceMorphingMenu();
- void notifyVoiceFontObservers();
-
- typedef enum e_voice_font_type
- {
- VOICE_FONT_TYPE_NONE = 0,
- VOICE_FONT_TYPE_ROOT = 1,
- VOICE_FONT_TYPE_USER = 2,
- VOICE_FONT_TYPE_UNKNOWN
- } EVoiceFontType;
-
- typedef enum e_voice_font_status
- {
- VOICE_FONT_STATUS_NONE = 0,
- VOICE_FONT_STATUS_FREE = 1,
- VOICE_FONT_STATUS_NOT_FREE = 2,
- VOICE_FONT_STATUS_UNKNOWN
- } EVoiceFontStatus;
-
- struct voiceFontEntry
- {
- voiceFontEntry(LLUUID& id);
- ~voiceFontEntry();
-
- LLUUID mID;
- S32 mFontIndex;
- std::string mName;
- LLDate mExpirationDate;
- S32 mFontType;
- S32 mFontStatus;
- bool mIsNew;
-
- LLFrameTimer mExpiryTimer;
- };
-
- bool mVoiceFontsReceived;
- bool mVoiceFontsNew;
- bool mVoiceFontListDirty;
- voice_effect_list_t mVoiceFontList;
- voice_effect_list_t mVoiceFontTemplateList;
-
- typedef std::map<const LLUUID, voiceFontEntry*> voice_font_map_t;
- voice_font_map_t mVoiceFontMap;
- voice_font_map_t mVoiceFontTemplateMap;
-
- typedef std::set<LLVoiceEffectObserver*> voice_font_observer_set_t;
- voice_font_observer_set_t mVoiceFontObservers;
-
- LLFrameTimer mVoiceFontExpiryTimer;
-
-
- // Audio capture buffer
-
- void captureBufferRecordStartSendMessage();
- void captureBufferRecordStopSendMessage();
- void captureBufferPlayStartSendMessage(const LLUUID& voice_font_id = LLUUID::null);
- void captureBufferPlayStopSendMessage();
-
- bool mCaptureBufferMode; // Disconnected from voice channels while using the capture buffer.
- bool mCaptureBufferRecording; // A voice sample is being captured.
- bool mCaptureBufferRecorded; // A voice sample is captured in the buffer ready to play.
- bool mCaptureBufferPlaying; // A voice sample is being played.
-
- LLTimer mCaptureTimer;
- LLUUID mPreviewVoiceFont;
- LLUUID mPreviewVoiceFontLast;
- S32 mPlayRequestCount;
- bool mIsInTuningMode;
- bool mIsInChannel;
- bool mIsJoiningSession;
- bool mIsWaitingForFonts;
- bool mIsLoggingIn;
- bool mIsLoggedIn;
- bool mIsProcessingChannels;
- bool mIsCoroutineActive;
-
- // This variables can last longer than vivox in coroutines so we need them as static
- static bool sShuttingDown;
- static bool sConnected;
- static LLPumpIO* sPump;
-
- LLEventMailDrop mVivoxPump;
-};
-
-
-/**
- * @class LLVivoxProtocolParser
- * @brief This class helps construct new LLIOPipe specializations
- * @see LLIOPipe
- *
- * THOROUGH_DESCRIPTION
- */
-class LLVivoxProtocolParser : public LLIOPipe
-{
- LOG_CLASS(LLVivoxProtocolParser);
-public:
- LLVivoxProtocolParser();
- virtual ~LLVivoxProtocolParser();
-
-protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
-
- std::string mInput;
-
- // Expat control members
- XML_Parser parser;
- int responseDepth;
- bool ignoringTags;
- bool isEvent;
- int ignoreDepth;
-
- // Members for processing responses. The values are transient and only valid within a call to processResponse().
- int returnCode;
- int statusCode;
- std::string statusString;
- std::string requestId;
- std::string actionString;
- std::string connectorHandle;
- std::string versionID;
- std::string mBuildID;
- std::string accountHandle;
- std::string sessionHandle;
- std::string sessionGroupHandle;
- std::string alias;
- std::string applicationString;
-
- // Members for processing events. The values are transient and only valid within a call to processResponse().
- std::string eventTypeString;
- int state;
- std::string uriString;
- bool isChannel;
- bool incoming;
- bool enabled;
- std::string nameString;
- std::string audioMediaString;
- std::string deviceString;
- std::string displayNameString;
- int participantType;
- bool isLocallyMuted;
- bool isModeratorMuted;
- bool isSpeaking;
- int volume;
- F32 energy;
- std::string messageHeader;
- std::string messageBody;
- std::string notificationType;
- bool hasText;
- bool hasAudio;
- bool hasVideo;
- bool terminated;
- std::string blockMask;
- std::string presenceOnly;
- std::string autoAcceptMask;
- std::string autoAddAsBuddy;
- int numberOfAliases;
- std::string subscriptionHandle;
- std::string subscriptionType;
- S32 id;
- std::string descriptionString;
- LLDate expirationDate;
- bool hasExpired;
- S32 fontType;
- S32 fontStatus;
- std::string mediaCompletionType;
-
- // Members for processing text between tags
- std::string textBuffer;
- bool accumulateText;
-
- void reset();
-
- void processResponse(std::string tag);
-
- static void XMLCALL ExpatStartTag(void *data, const char *el, const char **attr);
- static void XMLCALL ExpatEndTag(void *data, const char *el);
- static void XMLCALL ExpatCharHandler(void *data, const XML_Char *s, int len);
-
- void StartTag(const char *tag, const char **attr);
- void EndTag(const char *tag);
- void CharData(const char *buffer, int length);
- LLDate expiryTimeStampToLLDate(const std::string& vivox_ts);
-
-};
-
-class LLVivoxSecurity : public LLSingleton<LLVivoxSecurity>
-{
- LLSINGLETON(LLVivoxSecurity);
- virtual ~LLVivoxSecurity();
-
- public:
- std::string connectorHandle() { return mConnectorHandle; };
- std::string accountHandle() { return mAccountHandle; };
-
- private:
- std::string mConnectorHandle;
- std::string mAccountHandle;
-};
-
-class LLVoiceVivoxStats : public LLSingleton<LLVoiceVivoxStats>
-{
- LLSINGLETON(LLVoiceVivoxStats);
- LOG_CLASS(LLVoiceVivoxStats);
- virtual ~LLVoiceVivoxStats();
-
- private:
- F64SecondsImplicit mStartTime;
-
- U32 mConnectCycles;
-
- F64 mConnectTime;
- U32 mConnectAttempts;
-
- F64 mProvisionTime;
- U32 mProvisionAttempts;
-
- F64 mEstablishTime;
- U32 mEstablishAttempts;
-
- public:
-
- void reset();
- void connectionAttemptStart();
- void connectionAttemptEnd(bool success);
- void provisionAttemptStart();
- void provisionAttemptEnd(bool success);
- void establishAttemptStart();
- void establishAttemptEnd(bool success);
- LLSD read();
-};
-
-#endif //LL_VIVOX_VOICE_CLIENT_H
-
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 06ccd23670..33cdf66272 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -61,10 +61,12 @@
#include "llrand.h"
#include "llviewerwindow.h"
#include "llviewercamera.h"
+#include "llviewerstats.h"
#include "llversioninfo.h"
#include "llviewernetwork.h"
#include "llnotificationsutil.h"
+#include "llnearbyvoicemoderation.h"
#include "llcorehttputil.h"
#include "lleventfilter.h"
@@ -80,6 +82,8 @@
const std::string WEBRTC_VOICE_SERVER_TYPE = "webrtc";
+const F32 STATS_TIMER_DELAY = 2.0;
+
namespace {
const F32 MAX_AUDIO_DIST = 50.0f;
@@ -343,6 +347,46 @@ const LLVoiceVersionInfo& LLWebRTCVoiceClient::getVersion()
return mVoiceVersion;
}
+// --------------------------------------------------
+
+void LLWebRTCVoiceClient::updateVersion()
+{
+ sessionStatePtr_t session = mNextSession.get() ? mNextSession : mSession;
+
+ if (session)
+ {
+ // A WebRTC session can be connected to multiple servers at once. To more easily disambiguate which server version is being printed, show the connection type. In most cases, this shouldn't matter and the Janus version should be the same for all connections. Janus versions are also logged for each connection.
+ mVoiceVersion.serverVersion = session->getVersion();
+ if (dynamic_cast<adhocSessionState*>(session.get()))
+ {
+ if (session->mHangupOnLastLeave)
+ {
+ mVoiceVersion.mBuildVersion = "p2p";
+ }
+ else
+ {
+ mVoiceVersion.mBuildVersion = "ad-hoc";
+ }
+ }
+ else if (session->isEstate())
+ {
+ mVoiceVersion.mBuildVersion = "estate";
+ }
+ else if (session->isSpatial())
+ {
+ mVoiceVersion.mBuildVersion = "parcel";
+ }
+ else
+ {
+ mVoiceVersion.mBuildVersion = mVoiceVersion.serverVersion;
+ }
+ }
+ else
+ {
+ mVoiceVersion.serverVersion = mVoiceVersion.mBuildVersion = "";
+ }
+}
+
//---------------------------------------------------
void LLWebRTCVoiceClient::updateSettings()
@@ -1634,6 +1678,10 @@ void LLWebRTCVoiceClient::setVoiceVolume(F32 volume)
void LLWebRTCVoiceClient::predSetSpeakerVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume)
{
+ if (session->mShuttingDown)
+ {
+ return;
+ }
session->setSpeakerVolume(volume);
}
@@ -1663,6 +1711,14 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled)
mVoiceEnabled = enabled;
LLVoiceClientStatusObserver::EStatusType status;
+ // Gate the audio devices on voice being enabled: the capture mic and
+ // playout speaker only run while voice is on, and the mic isn't held
+ // open when voice is off.
+ if (mWebRTCDeviceInterface)
+ {
+ mWebRTCDeviceInterface->setVoiceEnabled(enabled);
+ }
+
if (enabled)
{
LL_DEBUGS("Voice") << "enabling" << LL_ENDL;
@@ -1862,6 +1918,10 @@ LLWebRTCVoiceClient::sessionState::sessionState() :
void LLWebRTCVoiceClient::predUpdateOwnVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 audio_level)
{
+ if (session->mShuttingDown)
+ {
+ return;
+ }
participantStatePtr_t participant = session->findParticipantByID(gAgentID);
if (participant)
{
@@ -1890,9 +1950,16 @@ void LLWebRTCVoiceClient::sessionState::sendData(const std::string &data)
void LLWebRTCVoiceClient::sessionState::setMuteMic(bool muted)
{
mMuted = muted;
+ if (mShuttingDown)
+ {
+ return;
+ }
for (auto &connection : mWebRTCConnections)
{
- connection->setMuteMic(muted);
+ if (!connection->isShuttingDown())
+ {
+ connection->setMuteMic(muted);
+ }
}
}
@@ -1901,7 +1968,10 @@ void LLWebRTCVoiceClient::sessionState::setSpeakerVolume(F32 volume)
mSpeakerVolume = volume;
for (auto &connection : mWebRTCConnections)
{
- connection->setSpeakerVolume(volume);
+ if (!connection->isShuttingDown())
+ {
+ connection->setSpeakerVolume(volume);
+ }
}
}
@@ -1913,7 +1983,10 @@ void LLWebRTCVoiceClient::sessionState::setUserVolume(const LLUUID &id, F32 volu
}
for (auto &connection : mWebRTCConnections)
{
- connection->setUserVolume(id, volume);
+ if (!connection->isShuttingDown())
+ {
+ connection->setUserVolume(id, volume);
+ }
}
}
@@ -1925,7 +1998,10 @@ void LLWebRTCVoiceClient::sessionState::setUserMute(const LLUUID &id, bool mute)
}
for (auto &connection : mWebRTCConnections)
{
- connection->setUserMute(id, mute);
+ if (!connection->isShuttingDown())
+ {
+ connection->setUserMute(id, mute);
+ }
}
}
/*static*/
@@ -2054,6 +2130,22 @@ void LLWebRTCVoiceClient::sessionState::revive()
mShuttingDown = false;
}
+const std::string LLWebRTCVoiceClient::sessionState::getVersion() const
+{
+ // Prefer the version of a primary connection which has already received a version string over the data channel. If that does not make sense, fall back to any non-empty version string we can find.
+ bool primary = true;
+ do
+ {
+ for (auto& connection : mWebRTCConnections) {
+ if (connection->isPrimary() == primary && connection->getVersion().length()) {
+ return connection->getVersion();
+ }
+ }
+ primary = !primary;
+ } while (!primary);
+ return "";
+}
+
//=========================================================================
// the following are methods to support the coroutine implementation of the
// voice connection and processing. They should only be called in the context
@@ -2250,6 +2342,11 @@ void LLWebRTCVoiceClient::deleteSession(const sessionStatePtr_t &session)
{
mNextSession.reset();
}
+
+ if (!sShuttingDown)
+ {
+ updateVersion();
+ }
}
@@ -2288,12 +2385,6 @@ void LLWebRTCVoiceClient::avatarNameResolved(const LLUUID &id, const std::string
sessionState::for_each(boost::bind(predAvatarNameResolution, _1, id, name));
}
-// Leftover from vivox PTSN
-std::string LLWebRTCVoiceClient::sipURIFromID(const LLUUID& id) const
-{
- return id.asString();
-}
-
LLSD LLWebRTCVoiceClient::getP2PChannelInfoTemplate(const LLUUID& id) const
{
return LLSD();
@@ -2496,17 +2587,18 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection)
// callback from llwebrtc
void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
{
+ connectionPtr_t connection = shared_from_this();
LL::WorkQueue::postMaybe(mMainQueue,
- [=, this] {
- if (mShutDown)
+ [=] {
+ if (connection->mShutDown)
{
return;
}
LL_DEBUGS("Voice") << "On Offer Available." << LL_ENDL;
- mChannelSDP = sdp;
- if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START)
+ connection->mChannelSDP = sdp;
+ if (connection->mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START)
{
- mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION;
+ connection->mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION;
}
});
}
@@ -2523,16 +2615,17 @@ void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
// callback from llwebrtc
void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface)
{
+ connectionPtr_t connection = shared_from_this();
LL::WorkQueue::postMaybe(mMainQueue,
- [=, this] {
- if (mShutDown)
+ [=] {
+ if (connection->mShutDown)
{
return;
}
LL_DEBUGS("Voice") << "On AudioEstablished." << LL_ENDL;
- mWebRTCAudioInterface = audio_interface;
- mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up.
- setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED);
+ connection->mWebRTCAudioInterface = audio_interface;
+ connection->mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up.
+ connection->setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED);
});
}
@@ -2623,6 +2716,10 @@ void LLVoiceWebRTCConnection::sendData(const std::string &data)
}
}
+const std::string& LLVoiceWebRTCConnection::getVersion() {
+ return mServerVersion;
+}
+
// Tell the simulator that we're shutting down a voice connection.
// The simulator will pass this on to the Secondlife WebRTC server.
void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connection)
@@ -2902,6 +2999,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
}
mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume);
LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID);
+ resetConnectionStats();
setVoiceConnectionState(VOICE_STATE_WAIT_FOR_DATA_CHANNEL);
break;
}
@@ -2955,6 +3053,13 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
sendJoin();
}
}
+
+ static LLTimer stats_timer;
+ if (stats_timer.getElapsedTimeF32() > STATS_TIMER_DELAY)
+ {
+ mWebRTCPeerConnectionInterface->gatherConnectionStats();
+ stats_timer.reset();
+ }
}
break;
}
@@ -3046,6 +3151,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
// An object where each key is an agent id. (in the future, we may allow
// integer indices into an agentid list, populated on join commands. For size.
// Each key will point to a json object with keys identifying what's updated.
+// 'V' - voice server version (string)
// 'p' - audio source power (level/volume) (int8 as int)
// 'j' - object of join data (currently only a boolean 'p' marking a primary participant)
// 'l' - boolean, always true if exists.
@@ -3086,6 +3192,13 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
LL_WARNS("Voice") << "Expected object from data channel:" << data << LL_ENDL;
return;
}
+
+ bool is_primary_region = mPrimary;
+ if (!mPrimary && isSpatial() && gAgent.getRegion())
+ {
+ is_primary_region = (mRegionID == gAgent.getRegion()->getRegionID());
+ LL_WARNS() << "mPrimary is false, expected: " << is_primary_region << " connection state: " << getVoiceConnectionState() << LL_ENDL;
+ }
boost::json::object voice_data = voice_data_parsed.as_object();
boost::json::object mute;
boost::json::object user_gain;
@@ -3106,6 +3219,16 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
boost::json::object participant_obj = participant_elem.value().as_object();
+ if (participant_obj.contains("V") && participant_obj["V"].is_string() && agent_id == gAgentID)
+ {
+ // sendJoin was called on the connection. The voice server has responded with the new version string. Set it here.
+ mServerVersion = participant_obj["V"].as_string().c_str();
+ LLWebRTCVoiceClient::getInstance()->updateVersion();
+ LL_DEBUGS("Voice") << "Received version string \"" << participant_obj["V"].as_string().c_str()
+ << "\" for connection: primary=" << mPrimary << ", spatial=" << isSpatial()
+ << ", region=" << mRegionID << ", mChannelID=" << mChannelID << LL_ENDL;
+ }
+
LLWebRTCVoiceClient::participantStatePtr_t participant =
LLWebRTCVoiceClient::getInstance()->findParticipantByID(mChannelID, agent_id);
bool joined = false;
@@ -3171,12 +3294,63 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
if (participant_obj.contains("m") && participant_obj["m"].is_bool())
{
- participant->mIsModeratorMuted = participant_obj["m"].as_bool();
+ bool is_moderator_muted = participant_obj["m"].as_bool();
+ if (isSpatial())
+ {
+ // ignore muted flags from non-primary server
+ if (is_primary_region || primary)
+ {
+ participant->mIsModeratorMuted = is_moderator_muted;
+ if (gAgentID == agent_id)
+ {
+ LLNearbyVoiceModeration::getInstance()->setMutedInfo(mChannelID, is_moderator_muted);
+ }
+ }
+ }
+ else
+ {
+ participant->mIsModeratorMuted = is_moderator_muted;
+ }
}
}
}
- }
+ else
+ {
+ if (isSpatial() && (is_primary_region || primary))
+ {
+ // mute info message can be received before join message, so try to mute again later
+ if (participant_obj.contains("m") && participant_obj["m"].is_bool())
+ {
+ LL_WARNS() << "Mute info msg received: " << participant_obj["m"].as_bool()
+ << " but participant " << agent_id
+ << " was not found in channel " << mChannelID << LL_ENDL;
+ bool is_moderator_muted = participant_obj["m"].as_bool();
+ std::string channel_id = mChannelID;
+ F32 delay { 1.5f };
+ doAfterInterval(
+ [channel_id, agent_id, is_moderator_muted]()
+ {
+ LLWebRTCVoiceClient::participantStatePtr_t participant =
+ LLWebRTCVoiceClient::getInstance()->findParticipantByID(channel_id, agent_id);
+ if (participant)
+ {
+ participant->mIsModeratorMuted = is_moderator_muted;
+ LL_WARNS() << "Participant " << agent_id << " is found after delay, is_muted: " << is_moderator_muted << LL_ENDL;
+ if (gAgentID == agent_id)
+ {
+ LLNearbyVoiceModeration::getInstance()->setMutedInfo(channel_id, is_moderator_muted);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Participant " << agent_id << " is still not found in channel " << channel_id << LL_ENDL;
+ }
+ }, delay);
+ }
+ }
+ }
+ }
// tell the simulator to set the mute and volume data for this
// participant, if there are any updates.
boost::json::object root;
@@ -3207,17 +3381,18 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
// llwebrtc callback
void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface)
{
+ connectionPtr_t connection = shared_from_this();
LL::WorkQueue::postMaybe(mMainQueue,
- [=, this] {
- if (mShutDown)
+ [=] {
+ if (connection->mShutDown)
{
return;
}
if (data_interface)
{
- mWebRTCDataInterface = data_interface;
- mWebRTCDataInterface->setDataObserver(this);
+ connection->mWebRTCDataInterface = data_interface;
+ connection->mWebRTCDataInterface->setDataObserver(connection.get());
}
});
}
@@ -3247,6 +3422,114 @@ void LLVoiceWebRTCConnection::sendJoin()
mWebRTCDataInterface->sendData(json_data, false);
}
+void LLVoiceWebRTCConnection::OnStatsDelivered(const llwebrtc::LLWebRTCStatsMap& stats_data)
+{
+ LL::WorkQueue::postMaybe(mMainQueue, [=, this]
+ {
+ if (mShutDown)
+ {
+ return;
+ }
+ for (const auto& [stats_id, attributes] : stats_data)
+ {
+ if (attributes.contains("currentRoundTripTime"))
+ {
+ F32 rtt_seconds = 0.0f;
+ LLStringUtil::convertToF32(attributes.at("currentRoundTripTime"), rtt_seconds);
+ sample(LLStatViewer::WEBRTC_LATENCY, rtt_seconds * 1000.0f);
+ }
+ if (attributes.contains("availableOutgoingBitrate"))
+ {
+ F32 bitrate_bps = 0.0f;
+ LLStringUtil::convertToF32(attributes.at("availableOutgoingBitrate"), bitrate_bps);
+ sample(LLStatViewer::WEBRTC_UPLOAD_BANDWIDTH, bitrate_bps / 1000.0f);
+ }
+
+ // Stat type detection below is heuristic-based.
+ // It's relied on specific fields to distinguish outbound-rtp, remote-inbound-rtp, and inbound-rtp.
+ // This approach works with current WebRTC stats but may need updating later.
+
+ // Outbound RTP
+ if (attributes.contains("mediaSourceId"))
+ {
+ U32 out_packets_sent = 0;
+ LLStringUtil::convertToU32(attributes.at("packetsSent"), out_packets_sent);
+ sample(LLStatViewer::WEBRTC_PACKETS_OUT_SENT, out_packets_sent);
+ }
+ // Remote-Inbound RTP
+ else if (attributes.contains("localId"))
+ {
+ if (attributes.contains("packetsLost"))
+ {
+ // packetsLost may be negative, clamp to zero for unsigned Viewer stats
+ S32 out_packets_lost = 0;
+ LLStringUtil::convertToS32(attributes.at("packetsLost"), out_packets_lost);
+ sample(LLStatViewer::WEBRTC_PACKETS_OUT_LOST, static_cast<U32>(llmax(out_packets_lost, 0)));
+ }
+ if (attributes.contains("jitter"))
+ {
+ F32 jitter_seconds = 0.0f;
+ LLStringUtil::convertToF32(attributes.at("jitter"), jitter_seconds);
+ sample(LLStatViewer::WEBRTC_JITTER_OUT, jitter_seconds * 1000.0f);
+ }
+ }
+ // Inbound RTP
+ else if (attributes.contains("jitterBufferDelay"))
+ {
+ if (attributes.contains("packetsLost"))
+ {
+ // packetsLost may be negative, clamp to zero for unsigned Viewer stats
+ S32 in_packets_lost = 0;
+ LLStringUtil::convertToS32(attributes.at("packetsLost"), in_packets_lost);
+ sample(LLStatViewer::WEBRTC_PACKETS_IN_LOST, static_cast<U32>(llmax(in_packets_lost, 0)));
+ }
+ if (attributes.contains("packetsReceived"))
+ {
+ U32 in_packets_recv = 0;
+ LLStringUtil::convertToU32(attributes.at("packetsReceived"), in_packets_recv);
+ sample(LLStatViewer::WEBRTC_PACKETS_IN_RECEIVED, in_packets_recv);
+ }
+ if (attributes.contains("jitter"))
+ {
+ F32 jitter_seconds = 0.0f;
+ LLStringUtil::convertToF32(attributes.at("jitter"), jitter_seconds);
+ sample(LLStatViewer::WEBRTC_JITTER_IN, jitter_seconds * 1000.0f);
+ }
+ if (attributes.contains("jitterBufferDelay") && attributes.contains("jitterBufferEmittedCount"))
+ {
+ F32 total_delay_seconds = 0.0f;
+ F32 emitted_count_f = 0.0f;
+
+ // total delay in seconds
+ LLStringUtil::convertToF32(attributes.at("jitterBufferDelay"), total_delay_seconds);
+
+ // number of packets played out
+ LLStringUtil::convertToF32(attributes.at("jitterBufferEmittedCount"), emitted_count_f);
+ if (emitted_count_f > 0.0f)
+ {
+ F32 avg_delay_seconds = total_delay_seconds / emitted_count_f;
+ F32 avg_delay_ms = avg_delay_seconds * 1000.0f;
+ sample(LLStatViewer::WEBRTC_JITTER_BUFFER, avg_delay_seconds * 1000.0f);
+ }
+ }
+ }
+ }
+ });
+}
+
+void LLVoiceWebRTCConnection::resetConnectionStats()
+{
+ sample(LLStatViewer::WEBRTC_JITTER_BUFFER, 0);
+ sample(LLStatViewer::WEBRTC_JITTER_IN, 0);
+ sample(LLStatViewer::WEBRTC_JITTER_OUT, 0);
+ sample(LLStatViewer::WEBRTC_LATENCY, 0);
+ sample(LLStatViewer::WEBRTC_PACKETS_IN_LOST, 0);
+ sample(LLStatViewer::WEBRTC_PACKETS_IN_RECEIVED, 0);
+ sample(LLStatViewer::WEBRTC_PACKETS_OUT_SENT, 0);
+ sample(LLStatViewer::WEBRTC_PACKETS_OUT_LOST, 0);
+ sample(LLStatViewer::WEBRTC_UPLOAD_BANDWIDTH, 0);
+}
+
/////////////////////////////
// WebRTC Spatial Connection
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index 0c658803db..a3f3ebe8b0 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -80,13 +80,13 @@ public:
static bool isShuttingDown() { return sShuttingDown; }
const LLVoiceVersionInfo& getVersion() override;
+ void updateVersion();
void updateSettings() override; // call after loading settings and whenever they change
// Returns true if WebRTC has successfully logged in and is not in error state
bool isVoiceWorking() const override;
- std::string sipURIFromID(const LLUUID &id) const override;
LLSD getP2PChannelInfoTemplate(const LLUUID& id) const override;
void setHidden(bool hidden) override; // virtual
@@ -285,6 +285,7 @@ public:
void shutdownAllConnections();
void revive();
+ const std::string getVersion() const;
static void processSessionStates();
@@ -540,6 +541,8 @@ private:
static bool sShuttingDown;
LLEventMailDrop mWebRTCPump;
+
+ LLSD mLastWebRTCStats;
};
@@ -603,12 +606,15 @@ class LLVoiceWebRTCConnection :
//@{
void OnDataReceived(const std::string &data, bool binary) override;
void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override;
+
+ void OnStatsDelivered(const llwebrtc::LLWebRTCStatsMap& stats_data) override;
//@}
void OnDataReceivedImpl(const std::string &data, bool binary);
void sendJoin();
void sendData(const std::string &data);
+ const std::string& getVersion();
void processIceUpdates();
@@ -623,6 +629,7 @@ class LLVoiceWebRTCConnection :
bool connectionStateMachine();
virtual bool isSpatial() { return false; }
+ bool isPrimary() const { return mPrimary; }
LLUUID getRegionID() { return mRegionID; }
@@ -638,6 +645,8 @@ class LLVoiceWebRTCConnection :
void OnVoiceConnectionRequestSuccess(const LLSD &body);
+ void resetConnectionStats();
+
protected:
typedef enum e_voice_connection_state
{
@@ -694,6 +703,7 @@ class LLVoiceWebRTCConnection :
bool mPrimary;
LLUUID mViewerSession;
std::string mChannelID;
+ std::string mServerVersion;
std::string mChannelSDP;
std::string mRemoteChannelSDP;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 4c316fce07..16c262d1ad 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -250,10 +250,12 @@ LLVOVolume::~LLVOVolume()
delete mVolumeImpl;
mVolumeImpl = NULL;
- gMeshRepo.unregisterMesh(this);
+ unregisterOldMeshAndSkin();
if(!mMediaImplList.empty())
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("delete volume media list");
+
for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
{
if(mMediaImplList[i].notNull())
@@ -351,7 +353,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
U8 sculpt_type = 0;
if (isSculpted())
{
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = getSculptParams();
if (sculpt_params)
{
sculpt_id = sculpt_params->getSculptTexture();
@@ -924,7 +926,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
if (getLightTextureID().notNull())
{
- LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ LLLightImageParams* params = getLightImageParams();
LLUUID id = params->getLightTexture();
mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE);
if (mLightTexture.notNull())
@@ -1048,6 +1050,28 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
+// Inverse of gMeshRepo.loadMesh and gMeshRepo.getSkinInfo, combined into one function
+// Assume a Collada mesh never changes after being set.
+void LLVOVolume::unregisterOldMeshAndSkin()
+{
+ if (mVolumep)
+ {
+ const LLVolumeParams& params = mVolumep->getParams();
+ if ((params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
+ {
+ // object is being deleted, so it will no longer need to request
+ // meshes.
+ for (S32 lod = 0; lod != LLVolumeLODGroup::NUM_LODS; ++lod)
+ {
+ gMeshRepo.unregisterMesh(this, params, lod);
+ }
+ // This volume may or may not have a skin
+ gMeshRepo.unregisterSkinInfo(params.getSculptID(), this);
+ }
+ }
+}
+
+
bool LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bool unique_volume)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
@@ -1082,7 +1106,7 @@ bool LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, true, false);
if (!mVolumeImpl)
{
- LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
+ LLFlexibleObjectData* data = getFlexibleObjectData();
mVolumeImpl = new LLVolumeImplFlexible(this, data);
}
}
@@ -1193,7 +1217,7 @@ void LLVOVolume::updateSculptTexture()
if (isSculpted() && !isMesh())
{
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams *sculpt_params = getSculptParams();
if (sculpt_params)
{
LLUUID id = sculpt_params->getSculptTexture();
@@ -1229,7 +1253,35 @@ void LLVOVolume::updateSculptTexture()
void LLVOVolume::updateVisualComplexity()
{
- LLVOAvatar* avatar = getAvatarAncestor();
+ LLVOAvatar* avatar = nullptr;
+ LLViewerObject* pobj = (LLViewerObject*)getParent();
+ LLViewerObject* lobj = this;
+ while (pobj)
+ {
+ avatar = pobj->asAvatar();
+ if (avatar)
+ {
+ break;
+ }
+ lobj = pobj;
+ pobj = (LLViewerObject*)pobj->getParent();
+ }
+
+ if (avatar)
+ {
+ // mark parent as dirty, complexity will be updated recursively.
+ avatar->markAttachmentComplexityDirty(lobj->getID());
+ }
+ LLVOAvatar* rigged_avatar = getAvatar();
+ if (rigged_avatar && (rigged_avatar != avatar))
+ {
+ // This might be wrong. Control avatars update each run,
+ // due to lack of dirty mechanics, and this might be
+ // where we should implement and call
+ // markControlAvatarComplexityDirty() if !isAttachment().
+ rigged_avatar->markAttachmentComplexityDirty(lobj->getID());
+ }
+ /*LLVOAvatar* avatar = getAvatarAncestor();
if (avatar)
{
avatar->updateVisualComplexity();
@@ -1238,7 +1290,7 @@ void LLVOVolume::updateVisualComplexity()
if(rigged_avatar && (rigged_avatar != avatar))
{
rigged_avatar->updateVisualComplexity();
- }
+ }*/
}
void LLVOVolume::notifyMeshLoaded()
@@ -3053,7 +3105,7 @@ void LLVOVolume::setLightTextureID(LLUUID id)
{
old_texturep->removeVolume(LLRender::LIGHT_TEX, this);
}
- LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ LLLightImageParams* param_block = getLightImageParams();
if (param_block && param_block->getLightTexture() != id)
{
param_block->setLightTexture(id);
@@ -3083,7 +3135,7 @@ void LLVOVolume::setLightTextureID(LLUUID id)
void LLVOVolume::setSpotLightParams(LLVector3 params)
{
- LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ LLLightImageParams* param_block = getLightImageParams();
if (param_block && param_block->getParams() != params)
{
param_block->setParams(params);
@@ -3125,7 +3177,7 @@ void LLVOVolume::setLightSRGBColor(const LLColor3& color)
void LLVOVolume::setLightLinearColor(const LLColor3& color)
{
- LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ LLLightParams *param_block = getLightParams();
if (param_block)
{
if (param_block->getLinearColor() != color)
@@ -3140,7 +3192,7 @@ void LLVOVolume::setLightLinearColor(const LLColor3& color)
void LLVOVolume::setLightIntensity(F32 intensity)
{
- LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ LLLightParams *param_block = getLightParams();
if (param_block)
{
if (param_block->getLinearColor().mV[3] != intensity)
@@ -3153,7 +3205,7 @@ void LLVOVolume::setLightIntensity(F32 intensity)
void LLVOVolume::setLightRadius(F32 radius)
{
- LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ LLLightParams *param_block = getLightParams();
if (param_block)
{
if (param_block->getRadius() != radius)
@@ -3166,7 +3218,7 @@ void LLVOVolume::setLightRadius(F32 radius)
void LLVOVolume::setLightFalloff(F32 falloff)
{
- LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ LLLightParams *param_block = getLightParams();
if (param_block)
{
if (param_block->getFalloff() != falloff)
@@ -3179,7 +3231,7 @@ void LLVOVolume::setLightFalloff(F32 falloff)
void LLVOVolume::setLightCutoff(F32 cutoff)
{
- LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ LLLightParams *param_block = getLightParams();
if (param_block)
{
if (param_block->getCutoff() != cutoff)
@@ -3194,7 +3246,7 @@ void LLVOVolume::setLightCutoff(F32 cutoff)
bool LLVOVolume::getIsLight() const
{
- mIsLight = getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT);
+ mIsLight = getLightParams() != nullptr;
return mIsLight;
}
@@ -3210,7 +3262,7 @@ LLColor3 LLVOVolume::getLightSRGBBaseColor() const
LLColor3 LLVOVolume::getLightLinearBaseColor() const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return LLColor3(param_block->getLinearColor());
@@ -3223,7 +3275,7 @@ LLColor3 LLVOVolume::getLightLinearBaseColor() const
LLColor3 LLVOVolume::getLightLinearColor() const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return LLColor3(param_block->getLinearColor()) * param_block->getLinearColor().mV[3];
@@ -3241,33 +3293,27 @@ LLColor3 LLVOVolume::getLightSRGBColor() const
return ret;
}
-LLUUID LLVOVolume::getLightTextureID() const
+const LLUUID& LLVOVolume::getLightTextureID() const
{
- if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ const LLLightImageParams *param_block = getLightImageParams();
+ if (param_block)
{
- const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
- if (param_block)
- {
- return param_block->getLightTexture();
- }
+ return param_block->getLightTexture();
}
return LLUUID::null;
}
-LLVector3 LLVOVolume::getSpotLightParams() const
+const LLVector3& LLVOVolume::getSpotLightParams() const
{
- if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ const LLLightImageParams *param_block = getLightImageParams();
+ if (param_block)
{
- const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
- if (param_block)
- {
- return param_block->getParams();
- }
+ return param_block->getParams();
}
- return LLVector3();
+ return LLVector3::zero;
}
F32 LLVOVolume::getSpotLightPriority() const
@@ -3304,8 +3350,8 @@ void LLVOVolume::updateSpotLightPriority()
bool LLVOVolume::isLightSpotlight() const
{
- LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
- if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ const LLLightImageParams* params = getLightImageParams();
+ if (params)
{
return params->isLightSpotlight();
}
@@ -3315,7 +3361,7 @@ bool LLVOVolume::isLightSpotlight() const
LLViewerTexture* LLVOVolume::getLightTexture()
{
- LLUUID id = getLightTextureID();
+ const LLUUID& id = getLightTextureID();
if (id.notNull())
{
@@ -3326,7 +3372,7 @@ LLViewerTexture* LLVOVolume::getLightTexture()
}
else
{
- mLightTexture = NULL;
+ mLightTexture = nullptr;
}
return mLightTexture;
@@ -3334,7 +3380,7 @@ LLViewerTexture* LLVOVolume::getLightTexture()
F32 LLVOVolume::getLightIntensity() const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return param_block->getLinearColor().mV[3];
@@ -3347,7 +3393,7 @@ F32 LLVOVolume::getLightIntensity() const
F32 LLVOVolume::getLightRadius() const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return param_block->getRadius();
@@ -3360,7 +3406,7 @@ F32 LLVOVolume::getLightRadius() const
F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return param_block->getFalloff() * fudge_factor;
@@ -3373,7 +3419,7 @@ F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const
F32 LLVOVolume::getLightCutoff() const
{
- const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+ const LLLightParams *param_block = getLightParams();
if (param_block)
{
return param_block->getCutoff();
@@ -3386,7 +3432,7 @@ F32 LLVOVolume::getLightCutoff() const
bool LLVOVolume::isReflectionProbe() const
{
- return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ return getReflectionProbeParams() != nullptr;
}
bool LLVOVolume::setIsReflectionProbe(bool is_probe)
@@ -3411,7 +3457,7 @@ bool LLVOVolume::setIsReflectionProbe(bool is_probe)
bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
{
- LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
if (param_block->getAmbiance() != ambiance)
@@ -3427,7 +3473,7 @@ bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
{
- LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
if (param_block->getClipDistance() != near_clip)
@@ -3443,7 +3489,7 @@ bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
bool LLVOVolume::setReflectionProbeIsBox(bool is_box)
{
- LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
if (param_block->getIsBox() != is_box)
@@ -3459,7 +3505,7 @@ bool LLVOVolume::setReflectionProbeIsBox(bool is_box)
bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
{
- LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
if (param_block->getIsDynamic() != is_dynamic)
@@ -3475,7 +3521,7 @@ bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror)
{
- LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
if (param_block->getIsMirror() != is_mirror)
@@ -3498,7 +3544,7 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror)
F32 LLVOVolume::getReflectionProbeAmbiance() const
{
- const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ const LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
return param_block->getAmbiance();
@@ -3511,7 +3557,7 @@ F32 LLVOVolume::getReflectionProbeAmbiance() const
F32 LLVOVolume::getReflectionProbeNearClip() const
{
- const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ const LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
return param_block->getClipDistance();
@@ -3524,7 +3570,7 @@ F32 LLVOVolume::getReflectionProbeNearClip() const
bool LLVOVolume::getReflectionProbeIsBox() const
{
- const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ const LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
return param_block->getIsBox();
@@ -3535,7 +3581,7 @@ bool LLVOVolume::getReflectionProbeIsBox() const
bool LLVOVolume::getReflectionProbeIsDynamic() const
{
- const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ const LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
return param_block->getIsDynamic();
@@ -3546,8 +3592,7 @@ bool LLVOVolume::getReflectionProbeIsDynamic() const
bool LLVOVolume::getReflectionProbeIsMirror() const
{
- const LLReflectionProbeParams *param_block =
- (const LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ const LLReflectionProbeParams* param_block = getReflectionProbeParams();
if (param_block)
{
return param_block->getIsMirror();
@@ -3568,7 +3613,7 @@ U32 LLVOVolume::getVolumeInterfaceID() const
bool LLVOVolume::isFlexible() const
{
- if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE))
+ if (getFlexibleObjectData())
{
LLVolume* volume = getVolume();
if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE)
@@ -3587,7 +3632,7 @@ bool LLVOVolume::isFlexible() const
bool LLVOVolume::isSculpted() const
{
- if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
+ if (getSculptParams())
{
return true;
}
@@ -3599,7 +3644,7 @@ bool LLVOVolume::isMesh() const
{
if (isSculpted())
{
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ const LLSculptParams *sculpt_params = getSculptParams();
if (sculpt_params)
{
U8 sculpt_type = sculpt_params->getSculptType();
@@ -3617,7 +3662,7 @@ bool LLVOVolume::isMesh() const
bool LLVOVolume::hasLightTexture() const
{
- if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ if (getLightImageParams())
{
return true;
}
@@ -3737,8 +3782,7 @@ bool LLVOVolume::isRiggedMesh() const
//----------------------------------------------------------------------------
U32 LLVOVolume::getExtendedMeshFlags() const
{
- const LLExtendedMeshParams *param_block =
- (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH);
+ const LLExtendedMeshParams *param_block = getExtendedMeshParams();
if (param_block)
{
return param_block->getFlags();
@@ -3783,8 +3827,7 @@ void LLVOVolume::setExtendedMeshFlags(U32 flags)
{
bool in_use = true;
setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true);
- LLExtendedMeshParams *param_block =
- (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH);
+ LLExtendedMeshParams *param_block = (LLExtendedMeshParams *)getExtendedMeshParams();
if (param_block)
{
param_block->setFlags(flags);
@@ -3842,11 +3885,12 @@ void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_pare
}
if (old_volp && old_volp->isAnimatedObject())
{
- if (old_volp->getControlAvatar())
+ LLControlAvatar* cav = old_volp->getControlAvatar();
+ if (cav)
{
// We have been removed from an animated object, need to do cleanup.
- old_volp->getControlAvatar()->updateAttachmentOverrides();
- old_volp->getControlAvatar()->updateAnimations();
+ cav->updateAttachmentOverrides();
+ cav->updateAnimations();
}
}
}
@@ -5131,7 +5175,7 @@ U32 LLVOVolume::getPartitionType() const
{
return LLViewerRegion::PARTITION_HUD;
}
- if (isAnimatedObject() && getControlAvatar())
+ if (isAnimatedObjectFast() && getControlAvatar())
{
return LLViewerRegion::PARTITION_CONTROL_AV;
}
@@ -5757,11 +5801,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
// Standard rigged mesh attachments:
- bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment();
+ bool is_animated = vobj->isAnimatedObject();
+ bool rigged = !is_animated && skinInfo && vobj->isAttachment();
// Animated objects. Have to check for isRiggedMesh() to
// exclude static objects in animated object linksets.
- rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() &&
- vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying);
+ if (!rigged && is_animated && vobj->isRiggedMesh())
+ {
+ LLControlAvatar* cav = vobj->getControlAvatar();
+ if (cav)
+ {
+ rigged = cav->mPlaying;
+ }
+ }
bool any_rigged_face = false;
@@ -5959,7 +6010,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
bool should_render = true;
if (gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND)
{
- if (gltf_mat->mBaseColor.mV[3] == 0.0f)
+ if (gltf_mat->mBaseColor.mV[3] == 0.0f && !LLDrawPoolAlpha::sShowDebugAlpha)
{
should_render = false;
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 97a5131260..b6044bc319 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -227,6 +227,7 @@ public:
void setTexture(const S32 face);
S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];}
+ void unregisterOldMeshAndSkin();
/*virtual*/ bool setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override;
void updateSculptTexture();
void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;}
@@ -283,9 +284,9 @@ public:
// Get the light color in sRGB color space scaled by intensity.
LLColor3 getLightSRGBColor() const;
- LLUUID getLightTextureID() const;
+ const LLUUID& getLightTextureID() const;
bool isLightSpotlight() const;
- LLVector3 getSpotLightParams() const;
+ const LLVector3& getSpotLightParams() const;
void updateSpotLightPriority();
F32 getSpotLightPriority() const;
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index cc593fe7b4..f639024228 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -82,7 +82,7 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item");
LLPanelWearableOutfitItem::Params::Params()
: add_btn("add_btn"),
@@ -222,7 +222,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(&typeid(LLPanelClothingListItem::Params), "clothing_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(typeid(LLPanelClothingListItem::Params), "clothing_list_item");
LLPanelClothingListItem::Params::Params()
@@ -309,7 +309,7 @@ bool LLPanelClothingListItem::postBuild()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(&typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item");
LLPanelBodyPartsListItem::Params::Params()
@@ -380,7 +380,7 @@ bool LLPanelBodyPartsListItem::postBuild()
return true;
}
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(&typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item");
LLPanelDeletableWearableListItem::Params::Params()
: delete_btn("delete_btn")
@@ -467,7 +467,7 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name,
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(&typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item");
LLPanelDummyClothingListItem::Params::Params()
: add_panel("add_panel"),
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index a319aa00bc..f603274335 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -34,6 +34,7 @@
#include "llagent.h"
#include "llappviewer.h"
+#include "llfloatermarketplace.h"
#include "llfloaterwebcontent.h"
#include "llfloaterreg.h"
#include "lllogininstance.h"
@@ -74,12 +75,20 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
}
// static
-// Explicitly open a Web URL using the Web content floater
+// Explicitly open a Web URL using the Web content floater or Marketplace floater
void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode)
{
LLFloaterWebContent::Params p;
p.url(url).target(target).id(uuid).dev_mode(dev_mode);
- LLFloaterReg::showInstance("web_content", p);
+
+ if (LLFloaterMarketplace::isMarketplaceURL(url))
+ {
+ LLFloaterReg::showInstance("marketplace", p);
+ }
+ else
+ {
+ LLFloaterReg::showInstance("web_content", p);
+ }
}
// static
diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp
index 6d234a9a34..38e49d0750 100644
--- a/indra/newview/llwindowlistener.cpp
+++ b/indra/newview/llwindowlistener.cpp
@@ -41,6 +41,8 @@
#include "llrootview.h"
#include "llsdutil.h"
#include "stringize.h"
+#include "llclipboard.h"
+#include "lleditmenuhandler.h"
#include <functional>
#include <typeinfo>
#include <map>
@@ -89,7 +91,8 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter&
&LLWindowListener::getPaths,
LLSDMap("reply", LLSD()));
add("keyDown",
- keySomething + "keypress event.\n" + keyExplain + mask,
+ keySomething + "keypress event.\n" + keyExplain +
+ "The [\"char\"] parameter detects and handles non-ASCII characters seperately\n" + mask,
&LLWindowListener::keyDown);
add("keyUp",
keySomething + "key release event.\n" + keyExplain + mask,
@@ -107,6 +110,10 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter&
"Given an integer number of [\"clicks\"], inject the requested mouse scroll event.\n"
"(positive clicks moves downward through typical content)",
&LLWindowListener::mouseScroll);
+ add("pasteText",
+ "Paste specified [\"text\"] into the current edit field\n"
+ "Optional [\"path\"] specifies target UI element (must be focusable).",
+ &LLWindowListener::pasteText);
}
template <typename MAPPED>
@@ -264,6 +271,20 @@ void LLWindowListener::keyDown(LLSD const & evt)
KEY key = getKEY(evt);
MASK mask = getMask(evt);
+ bool is_non_ascii = false;
+ llwchar uni_char = 0;
+
+ if (evt.has("char"))
+ {
+ LLWString wstr = utf8str_to_wstring(evt["char"].asString());
+ if (!wstr.empty())
+ {
+ uni_char = wstr[0];
+ // If the Unicode code point is outside ASCII range, use Unicode-only handling
+ is_non_ascii = (uni_char >= 0x80);
+ }
+ }
+
if (evt.has("path"))
{
std::string path(evt["path"]);
@@ -278,8 +299,17 @@ void LLWindowListener::keyDown(LLSD const & evt)
response.setResponse(target_view->getInfo());
gFocusMgr.setKeyboardFocus(target_view);
- gViewerInput.handleKey(key, mask, false);
- if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
+
+ if (is_non_ascii)
+ {
+ // For non-ASCII characters, only send the Unicode event
+ mWindow->handleUnicodeChar(uni_char, mask);
+ }
+ else
+ {
+ gViewerInput.handleKey(key, mask, false);
+ if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
+ }
}
else
{
@@ -290,8 +320,16 @@ void LLWindowListener::keyDown(LLSD const & evt)
}
else
{
- gViewerInput.handleKey(key, mask, false);
- if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
+ if (is_non_ascii)
+ {
+ // For non-ASCII characters, only send the Unicode event
+ mWindow->handleUnicodeChar(uni_char, mask);
+ }
+ else
+ {
+ gViewerInput.handleKey(key, mask, false);
+ if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
+ }
}
}
@@ -521,3 +559,60 @@ void LLWindowListener::mouseScroll(LLSD const & request)
mWindow->handleScrollWheel(NULL, clicks);
}
+
+void LLWindowListener::pasteText(LLSD const & evt)
+{
+ Response response(LLSD(), evt);
+
+ if (!evt.has("text"))
+ {
+ response.error(STRINGIZE(evt["op"].asString() << " request did not provide required \"text\" parameter"));
+ return;
+ }
+
+ std::string text_to_paste = evt["text"].asString();
+ if (evt.has("path"))
+ {
+ std::string path(evt["path"]);
+ LLView* target_view = LLUI::getInstance()->resolvePath(LLUI::getInstance()->getRootView(), path);
+ if (!target_view)
+ {
+ response.error(STRINGIZE(evt["op"].asString() << " request specified invalid \"path\": " << path));
+ return;
+ }
+ else if(!target_view->isAvailable())
+ {
+ response.error(STRINGIZE("Target view specified by \"path\": " << path << " is not visible"));
+ return;
+ }
+ else
+ {
+ // Focus the target view
+ gFocusMgr.setKeyboardFocus(target_view);
+ }
+ }
+
+ // Check if edit menu handler is available
+ if (!LLEditMenuHandler::gEditMenuHandler)
+ {
+ response.error(STRINGIZE(evt["op"].asString() << " request failed: no edit menu handler available"));
+ return;
+ }
+
+ // Save current clipboard contents
+ LLWString saved_clipboard;
+ LLClipboard::instance().pasteFromClipboard(saved_clipboard);
+
+ LLClipboard::instance().copyToClipboard(utf8str_to_wstring(text_to_paste), 0, static_cast<S32>(text_to_paste.size()));
+ LLEditMenuHandler::gEditMenuHandler->paste();
+
+ // Restore original clipboard contents if there were any
+ if (!saved_clipboard.empty())
+ {
+ LLClipboard::instance().copyToClipboard(saved_clipboard, 0, static_cast<S32>(saved_clipboard.size()));
+ }
+ else
+ {
+ LLClipboard::instance().reset();
+ }
+}
diff --git a/indra/newview/llwindowlistener.h b/indra/newview/llwindowlistener.h
index 9908a9c451..d3a16cfde9 100644
--- a/indra/newview/llwindowlistener.h
+++ b/indra/newview/llwindowlistener.h
@@ -47,6 +47,7 @@ public:
void mouseUp(LLSD const & evt);
void mouseMove(LLSD const & evt);
void mouseScroll(LLSD const & evt);
+ void pasteText(LLSD const & evt);
private:
LLViewerWindow * mWindow;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 47e1815bc2..d02694de7d 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1217,6 +1217,7 @@ void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
void process_region_handshake(LLMessageSystem* msg, void** user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
LLHost host = msg->getSender();
LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host);
if (!regionp)
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 153bee3aef..c7c8404eb9 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -118,6 +118,7 @@ LLVector3d LLSimInfo::getGlobalOrigin() const
{
return from_region_handle(mHandle);
}
+
LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const
{
LLVector3d sim_origin = from_region_handle(mHandle);
@@ -602,25 +603,103 @@ void LLWorldMap::dropImagePriorities()
// Load all regions in a given rectangle (in region grid coordinates, i.e. world / 256 meters)
void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1)
{
- // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates
- x0 = x0 / MAP_BLOCK_SIZE;
- x1 = x1 / MAP_BLOCK_SIZE;
- y0 = y0 / MAP_BLOCK_SIZE;
- y1 = y1 / MAP_BLOCK_SIZE;
+ constexpr S32 MAX_REQUEST_REGIONS = 64; // Server side enforced limit.
+ constexpr S32 REGIONS_PER_BLOCK = MAP_BLOCK_SIZE * MAP_BLOCK_SIZE; // 4 x 4 = 16 regions per block
+ constexpr S32 MAX_TOTAL_BLOCKS = MAX_REQUEST_REGIONS / REGIONS_PER_BLOCK; // 64 / 16 = 4 blocks total
+ constexpr S32 MAX_BLOCKS_PER_SIDE = MAX_TOTAL_BLOCKS; // Can have up to 4 blocks in one dimension (e.g., 4x1, 1x4, 2x2)
+
+ // Convert region coordinates to block coordinates
+ // We use fixed sized blocks for ease of storage and lookup,
+ // but the requests can be of variable size of up to
+ // MAX_REQUEST_REGIONS.
+ S32 block_x0 = x0 / MAP_BLOCK_SIZE;
+ S32 block_x1 = x1 / MAP_BLOCK_SIZE;
+ S32 block_y0 = y0 / MAP_BLOCK_SIZE;
+ S32 block_y1 = y1 / MAP_BLOCK_SIZE;
- // Load the region info those blocks
- for (S32 block_x = llmax(x0, 0); block_x <= llmin(x1, MAP_BLOCK_RES-1); ++block_x)
+ // Clamp to valid range
+ block_x0 = llmax(block_x0, 0);
+ block_x1 = llmin(block_x1, MAP_BLOCK_RES - 1);
+ block_y0 = llmax(block_y0, 0);
+ block_y1 = llmin(block_y1, MAP_BLOCK_RES - 1);
+
+ // Process blocks, grouping unloaded blocks into larger requests up to MAX_TOTAL_BLOCKS
+ for (S32 block_y = block_y0; block_y <= block_y1; )
{
- for (S32 block_y = llmax(y0, 0); block_y <= llmin(y1, MAP_BLOCK_RES-1); ++block_y)
+ for (S32 block_x = block_x0; block_x <= block_x1; )
{
S32 offset = block_x | (block_y * MAP_BLOCK_RES);
if (!mMapBlockLoaded[offset])
{
- //LL_INFOS("WorldMap") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL;
- LLWorldMapMessage::getInstance()->sendMapBlockRequest(block_x * MAP_BLOCK_SIZE, block_y * MAP_BLOCK_SIZE, (block_x * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1, (block_y * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1);
- mMapBlockLoaded[offset] = true;
+ // Find the maximum contiguous unloaded rectangle starting at this block
+ S32 request_width = 1;
+ S32 request_height = 1;
+
+ // Expand width (check horizontal contiguous unloaded blocks)
+ while (request_width < MAX_BLOCKS_PER_SIDE &&
+ (block_x + request_width) <= block_x1)
+ {
+ // request_height is 1, can add blocks one by one.
+ S32 check_offset = (block_x + request_width) | (block_y * MAP_BLOCK_RES);
+ if (mMapBlockLoaded[check_offset])
+ {
+ break;
+ }
+ ++request_width;
+ }
+
+ // Expand height (check vertical contiguous unloaded blocks)
+ while (request_height < MAX_BLOCKS_PER_SIDE &&
+ (block_y + request_height) <= block_y1 &&
+ (request_width * (request_height + 1) <= MAX_TOTAL_BLOCKS)) // Don't exceed 64 total regions
+ {
+ bool can_expand = true;
+ // Width can be >1, loop over blocks in the line
+ for (S32 x = 0; x < request_width; ++x)
+ {
+ S32 check_offset = (block_x + x) | ((block_y + request_height) * MAP_BLOCK_RES);
+ if (mMapBlockLoaded[check_offset])
+ {
+ can_expand = false;
+ break;
+ }
+ }
+ if (!can_expand) break;
+ ++request_height;
+ }
+
+ // Send request for the contiguous rectangle
+ S32 min_x = block_x * MAP_BLOCK_SIZE;
+ S32 min_y = block_y * MAP_BLOCK_SIZE;
+ S32 max_x = (block_x + request_width) * MAP_BLOCK_SIZE - 1;
+ S32 max_y = (block_y + request_height) * MAP_BLOCK_SIZE - 1;
+
+ LL_DEBUGS("WorldMap") << "Loading Block rectangle (" << block_x << "," << block_y
+ << ") to (" << (block_x + request_width - 1) << "," << (block_y + request_height - 1)
+ << ") [" << (request_width * request_height * MAP_BLOCK_SIZE * MAP_BLOCK_SIZE) << " regions]" << LL_ENDL;
+
+ LLWorldMapMessage::getInstance()->sendMapBlockRequest(min_x, min_y, max_x, max_y);
+
+ // Mark all blocks in the requested rectangle as loaded
+ for (S32 y = 0; y < request_height; ++y)
+ {
+ for (S32 x = 0; x < request_width; ++x)
+ {
+ S32 mark_offset = (block_x + x) | ((block_y + y) * MAP_BLOCK_RES);
+ mMapBlockLoaded[mark_offset] = true;
+ }
+ }
+
+ // Skip over the width of blocks we just requested
+ block_x += request_width;
+ }
+ else
+ {
+ // This block is already loaded, move to next
+ ++block_x;
}
}
+ ++block_y;
}
}
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index 68e7f3ee29..91bc699708 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -37,18 +37,6 @@
#include "llviewertexture.h"
#include "llgltexture.h"
-// map item types
-const U32 MAP_ITEM_TELEHUB = 0x01;
-const U32 MAP_ITEM_PG_EVENT = 0x02;
-const U32 MAP_ITEM_MATURE_EVENT = 0x03;
-//const U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW
-//const U32 MAP_ITEM_AGENT_COUNT = 0x05;
-const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06;
-const U32 MAP_ITEM_LAND_FOR_SALE = 0x07;
-const U32 MAP_ITEM_CLASSIFIED = 0x08;
-const U32 MAP_ITEM_ADULT_EVENT = 0x09;
-const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
-
// Description of objects like hubs, events, land for sale, people and more (TBD).
// Note: we don't store a "type" in there so we need to store instances of this class in
// well known objects (i.e. list of objects which type is "well known").
diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp
index a5433133ab..c039f9de3f 100644
--- a/indra/newview/llworldmapmessage.cpp
+++ b/indra/newview/llworldmapmessage.cpp
@@ -34,7 +34,6 @@
#include "llfloaterworldmap.h"
constexpr U32 LAYER_FLAG = 2;
-constexpr S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000;
//---------------------------------------------------------------------------
// World Map Message Handling
@@ -155,6 +154,7 @@ void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16
// public static
void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (gNonInteractive)
{
return;
@@ -249,6 +249,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
// public static
void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
//LL_INFOS("WorldMap") << LL_ENDL;
U32 type;
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 6b2bd3e6fb..8e7b86eb00 100755
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -517,26 +517,38 @@ void LLWorldMapView::draw()
// Draw the region name in the lower left corner
if (mMapScale >= DRAW_TEXT_THRESHOLD)
{
- std::string mesg;
+ static LLCachedControl<bool> print_coords(gSavedSettings, "MapShowGridCoords");
+ static LLFontGL* font = LLFontGL::getFontSansSerifSmallBold();
+
+ auto print = [&](std::string text, F32 x, F32 y, bool use_ellipses)
+ {
+ font->renderUTF8(text, 0,
+ (F32)llfloor(left + x), (F32)llfloor(bottom + y),
+ LLColor4::white,
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW,
+ S32_MAX, //max_chars
+ (S32)mMapScale, //max_pixels
+ NULL,
+ use_ellipses);
+ };
+
+ std::string grid_name = info->getName();
if (info->isDown())
{
- mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str());
+ grid_name += " (" + sStringsMap["offline"] + ")";
}
- else
+
+ if (print_coords)
{
- mesg = info->getName();
+ print(grid_name, 3, 14, true);
+ // Obtain and print the grid map coordinates
+ LLVector3d region_pos = info->getGlobalOrigin();
+ std::string grid_coords = llformat("[%.0f, %.0f]", region_pos[VX] / 256, region_pos[VY] / 256);
+ print(grid_coords, 3, 2, false);
}
- if (!mesg.empty())
+ else
{
- LLFontGL::getFontSansSerifSmallBold()->renderUTF8(
- mesg, 0,
- (F32)llfloor(left + 3), (F32)llfloor(bottom + 2),
- LLColor4::white,
- LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW,
- S32_MAX, //max_chars
- (S32)mMapScale, //max_pixels
- NULL,
- /*use_ellipses*/true);
+ print(grid_name, 3, 2, true);
}
}
}
@@ -1725,8 +1737,11 @@ void LLWorldMapView::updateVisibleBlocks()
const F32 half_height = F32(height) / 2.0f;
// Compute center into sim grid coordinates
- S32 world_center_x = S32((-mPanX / mMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
- S32 world_center_y = S32((-mPanY / mMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
+ // mPanX and mPanY values can be obsolete as they are used for
+ // animation and there is no point loading regions we will see
+ // so briefly, they won't have time to load. Use target directly.
+ S32 world_center_x = S32((-mTargetPanX / mMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
+ S32 world_center_y = S32((-mTargetPanY / mMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
// Compute the boundaries into sim grid coordinates
S32 world_left = world_center_x - S32(half_width / mMapScale) - 1;
diff --git a/indra/newview/net.megapahit.Viewer.metainfo.xml.in b/indra/newview/net.megapahit.Viewer.metainfo.xml.in
new file mode 100644
index 0000000000..deeaa9c140
--- /dev/null
+++ b/indra/newview/net.megapahit.Viewer.metainfo.xml.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop-application">
+ <id>net.megapahit.Viewer</id>
+ <launchable type="desktop-id">net.megapahit.Viewer.desktop</launchable>
+ <metadata_license>CC0-1.0</metadata_license>
+ <project_license>LGPL-2.1</project_license>
+ <name>Megapahit</name>
+ <developer id="net.megapahit">
+ <name>Megapahit</name>
+ </developer>
+ <summary>A fork of the Second Life viewer</summary>
+ <description>
+ <p>An entrance to virtual empires in only megabytes. A shelter for the metaverse refugees, especially those from less supported operating systems.</p>
+ </description>
+ <url type="homepage">https://megapahit.net/</url>
+ <url type="vcs-browser">https://megapahit.org</url>
+ <url type="bugtracker">https://megapahit.com</url>
+ <releases>
+ <release version="${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" date="${TODAY_DATE}" />
+ </releases>
+</component>
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a844e29cbb..f4c121c18b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -623,7 +623,9 @@ void LLPipeline::init()
{
cntrl_ptr->getCommitSignal()->connect([](LLControlVariable* control, const LLSD& value, const LLSD& previous)
{
- LLFontVertexBuffer::enableBufferCollection(control->getValue().asBoolean());
+ bool enable_buffers = control->getValue().asBoolean();
+ LLFontVertexBuffer::enableBufferCollection(enable_buffers);
+ LLFontWidthBuffer::enableBufferCollection(enable_buffers);
});
}
}
@@ -1205,7 +1207,9 @@ void LLPipeline::refreshCachedSettings()
LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors);
}
- LLFontVertexBuffer::enableBufferCollection(gSavedSettings.getBOOL("CollectFontVertexBuffers"));
+ bool enable_buffers = gSavedSettings.getBOOL("CollectFontVertexBuffers");
+ LLFontVertexBuffer::enableBufferCollection(enable_buffers);
+ LLFontWidthBuffer::enableBufferCollection(enable_buffers);
}
void LLPipeline::releaseGLBuffers()
@@ -2811,6 +2815,10 @@ void LLPipeline::clearRebuildGroups()
{
LLSpatialGroup* group = *iter;
+ if (!group || group->isDead())
+ {
+ continue;
+ }
// If the group contains HUD objects, save the group
if (group->isHUDGroup())
{
@@ -5693,7 +5701,7 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_
if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
{
// moving lights get a little higher priority (too much causes artifacts)
- dist = llmax(dist - light->getLightRadius()*0.25f, 0.f);
+ dist = llmax(dist - radius * 0.25f, 0.f);
}
return dist;
}
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 4437adcf1b..a3015d004a 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -93,6 +93,7 @@ namespace Rlv
Version = 0,
VersionNew,
VersionNum,
+ RedirChat,
GetSitID,
Sit,
SitGround,
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 2cc06b3bbc..53df717af7 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -29,6 +29,7 @@
#include "llagent.h"
#include "llstartup.h"
#include "llappearancemgr.h"
+#include "llfloaterimnearbychat.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llmoveview.h"
@@ -393,6 +394,10 @@ ECmdRet ForceHandler<EBehaviour::Detach>::onCommand(const RlvCommand& rlvCmd)
folderID = findDescendentCategoryIDByName(folderID, option);
LLAppearanceMgr::instance().takeOffOutfit(folderID);
}
+ else
+ {
+ LLAppearanceMgr::instance().removeItemFromAvatar(gObjectList.findObject(LLUUID(option))->getAttachmentItemID());
+ }
}
return ECmdRet::Succeeded;
}
@@ -403,14 +408,21 @@ ECmdRet CommandHandlerBaseImpl<EParamType::AddRem>::processCommand(const RlvComm
{
auto param = rlvCmd.getParam();
bool toggle = false;
- if (param == "y")
+ if (param == "y" || param == "add")
toggle = true;
- else if (param != "n")
+ else if (param != "n" && param != "rem")
return ECmdRet::FailedParam;
return (*pHandler)(rlvCmd, toggle);
}
template<> template<>
+ECmdRet BehaviourToggleHandler<EBehaviour::RedirChat>::onCommand(const RlvCommand& rlvCmd, bool& toggle)
+{
+ LLFloaterIMNearbyChat::addOrRemoveRedirChatChannel(std::stoi(rlvCmd.getOption()), toggle);
+ return ECmdRet::Succeeded;
+}
+
+template<> template<>
ECmdRet BehaviourToggleHandler<EBehaviour::Sit>::onCommand(const RlvCommand& rlvCmd, bool& toggle)
{
gAgent.setAllowedToSit(toggle);
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index 2c14434194..4d2a40da67 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -66,6 +66,7 @@ BehaviourDictionary::BehaviourDictionary()
addEntry(new ForceProcessor<EBehaviour::Detach>("detach"));
// AddRem
+ addEntry(new BehaviourProcessor<EBehaviour::RedirChat>("redirchat"));
addEntry(new BehaviourProcessor<EBehaviour::Sit>("sit"));
addEntry(new BehaviourProcessor<EBehaviour::Unsit>("unsit"));
addEntry(new BehaviourProcessor<EBehaviour::Detach>("detach"));
diff --git a/indra/newview/skins/classic/colors.xml b/indra/newview/skins/classic/colors.xml
new file mode 100644
index 0000000000..699b727212
--- /dev/null
+++ b/indra/newview/skins/classic/colors.xml
@@ -0,0 +1,1022 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<colors>
+
+ <!-- Named Colors -->
+ <color
+ name="EmphasisColor"
+ value="0.25 0.48 0.70 1" />
+ <color
+ name="EmphasisColor_13"
+ value="0.25 0.48 0.70 0.13" />
+ <color
+ name="EmphasisColor_35"
+ value="0.25 0.48 0.70 0.35" />
+ <color
+ name="BeaconColor"
+ value="0.749 0.298 0 1" />
+ <color
+ name="White"
+ value="1 1 1 1" />
+ <color
+ name="White_05"
+ value="1 1 1 0.05" />
+ <color
+ name="White_10"
+ value="1 1 1 0.1" />
+ <color
+ name="White_25"
+ value="1 1 1 0.25" />
+ <color
+ name="White_50"
+ value="1 1 1 0.5" />
+ <color
+ name="LtGray"
+ value="0.75 0.75 0.75 1" />
+ <color
+ name="LtGray_35"
+ value="0.75 0.75 0.75 0.35" />
+ <color
+ name="LtGray_50"
+ value="0.75 0.75 0.75 0.50" />
+ <color
+ name="Gray"
+ value="0.5 0.5 0.5 1" />
+ <color
+ name="DkGray0"
+ value="0.27 0.27 0.27 1" />
+ <color
+ name="DkGray"
+ value="0.125 0.125 0.125 1" />
+ <color
+ name="DkGray_66"
+ value="0.125 0.125 0.125 .66" />
+ <color
+ name="DkGray2"
+ value="0.169 0.169 0.169 1" />
+ <color
+ name="MouseGray"
+ value="0.191 0.191 0.191 1" />
+ <color
+ name="Black"
+ value="0 0 0 1" />
+ <color
+ name="Black_10"
+ value="0 0 0 0.1" />
+ <color
+ name="Black_25"
+ value="0 0 0 0.25" />
+ <color
+ name="Black_50"
+ value="0 0 0 0.5" />
+ <color
+ name="FrogGreen"
+ value="0.26 0.33 0.42 1" />
+ <!-- ^(Not actually green) -->
+ <color
+ name="Red"
+ value="1 0 0 1" />
+ <color
+ name="Blue"
+ value="0 0 1 1" />
+ <color
+ name="Yellow"
+ value="1 1 0 1" />
+ <color
+ name="Green"
+ value="0 1 0 1" />
+ <color
+ name="Transparent"
+ value="0 0 0 0" />
+ <color
+ name="Purple"
+ value="1 0 1 1" />
+ <color
+ name="Lime"
+ value=".8 1 .73 1" />
+ <color
+ name="LtYellow"
+ value="1 1 .79 1" />
+ <color
+ name="DrYellow"
+ value="1 0.86 0 1" />
+ <color
+ name="LtOrange"
+ value="1 .85 .73 1" />
+ <color
+ name="MdBlue"
+ value=".07 .38 .51 1" />
+ <color
+ name="DkBlue"
+ value=".06 .06 .3 1" />
+ <color
+ name="LtRed"
+ value="1 0.2 0.2 1" />
+ <color
+ name="LtGreen"
+ value="0.2 1 0.2 1" />
+ <color
+ name="Red_80"
+ value="1 0 0 0.8" />
+ <color
+ name="DkRed"
+ value="0.3 0.06 0.06 1" />
+ <color
+ name="Green_80"
+ value="0 1 0 0.8" />
+ <color
+ name="Blue_80"
+ value="0 0 1 0.8" />
+ <color
+ name="Orange"
+ value="1 .82 .46 1" />
+
+ <!-- This color name makes potentially unused colors show up bright purple.
+ Leave this here until all Unused? are removed below, otherwise
+ the viewer generates many warnings on startup. -->
+ <color
+ name="Unused?"
+ value=".831 1 0 1" />
+
+ <!-- UI Definitions -->
+
+ <color
+ name="AccordionHeaderTextColor"
+ reference="LtGray" />
+ <color
+ name="AgentChatColor"
+ reference="White" />
+ <color
+ name="AlertBoxColor"
+ value="0.24 0.24 0.24 1" />
+ <color
+ name="AlertCautionBoxColor"
+ value="1 0.82 0.46 1" />
+ <color
+ name="AlertCautionTextColor"
+ reference="LtYellow" />
+ <color
+ name="AvatarListItemIconDefaultColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOnlineColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOfflineColor"
+ value="0.5 0.5 0.5 0.5" />
+ <color
+ name="AvatarListItemIconVoiceInvitedColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
+ name="AvatarListItemIconVoiceJoinedColor"
+ reference="AvatarListItemIconOnlineColor" />
+ <color
+ name="AvatarListItemIconVoiceLeftColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
+ name="BadgeImageColor"
+ value="1.0 0.40 0.0 1.0" />
+ <color
+ name="BadgeBorderColor"
+ value="0.9 0.9 0.9 1.0" />
+ <color
+ name="BadgeLabelColor"
+ reference="White" />
+ <color
+ name="ButtonBorderColor"
+ reference="Unused?" />
+ <color
+ name="ButtonCautionImageColor"
+ reference="Unused?" />
+ <color
+ name="ButtonColor"
+ reference="Unused?" />
+ <color
+ name="ButtonFlashBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonImageColor"
+ reference="White" />
+ <color
+ name="ButtonLabelColor"
+ reference="LtGray" />
+ <color
+ name="ButtonLabelDisabledColor"
+ reference="White_25" />
+ <color
+ name="ButtonLabelSelectedColor"
+ reference="White" />
+ <color
+ name="ButtonLabelSelectedDisabledColor"
+ reference="White_25" />
+ <color
+ name="ButtonSelectedBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonSelectedColor"
+ reference="Unused?" />
+ <color
+ name="ButtonUnselectedBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonUnselectedFgColor"
+ reference="Unused?" />
+ <color
+ name="ChatHistoryBgColor"
+ reference="Transparent" />
+ <color
+ name="ChatHistoryTextColor"
+ reference="LtGray" />
+ <color
+ name="ChicletFlashColor"
+ value="0.114 0.65 0.1" />
+ <color
+ name="ColorDropShadow"
+ reference="Black_50" />
+ <color
+ name="ColorPaletteEntry01"
+ reference="Black" />
+ <color
+ name="ColorPaletteEntry02"
+ reference="Gray" />
+ <color
+ name="ColorPaletteEntry03"
+ value="0.5 0 0 1" />
+ <color
+ name="ColorPaletteEntry04"
+ value="0.5 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry05"
+ value="0 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry06"
+ value="0 0.5 0.5 1" />
+ <color
+ name="ColorPaletteEntry07"
+ value="0 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry08"
+ value="0.5 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry09"
+ value="0.5 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry10"
+ value="0 0.25 0.25 1" />
+ <color
+ name="ColorPaletteEntry11"
+ value="0 0.5 1 1" />
+ <color
+ name="ColorPaletteEntry12"
+ value="0 0.25 0.5 1" />
+ <color
+ name="ColorPaletteEntry13"
+ value="0.5 0 1 1" />
+ <color
+ name="ColorPaletteEntry14"
+ value="0.5 0.25 0 1" />
+ <color
+ name="ColorPaletteEntry15"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry16"
+ reference="LtYellow" />
+ <color
+ name="ColorPaletteEntry17"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry18"
+ reference="LtGray" />
+ <color
+ name="ColorPaletteEntry19"
+ reference="Red" />
+ <color
+ name="ColorPaletteEntry20"
+ reference="Yellow" />
+ <color
+ name="ColorPaletteEntry21"
+ reference="Green" />
+ <color
+ name="ColorPaletteEntry22"
+ value="0 1 1 1" />
+ <color
+ name="ColorPaletteEntry23"
+ reference="Blue" />
+ <color
+ name="ColorPaletteEntry24"
+ reference="Purple" />
+ <color
+ name="ColorPaletteEntry25"
+ value="1 1 0.5 1" />
+ <color
+ name="ColorPaletteEntry26"
+ value="0 1 0.5 1" />
+ <color
+ name="ColorPaletteEntry27"
+ value="0.5 1 1 1" />
+ <color
+ name="ColorPaletteEntry28"
+ value="0.5 0.5 1 1" />
+ <color
+ name="ColorPaletteEntry29"
+ value="1 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry30"
+ value="1 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry31"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry32"
+ reference="White" />
+ <color
+ name="ComboListBgColor"
+ reference="DkGray" />
+ <color
+ name="ConsoleBackground"
+ reference="Black" />
+ <color
+ name="ContextSilhouetteColor"
+ reference="EmphasisColor" />
+ <color
+ name="ConversationFriendColor"
+ value="0.5 0.7 0.85 1" />
+ <color
+ name="DefaultHighlightDark"
+ reference="White_10" />
+ <color
+ name="DefaultHighlightLight"
+ reference="White_25" />
+ <color
+ name="DefaultShadowDark"
+ reference="Black_50" />
+ <color
+ name="DefaultShadowLight"
+ reference="Black_50" />
+ <color
+ name="EffectColor"
+ reference="White" />
+ <color
+ name="FilterBackgroundColor"
+ reference="Black" />
+ <color
+ name="FilterTextColor"
+ reference="EmphasisColor" />
+ <color
+ name="FloaterButtonImageColor"
+ reference="LtGray" />
+ <color
+ name="FloaterDefaultBackgroundColor"
+ reference="DkGray_66" />
+ <color
+ name="FloaterFocusBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="FloaterFocusBorderColor"
+ reference="Black_50" />
+ <color
+ name="FloaterUnfocusBorderColor"
+ reference="Black_50" />
+ <color
+ name="FocusColor"
+ reference="EmphasisColor" />
+ <color
+ name="FolderViewLoadingMessageTextColor"
+ value="0.3344 0.545 0.645 1" />
+ <color
+ name="FpsTextColor"
+ value="0.34 0.51 0.64 0.8" />
+ <color
+ name="GridFocusPointColor"
+ reference="White_50" />
+ <color
+ name="GridlineBGColor"
+ value="0.92 0.92 1 0.78" />
+ <color
+ name="GridlineColor"
+ reference="White" />
+ <color
+ name="GridlineShadowColor"
+ value="0 0 0 0.31" />
+ <color
+ name="GroupNotifyBoxColor"
+ value="0.3344 0.5456 0.5159 1" />
+ <color
+ name="GroupNotifyTextColor"
+ reference="White"/>
+ <color
+ name="GroupNotifyDimmedTextColor"
+ reference="LtGray" />
+ <color
+ name="GroupOverTierColor"
+ value="0.43 0.06 0.06 1" />
+ <color
+ name="HTMLLinkColor"
+ reference="EmphasisColor" />
+ <color
+ name="HealthTextColor"
+ reference="White" />
+ <color
+ name="HelpBgColor"
+ reference="Unused?" />
+ <color
+ name="HelpFgColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollHighlightColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollShadowColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollThumbColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollTrackColor"
+ reference="Unused?" />
+ <color
+ name="HighlightChildColor"
+ reference="Yellow" />
+ <color
+ name="HighlightInspectColor"
+ value="1 0 1 1" />
+ <color
+ name="HighlightParentColor"
+ value="0.5 0.65 0.8 1" />
+ <color
+ name="IMHistoryBgColor"
+ reference="Unused?" />
+ <color
+ name="IMHistoryTextColor"
+ reference="Unused?" />
+ <color
+ name="IconDisabledColor"
+ reference="White_25" />
+ <color
+ name="IconEnabledColor"
+ reference="White" />
+ <color
+ name="InventoryBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="InventoryFavoriteColor"
+ reference="Yellow" />
+ <color
+ name="InventoryFocusOutlineColor"
+ reference="White_25" />
+ <color
+ name="InventoryItemSuffixColor"
+ reference="White_25" />
+ <color
+ name="InventoryItemLibraryColor"
+ reference="EmphasisColor" />
+ <color
+ name="InventoryItemLinkColor"
+ reference="LtGray_50" />
+ <color
+ name="InventoryMouseOverColor"
+ reference="LtGray_35" />
+ <color
+ name="InventorySearchStatusColor"
+ reference="EmphasisColor" />
+ <color
+ name="LabelDisabledColor"
+ reference="White_25" />
+ <color
+ name="LabelSelectedColor"
+ reference="White" />
+ <color
+ name="LabelSelectedDisabledColor"
+ reference="White_25" />
+ <color
+ name="LabelTextColor"
+ reference="LtGray" />
+ <color
+ name="LoginProgressBarBgColor"
+ reference="Unused?" />
+ <color
+ name="LoginProgressBarFgColor"
+ reference="Unused?" />
+ <color
+ name="LoginProgressBoxBorderColor"
+ value="0 0.12 0.24 0" />
+ <color
+ name="LoginProgressBoxCenterColor"
+ value="0 0 0 0.78" />
+ <color
+ name="LoginProgressBoxShadowColor"
+ value="0 0 0 0.78" />
+ <color
+ name="LoginProgressBoxTextColor"
+ reference="White" />
+ <color
+ name="MapAvatarColor"
+ reference="White" />
+ <color
+ name="MapAvatarFriendColor"
+ value="0.5 0.7 0.85 1" />
+ <color
+ name="MapAvatarSelfColor"
+ value="0.53125 0 0.498047 1" />
+ <color
+ name="MapFrustumColor"
+ reference="White_10" />
+ <color
+ name="MapParcelOutlineColor"
+ value="1 1 1 0.5" />
+ <color
+ name="MapTrackColor"
+ reference="Red" />
+ <color
+ name="MapTrackColorUnder"
+ reference="Blue" />
+ <color
+ name="MapTrackDisabledColor"
+ value="0.5 0 0 1" />
+ <color
+ name="MenuBarBgColor"
+ reference="MouseGray" />
+ <color
+ name="MenuBarGodBgColor"
+ reference="FrogGreen" />
+ <color
+ name="MenuDefaultBgColor"
+ reference="DkGray2" />
+ <color
+ name="MenuItemDisabledColor"
+ reference="LtGray_50" />
+ <color
+ name="MenuItemEnabledColor"
+ reference="LtGray" />
+ <color
+ name="MenuItemHighlightBgColor"
+ reference="EmphasisColor_35" />
+ <color
+ name="MenuItemFlashBgColor"
+ reference="BeaconColor" />
+ <color
+ name="MenuItemHighlightFgColor"
+ reference="White" />
+ <color
+ name="MenuNonProductionBgColor"
+ reference="Black" />
+ <color
+ name="MenuNonProductionGodBgColor"
+ value="0.263 0.325 0.345 1" />
+ <color
+ name="MenuPopupBgColor"
+ reference="DkGray2" />
+ <color
+ name="ModelUploaderLabels"
+ value="1 0.6 0 1" />
+ <color
+ name="MultiSliderDisabledThumbColor"
+ reference="Black" />
+ <color
+ name="MultiSliderThumbCenterColor"
+ reference="White" />
+ <color
+ name="MultiSliderThumbCenterSelectedColor"
+ reference="Green" />
+ <color
+ name="MultiSliderThumbOutlineColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderTrackColor"
+ reference="LtGray" />
+ <color
+ name="MultiSliderTriangleColor"
+ reference="Yellow" />
+ <!--
+ <color
+ name="NameTagBackground"
+ value="0.85 0.85 0.85 0.80" />
+ -->
+ <color
+ name="NameTagBackground"
+ value="0.101 0.101 0.101 0.6" />
+ <color
+ name="NameTagChat"
+ reference="White" />
+ <color
+ name="NameTagFriend"
+ value="0.5 0.7 0.85 1" />
+ <color
+ name="NameTagLegacy"
+ reference="White" />
+ <color
+ name="NameTagMatch"
+ reference="White" />
+ <color
+ name="NameTagMismatch"
+ reference="White" />
+ <color
+ name="NetMapBackgroundColor"
+ value="0 0 0 1" />
+ <color
+ name="NetMapGroupOwnAboveWater"
+ value="0.85 0 0.85 1" />
+ <color
+ name="NetMapGroupOwnBelowWater"
+ value="0.63 0 0.63 1" />
+ <color
+ name="NetMapOtherOwnAboveWater"
+ value="0.24 0.24 0.24 1" />
+ <color
+ name="NetMapOtherOwnBelowWater"
+ value="0.12 0.12 0.12 1" />
+ <color
+ name="NetMapYouOwnAboveWater"
+ value="0 0.85 0.85 1" />
+ <color
+ name="NetMapYouOwnBelowWater"
+ value="0 0.63 0.63 1" />
+ <color
+ name="NotifyBoxColor"
+ value="LtGray" />
+ <color
+ name="NotifyCautionBoxColor"
+ value="1 0.82 0.46 1" />
+ <color
+ name="NotifyCautionWarnColor"
+ reference="White" />
+ <color
+ name="NotifyTextColor"
+ reference="White" />
+ <color
+ name="ObjectBubbleColor"
+ reference="DkGray_66" />
+ <color
+ name="ObjectChatColor"
+ reference="LtYellow" />
+ <color
+ name="OverdrivenColor"
+ reference="Red" />
+ <color
+ name="PanelDefaultBackgroundColor"
+ reference="DkGray" />
+ <color
+ name="PanelDefaultHighlightLight"
+ reference="White_50" />
+ <color
+ name="PanelFocusBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="PanelNotificationBackground"
+ value="1 0.3 0.3 0" />
+ <color
+ name="ParcelHoverColor"
+ reference="White" />
+ <color
+ name="PathfindingErrorColor"
+ reference="LtRed" />
+ <color
+ name="PathfindingWarningColor"
+ reference="DrYellow" />
+ <color
+ name="PathfindingGoodColor"
+ reference="LtGreen" />
+ <color
+ name="MaterialErrorColor"
+ reference="LtRed" />
+ <color
+ name="MaterialWarningColor"
+ reference="DrYellow" />
+ <color
+ name="MaterialGoodColor"
+ reference="LtGreen" />
+ <color
+ name="PathfindingDefaultBeaconColor"
+ reference="Red_80" />
+ <color
+ name="PathfindingDefaultBeaconTextColor"
+ reference="White" />
+ <color
+ name="PathfindingLinksetBeaconColor"
+ reference="Blue_80" />
+ <color
+ name="PathfindingCharacterBeaconColor"
+ reference="Red_80" />
+ <color
+ name="PieMenuBgColor"
+ value="0.24 0.24 0.24 0.59" />
+ <color
+ name="PieMenuLineColor"
+ value="0 0 0 0.5" />
+ <color
+ name="PieMenuSelectedColor"
+ value="0.72 0.72 0.74 0.3" />
+ <color
+ name="PropertyColorAuction"
+ value="0.5 0 1 0.4" />
+ <color
+ name="PropertyColorAvail"
+ reference="Transparent" />
+ <color
+ name="PropertyColorForSale"
+ value="1 0.5 0 0.4" />
+ <color
+ name="PropertyColorGroup"
+ value="0 0.72 0.72 0.4" />
+ <color
+ name="PropertyColorOther"
+ value="1 0 0 0.4" />
+ <color
+ name="PropertyColorSelf"
+ value="0 1 0 0.4" />
+ <color
+ name="ScriptBgReadOnlyColor"
+ value="0.39 0.39 0.39 1" />
+ <color
+ name="ScriptErrorColor"
+ reference="Red" />
+ <color
+ name="ScrollBGStripeColor"
+ reference="Transparent" />
+ <color
+ name="ScrollBgReadOnlyColor"
+ reference="Transparent" />
+ <color
+ name="ScrollBgWriteableColor"
+ reference="White_05" />
+ <color
+ name="ScrollDisabledColor"
+ reference="White_25" />
+ <color
+ name="ScrollHighlightedColor"
+ reference="Unused?" />
+ <color
+ name="ScrollHoveredColor"
+ reference="EmphasisColor_13" />
+ <color
+ name="ScrollSelectedBGColor"
+ reference="EmphasisColor_35" />
+ <color
+ name="ScrollSelectedFGColor"
+ reference="White" />
+ <color
+ name="ScrollUnselectedColor"
+ reference="LtGray" />
+ <color
+ name="ScrollbarThumbColor"
+ reference="White" />
+ <color
+ name="ScrollbarTrackColor"
+ reference="Black" />
+ <color
+ name="SelectedOutfitTextColor"
+ reference="EmphasisColor" />
+ <color
+ name="SearchableControlHighlightFontColor"
+ value="1 0 0 1" />
+ <color
+ name="SearchableControlHighlightBgColor"
+ value="0.5 0.1 0.1 1" />
+ <color
+ name="SilhouetteChildColor"
+ value="0.13 0.42 0.77 1" />
+ <color
+ name="SilhouetteParentColor"
+ reference="Yellow" />
+ <color
+ name="SliderDisabledThumbColor"
+ reference="White_25" />
+ <color
+ name="SliderThumbCenterColor"
+ reference="White" />
+ <color
+ name="SliderThumbOutlineColor"
+ reference="White" />
+ <color
+ name="SliderTrackColor"
+ reference="Unused?" />
+ <color
+ name="SpeakingColor"
+ reference="FrogGreen" />
+ <color
+ name="SystemChatColor"
+ reference="LtGray" />
+ <color
+ name="TextBgFocusColor"
+ reference="White" />
+ <color
+ name="TextBgReadOnlyColor"
+ reference="White_05" />
+ <color
+ name="TextBgWriteableColor"
+ reference="LtGray" />
+ <color
+ name="TextCursorColor"
+ reference="Black" />
+ <color
+ name="TextDefaultColor"
+ reference="Black" />
+ <color
+ name="TextEmbeddedItemColor"
+ value="0 0 0.5 1" />
+ <color
+ name="TextEmbeddedItemReadOnlyColor"
+ reference="Unused?" />
+ <color
+ name="TextFgColor"
+ value="0.102 0.102 0.102 1" />
+ <color
+ name="TextFgReadOnlyColor"
+ reference="LtGray" />
+ <color
+ name="TextFgTentativeColor"
+ value="0.4 0.4 0.4 1" />
+ <color
+ name="TimeTextColor"
+ reference="LtGray" />
+ <color
+ name="TitleBarFocusColor"
+ reference="White_10" />
+ <color
+ name="ToastBackground"
+ value="0.3 0.3 0.3 0" />
+ <color
+ name="ToolTipBgColor"
+ value="0.937 0.89 0.655 1" />
+ <color
+ name="ToolTipBorderColor"
+ value="0.812 0.753 0.451 1" />
+ <color
+ name="ToolTipTextColor"
+ reference="DkGray2" />
+ <color
+ name="InspectorTipTextColor"
+ reference="LtGray" />
+ <color
+ name="UserChatColor"
+ reference="White" />
+ <color
+ name="llOwnerSayChatColor"
+ reference="LtOrange" />
+
+ <!-- New Colors -->
+ <color
+ name="OutputMonitorMutedColor"
+ reference="DkGray2" />
+ <color
+ name="SysWellItemUnselected"
+ value="0 0 0 0" />
+ <color
+ name="SysWellItemSelected"
+ value="0.3 0.3 0.3 1.0" />
+ <color
+ name="ColorSwatchBorderColor"
+ value="0.45098 0.517647 0.607843 1"/>
+ <color
+ name="ChatTeleportSeparatorColor"
+ reference="Black" />
+ <color
+ name="ChatTimestampColor"
+ reference="White" />
+ <color
+ name="MenuBarBetaBgColor"
+ reference="DkBlue" />
+ <color
+ name="MenuBarProjectBgColor"
+ reference="MdBlue" />
+ <color
+ name="MenuBarTestBgColor"
+ reference="DkRed" />
+ <color
+ name="MeshImportTableNormalColor"
+ value="1 1 1 1"/>
+ <color
+ name="MeshImportTableHighlightColor"
+ value="0.2 0.8 1 1"/>
+
+ <color
+ name="DirectChatColor"
+ reference="LtOrange" />
+
+ <color
+ name="ToolbarDropZoneColor"
+ value=".48 .69 1 .5" />
+ <color
+ name="PanelNotificationListItem"
+ value="0.3 0.3 0.3 .3" />
+
+ <!-- profiles -->
+ <color
+ name="StatusUserOnline"
+ reference="White" />
+ <color
+ name="StatusUserOffline"
+ reference="LtGray_35" />
+ <!-- Groups visible in own profiles -->
+ <color
+ name="GroupVisibleInProfile"
+ reference="TextBgFocusColor" />
+ <color
+ name="GroupHiddenInProfile"
+ reference="Gray" />
+
+
+ <!-- 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"/>
+
+ <!--Resize bar colors -->
+
+ <color
+ name="ResizebarBorderLight"
+ value="0.231 0.231 0.231 1"/>
+
+ <color
+ name="ResizebarBorderDark"
+ value="0.133 0.133 0.133 1"/>
+
+ <color
+ name="ResizebarBody"
+ value="0.208 0.208 0.208 1"/>
+
+ <!-- syntax highlighting (LSL Scripts) -->
+ <color
+ name="ScriptText"
+ reference="Black" />
+ <color
+ name="ScriptBackground"
+ reference="White" />
+ <color
+ name="ScriptCursorColor"
+ reference="Black" />
+ <color
+ name="SyntaxLslComment"
+ value="0 0.5 0 1" />
+ <color
+ name="SyntaxLslConstant"
+ value="0 0.6 0.6 1" />
+ <color
+ name="SyntaxLslControlFlow"
+ value="0.4 0 0.8 1" />
+ <color
+ name="SyntaxLslControlLabel"
+ value="0 0 0.8 1" />
+ <color
+ name="SyntaxLslDataType"
+ value="0.8 0.4 0 1" />
+ <color
+ name="SyntaxLslDeprecated"
+ value="0.9 0.0 0.66, 1" />
+ <color
+ name="SyntaxLslEvent"
+ value="0 0.3 0.5 1" />
+ <color
+ name="SyntaxLslFunction"
+ value="0.3 0 0.5 1" />
+ <color
+ name="SyntaxLslGodMode"
+ value="0.7 .2 .35 1" />
+ <color
+ name="SyntaxLslStringLiteral"
+ value="1 0.14 0 1" />
+ <color
+ name="OutfitGalleryItemSelected"
+ reference="EmphasisColor_35" />
+ <color
+ name="OutfitGalleryItemWorn"
+ reference="EmphasisColor_13" />
+ <color
+ name="OutfitGalleryItemUnselected"
+ value="0.4 0.4 0.4 1" />
+ <color
+ name="PanelGray"
+ value="0.27 0.27 0.27 1" />
+ <color
+ name="PerformanceMid"
+ value="1 0.8 0 1" />
+ <color
+ name="OutfitSnapshotMacMask"
+ value="0.115 0.115 0.115 1"/>
+ <color
+ name="OutfitSnapshotMacMask2"
+ value="0.1 0.1 0.1 1"/>
+ <color
+ name="ChatMentionFont"
+ value="0.3 0.82 1 1" />
+ <color
+ name="ChatMentionHighlight"
+ value="0.82 0.91 0.98 0.15" />
+ <color
+ name="ChatSelfMentionHighlight"
+ value="1 1 0 0.35" />
+ <color
+ name="MentionFlashBgColor"
+ value="1 1 0 0.5" />
+</colors>
diff --git a/indra/newview/skins/classic/textures/3p_icons/fmod_logo.png b/indra/newview/skins/classic/textures/3p_icons/fmod_logo.png
new file mode 100644
index 0000000000..5a50e0ad34
--- /dev/null
+++ b/indra/newview/skins/classic/textures/3p_icons/fmod_logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/3p_icons/havok_logo.png b/indra/newview/skins/classic/textures/3p_icons/havok_logo.png
new file mode 100644
index 0000000000..ff1ea3a72e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/3p_icons/havok_logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Avatar_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Avatar_Off.png
new file mode 100644
index 0000000000..6b725e153a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Avatar_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_FreeCam_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_FreeCam_Off.png
new file mode 100644
index 0000000000..9f22080d13
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_FreeCam_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Orbit_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Orbit_Off.png
new file mode 100644
index 0000000000..5b2a8eb339
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Orbit_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Pan_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Pan_Off.png
new file mode 100644
index 0000000000..9acf7053d5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Pan_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_Off.png
new file mode 100644
index 0000000000..00158a7bc2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_On.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_On.png
new file mode 100644
index 0000000000..3748f5e190
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Back_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Eye_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Eye_Off.png
new file mode 100644
index 0000000000..2b50986780
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Eye_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_Off.png
new file mode 100644
index 0000000000..c49b8f9a27
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_On.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_On.png
new file mode 100644
index 0000000000..bc8c4db04d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Front_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_Off.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_Off.png
new file mode 100644
index 0000000000..b919a0a152
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_On.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_On.png
new file mode 100644
index 0000000000..de9da359a0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Preset_Side_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Center.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Center.png
new file mode 100644
index 0000000000..5f25281518
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Center.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_In.png
new file mode 100644
index 0000000000..1df7618a2b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_In.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Out.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Out.png
new file mode 100644
index 0000000000..cc4e6f99ff
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Rotate_Out.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Center.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Center.png
new file mode 100644
index 0000000000..82e6806af6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Center.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_In.png
new file mode 100644
index 0000000000..338062c083
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_In.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Out.png b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Out.png
new file mode 100644
index 0000000000..cffead1703
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Cam_Tracking_Out.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/ChatBarHandle.png b/indra/newview/skins/classic/textures/bottomtray/ChatBarHandle.png
new file mode 100644
index 0000000000..50239c8af8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/ChatBarHandle.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/DownArrow.png b/indra/newview/skins/classic/textures/bottomtray/DownArrow.png
new file mode 100644
index 0000000000..82f58b22b9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/DownArrow.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_Off.png b/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_Off.png
new file mode 100644
index 0000000000..8d32cad95f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_On.png b/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_On.png
new file mode 100644
index 0000000000..4c98e35868
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Mouselook_View_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Move_Fly_Off.png b/indra/newview/skins/classic/textures/bottomtray/Move_Fly_Off.png
new file mode 100644
index 0000000000..fade065ce7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Move_Fly_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Move_Run_Off.png b/indra/newview/skins/classic/textures/bottomtray/Move_Run_Off.png
new file mode 100644
index 0000000000..e2eb38e12d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Move_Run_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Move_Walk_Off.png b/indra/newview/skins/classic/textures/bottomtray/Move_Walk_Off.png
new file mode 100644
index 0000000000..f314d4e001
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Move_Walk_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_Off.png
new file mode 100644
index 0000000000..4dddc2b391
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_On.png
new file mode 100644
index 0000000000..a2ac8bd8c6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Backward_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Down_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Down_Off.png
new file mode 100644
index 0000000000..2893c9a9f1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Down_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Down_On.png
new file mode 100644
index 0000000000..0cb73798b3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Down_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_Off.png
new file mode 100644
index 0000000000..80d227b6a7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_On.png
new file mode 100644
index 0000000000..83df78e8f3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Forward_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Left_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Left_Off.png
new file mode 100644
index 0000000000..3602efa9d9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Left_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Left_On.png
new file mode 100644
index 0000000000..be7366a2a8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Left_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Right_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Right_Off.png
new file mode 100644
index 0000000000..9c3fc37dfe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Right_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Right_On.png
new file mode 100644
index 0000000000..32bdb8a034
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Right_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_Off.png
new file mode 100644
index 0000000000..282e8d62de
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_On.png
new file mode 100644
index 0000000000..168af4bac5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnLeft_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_Off.png
new file mode 100644
index 0000000000..5039e57c32
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_On.png
new file mode 100644
index 0000000000..803ce250e7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_TurnRight_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Up_Off.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Up_Off.png
new file mode 100644
index 0000000000..a49c43c2cf
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Movement_Up_On.png b/indra/newview/skins/classic/textures/bottomtray/Movement_Up_On.png
new file mode 100644
index 0000000000..3b7f83fbab
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Movement_Up_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/classic/textures/bottomtray/Notices_Unread.png
new file mode 100644
index 0000000000..eb2f3dbaa4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Notices_Unread.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Object_View_Off.png b/indra/newview/skins/classic/textures/bottomtray/Object_View_Off.png
new file mode 100644
index 0000000000..e9dea7e17e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Object_View_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Object_View_On.png b/indra/newview/skins/classic/textures/bottomtray/Object_View_On.png
new file mode 100644
index 0000000000..7a348ba22e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Object_View_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/PanOrbit_Off.png b/indra/newview/skins/classic/textures/bottomtray/PanOrbit_Off.png
new file mode 100644
index 0000000000..53efa3a9a9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/PanOrbit_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Snapshot_Off.png b/indra/newview/skins/classic/textures/bottomtray/Snapshot_Off.png
new file mode 100644
index 0000000000..4ab4bbe4af
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Snapshot_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/Unread_Chiclet.png b/indra/newview/skins/classic/textures/bottomtray/Unread_Chiclet.png
new file mode 100644
index 0000000000..e8fe243dc7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/Unread_Chiclet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl1.png b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl1.png
new file mode 100644
index 0000000000..438b4912f8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl1.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl2.png b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl2.png
new file mode 100644
index 0000000000..693adc4781
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl2.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl3.png b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl3.png
new file mode 100644
index 0000000000..14ec77b99a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Lvl3.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Off.png b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Off.png
new file mode 100644
index 0000000000..48be51e9af
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/VoicePTT_On.png b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_On.png
new file mode 100644
index 0000000000..818b34d40f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/VoicePTT_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit.png
new file mode 100644
index 0000000000..84711ddc29
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit_Selected.png
new file mode 100644
index 0000000000..9b9468c574
--- /dev/null
+++ b/indra/newview/skins/classic/textures/bottomtray/WellButton_Lit_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cone.png b/indra/newview/skins/classic/textures/build/Object_Cone.png
new file mode 100644
index 0000000000..5167f1a820
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cone.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cone_Selected.png b/indra/newview/skins/classic/textures/build/Object_Cone_Selected.png
new file mode 100644
index 0000000000..0f04cb2f28
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cone_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cube.png b/indra/newview/skins/classic/textures/build/Object_Cube.png
new file mode 100644
index 0000000000..e82af1ca82
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cube.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cube_Selected.png b/indra/newview/skins/classic/textures/build/Object_Cube_Selected.png
new file mode 100644
index 0000000000..2a10237771
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cube_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cylinder.png b/indra/newview/skins/classic/textures/build/Object_Cylinder.png
new file mode 100644
index 0000000000..fe1041d4c7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cylinder.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Cylinder_Selected.png b/indra/newview/skins/classic/textures/build/Object_Cylinder_Selected.png
new file mode 100644
index 0000000000..ee6db5d64e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Cylinder_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Grass.png b/indra/newview/skins/classic/textures/build/Object_Grass.png
new file mode 100644
index 0000000000..a88efd5f3e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Grass.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Grass_Selected.png b/indra/newview/skins/classic/textures/build/Object_Grass_Selected.png
new file mode 100644
index 0000000000..37f35f9339
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Grass_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Cone.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Cone.png
new file mode 100644
index 0000000000..595f64d480
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Cone.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Cone_Selected.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Cone_Selected.png
new file mode 100644
index 0000000000..ad6ba66bed
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Cone_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder.png
new file mode 100644
index 0000000000..dd41d56fb3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder_Selected.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder_Selected.png
new file mode 100644
index 0000000000..03a47494f5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Cylinder_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere.png
new file mode 100644
index 0000000000..1489630624
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere_Selected.png b/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere_Selected.png
new file mode 100644
index 0000000000..daefae7389
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Hemi_Sphere_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Prism.png b/indra/newview/skins/classic/textures/build/Object_Prism.png
new file mode 100644
index 0000000000..51c6c161a0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Prism.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Prism_Selected.png b/indra/newview/skins/classic/textures/build/Object_Prism_Selected.png
new file mode 100644
index 0000000000..73470c7af9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Prism_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Pyramid.png b/indra/newview/skins/classic/textures/build/Object_Pyramid.png
new file mode 100644
index 0000000000..a147b59553
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Pyramid.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Pyramid_Selected.png b/indra/newview/skins/classic/textures/build/Object_Pyramid_Selected.png
new file mode 100644
index 0000000000..361c915231
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Pyramid_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Ring.png b/indra/newview/skins/classic/textures/build/Object_Ring.png
new file mode 100644
index 0000000000..a9790fd60c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Ring.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Ring_Selected.png b/indra/newview/skins/classic/textures/build/Object_Ring_Selected.png
new file mode 100644
index 0000000000..49b76d137e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Ring_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Sphere.png b/indra/newview/skins/classic/textures/build/Object_Sphere.png
new file mode 100644
index 0000000000..8e2dd92a82
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Sphere.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Sphere_Selected.png b/indra/newview/skins/classic/textures/build/Object_Sphere_Selected.png
new file mode 100644
index 0000000000..473b90e867
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Sphere_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tetrahedron.png b/indra/newview/skins/classic/textures/build/Object_Tetrahedron.png
new file mode 100644
index 0000000000..23e22b1796
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tetrahedron.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tetrahedron_Selected.png b/indra/newview/skins/classic/textures/build/Object_Tetrahedron_Selected.png
new file mode 100644
index 0000000000..20278c8f6d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tetrahedron_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Torus.png b/indra/newview/skins/classic/textures/build/Object_Torus.png
new file mode 100644
index 0000000000..15c62423a9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Torus.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Torus_Selected.png b/indra/newview/skins/classic/textures/build/Object_Torus_Selected.png
new file mode 100644
index 0000000000..e6cad859fd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Torus_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tree.png b/indra/newview/skins/classic/textures/build/Object_Tree.png
new file mode 100644
index 0000000000..82c422419b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tree.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tree_Selected.png b/indra/newview/skins/classic/textures/build/Object_Tree_Selected.png
new file mode 100644
index 0000000000..52b4f535f8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tree_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tube.png b/indra/newview/skins/classic/textures/build/Object_Tube.png
new file mode 100644
index 0000000000..e47fce7511
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tube.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Object_Tube_Selected.png b/indra/newview/skins/classic/textures/build/Object_Tube_Selected.png
new file mode 100644
index 0000000000..4469814e1a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Object_Tube_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Tool_Create.png b/indra/newview/skins/classic/textures/build/Tool_Create.png
new file mode 100644
index 0000000000..1f1097def5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Tool_Create.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Tool_Dozer.png b/indra/newview/skins/classic/textures/build/Tool_Dozer.png
new file mode 100644
index 0000000000..61744666f4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Tool_Dozer.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Tool_Face.png b/indra/newview/skins/classic/textures/build/Tool_Face.png
new file mode 100644
index 0000000000..5ab42a4ad6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Tool_Face.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Tool_Grab.png b/indra/newview/skins/classic/textures/build/Tool_Grab.png
new file mode 100644
index 0000000000..5c58288d5e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Tool_Grab.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/build/Tool_Zoom.png b/indra/newview/skins/classic/textures/build/Tool_Zoom.png
new file mode 100644
index 0000000000..ad493b0d66
--- /dev/null
+++ b/indra/newview/skins/classic/textures/build/Tool_Zoom.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Off.png b/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Off.png
new file mode 100644
index 0000000000..19c842b816
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Press.png b/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Press.png
new file mode 100644
index 0000000000..b9879dcc8a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_ArrowClosed_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Off.png b/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Off.png
new file mode 100644
index 0000000000..d506cda5c9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Press.png b/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Press.png
new file mode 100644
index 0000000000..08f7493a02
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_ArrowOpened_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_Off.png b/indra/newview/skins/classic/textures/containers/Accordion_Off.png
new file mode 100644
index 0000000000..414f4509c6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_Over.png b/indra/newview/skins/classic/textures/containers/Accordion_Over.png
new file mode 100644
index 0000000000..5416d73310
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_Press.png b/indra/newview/skins/classic/textures/containers/Accordion_Press.png
new file mode 100644
index 0000000000..1578e0dfc5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Accordion_Selected.png b/indra/newview/skins/classic/textures/containers/Accordion_Selected.png
new file mode 100644
index 0000000000..2222954332
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Accordion_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Container.png b/indra/newview/skins/classic/textures/containers/Container.png
new file mode 100644
index 0000000000..511eb94386
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Container.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Left_Off.png b/indra/newview/skins/classic/textures/containers/TabTop_Left_Off.png
new file mode 100644
index 0000000000..c5b232d9ab
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Left_Selected.png b/indra/newview/skins/classic/textures/containers/TabTop_Left_Selected.png
new file mode 100644
index 0000000000..cd78651064
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Middle_Off.png b/indra/newview/skins/classic/textures/containers/TabTop_Middle_Off.png
new file mode 100644
index 0000000000..be624ab273
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Middle_Selected.png b/indra/newview/skins/classic/textures/containers/TabTop_Middle_Selected.png
new file mode 100644
index 0000000000..dba61903a6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Right_Flashing.png b/indra/newview/skins/classic/textures/containers/TabTop_Right_Flashing.png
new file mode 100644
index 0000000000..fd13bb699d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Right_Flashing.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Right_Off.png b/indra/newview/skins/classic/textures/containers/TabTop_Right_Off.png
new file mode 100644
index 0000000000..db28e9e13a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/TabTop_Right_Selected.png b/indra/newview/skins/classic/textures/containers/TabTop_Right_Selected.png
new file mode 100644
index 0000000000..4da3bc232c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/TabTop_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Left_Flash.png b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Flash.png
new file mode 100644
index 0000000000..9f1e2a469d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Flash.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Left_Off.png b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Off.png
new file mode 100644
index 0000000000..f347505772
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Left_Over.png b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Over.png
new file mode 100644
index 0000000000..fd24e5b430
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Left_Selected.png b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Selected.png
new file mode 100644
index 0000000000..dccf543a9a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Flash.png b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Flash.png
new file mode 100644
index 0000000000..dd73d655e9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Flash.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Off.png b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Off.png
new file mode 100644
index 0000000000..cf30330f1c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Over.png b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Over.png
new file mode 100644
index 0000000000..6ac1ce3ffb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Selected.png b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Selected.png
new file mode 100644
index 0000000000..8b40051c0b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Right_Flash.png b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Flash.png
new file mode 100644
index 0000000000..f6b775c2a0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Flash.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Right_Off.png b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Off.png
new file mode 100644
index 0000000000..d4881e21d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Right_Over.png b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Over.png
new file mode 100644
index 0000000000..bf2a72d6f4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/containers/Toolbar_Right_Selected.png b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Selected.png
new file mode 100644
index 0000000000..c3833ad7fa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/containers/Toolbar_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/AddItem_Disabled.png b/indra/newview/skins/classic/textures/icons/AddItem_Disabled.png
new file mode 100644
index 0000000000..d21b72b973
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/AddItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/AddItem_Off.png b/indra/newview/skins/classic/textures/icons/AddItem_Off.png
new file mode 100644
index 0000000000..64108d133a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/AddItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/AddItem_Press.png b/indra/newview/skins/classic/textures/icons/AddItem_Press.png
new file mode 100644
index 0000000000..3168f51757
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/AddItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/AudioMute_Off.png b/indra/newview/skins/classic/textures/icons/AudioMute_Off.png
new file mode 100644
index 0000000000..dd89920fae
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/AudioMute_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/AudioMute_Over.png b/indra/newview/skins/classic/textures/icons/AudioMute_Over.png
new file mode 100644
index 0000000000..a4fbec4144
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/AudioMute_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Audio_Off.png b/indra/newview/skins/classic/textures/icons/Audio_Off.png
new file mode 100644
index 0000000000..4f6f5512c8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Audio_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Audio_Press.png b/indra/newview/skins/classic/textures/icons/Audio_Press.png
new file mode 100644
index 0000000000..0268a0f9fb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Audio_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/BackArrow_Off.png b/indra/newview/skins/classic/textures/icons/BackArrow_Off.png
new file mode 100644
index 0000000000..3775690531
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/BackArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardMenu_Disabled.png b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Disabled.png
new file mode 100644
index 0000000000..c219ac4446
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardMenu_Off.png b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Off.png
new file mode 100644
index 0000000000..586f577181
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardMenu_Press.png b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Press.png
new file mode 100644
index 0000000000..697bee3bbd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardMenu_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Disabled.png b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Disabled.png
new file mode 100644
index 0000000000..12cc1857d4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Off.png b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Off.png
new file mode 100644
index 0000000000..7b40e33e11
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Press.png b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Press.png
new file mode 100644
index 0000000000..e030c44f01
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ClipboardSmallMenu_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_log_inbox.png b/indra/newview/skins/classic/textures/icons/Conv_log_inbox.png
new file mode 100644
index 0000000000..f4bbdc059d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_log_inbox.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_add_person.png
new file mode 100644
index 0000000000..acb3904e32
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_add_person.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_ne.png
new file mode 100644
index 0000000000..70dec7cad1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_ne.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_sw.png
new file mode 100644
index 0000000000..13d424832b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_arrow_sw.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_call_log.png
new file mode 100644
index 0000000000..1866dd965c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_call_log.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_close.png
new file mode 100644
index 0000000000..f4f2e2fd37
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_close.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_collapse.png
new file mode 100644
index 0000000000..3c427a3cc5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_collapse.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_expand.png
new file mode 100644
index 0000000000..6e8031b42c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_expand.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_hang_up.png
new file mode 100644
index 0000000000..887a3b8335
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_hang_up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_open_call.png
new file mode 100644
index 0000000000..fc0da5a810
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_open_call.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_plus.png
new file mode 100644
index 0000000000..6d45dbbff6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_plus.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/classic/textures/icons/Conv_toolbar_sort.png
new file mode 100644
index 0000000000..e3e5f49741
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Conv_toolbar_sort.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Copy.png b/indra/newview/skins/classic/textures/icons/Copy.png
new file mode 100644
index 0000000000..8448e70385
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Copy.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/CopyBright.png b/indra/newview/skins/classic/textures/icons/CopyBright.png
new file mode 100644
index 0000000000..ac65d68e0b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/CopyBright.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Default_Outfit_Photo.png b/indra/newview/skins/classic/textures/icons/Default_Outfit_Photo.png
new file mode 100644
index 0000000000..1113b4effe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Default_Outfit_Photo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/DownArrow_Off.png b/indra/newview/skins/classic/textures/icons/DownArrow_Off.png
new file mode 100644
index 0000000000..2e1e2964a0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/DownArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Edit_Wrench.png b/indra/newview/skins/classic/textures/icons/Edit_Wrench.png
new file mode 100644
index 0000000000..2b9ba9dc10
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Edit_Wrench.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ExternalBrowser_Off.png b/indra/newview/skins/classic/textures/icons/ExternalBrowser_Off.png
new file mode 100644
index 0000000000..dc4532b5a1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ExternalBrowser_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Facebook.png b/indra/newview/skins/classic/textures/icons/Facebook.png
new file mode 100644
index 0000000000..9e51e3ac7f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Facebook.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Female.png b/indra/newview/skins/classic/textures/icons/Female.png
new file mode 100644
index 0000000000..c9fef87b6e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Female.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ForSale_Badge.png b/indra/newview/skins/classic/textures/icons/ForSale_Badge.png
new file mode 100644
index 0000000000..3b3a41c7c1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ForSale_Badge.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ForwardArrow_Off.png b/indra/newview/skins/classic/textures/icons/ForwardArrow_Off.png
new file mode 100644
index 0000000000..c33320cf6e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ForwardArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/ForwardArrow_Press.png b/indra/newview/skins/classic/textures/icons/ForwardArrow_Press.png
new file mode 100644
index 0000000000..86eb39c43a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/ForwardArrow_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Generic_Group.png b/indra/newview/skins/classic/textures/icons/Generic_Group.png
new file mode 100644
index 0000000000..e96b7fc992
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Generic_Group.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Generic_Group_Large.png b/indra/newview/skins/classic/textures/icons/Generic_Group_Large.png
new file mode 100644
index 0000000000..9396819bfb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Generic_Group_Large.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Generic_Object_Small.png b/indra/newview/skins/classic/textures/icons/Generic_Object_Small.png
new file mode 100644
index 0000000000..142390e3f3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Generic_Object_Small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Generic_Person.png b/indra/newview/skins/classic/textures/icons/Generic_Person.png
new file mode 100644
index 0000000000..162735d979
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Generic_Person.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Generic_Person_Large.png b/indra/newview/skins/classic/textures/icons/Generic_Person_Large.png
new file mode 100644
index 0000000000..5be82418c1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Generic_Person_Large.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Group_Notices.png b/indra/newview/skins/classic/textures/icons/Group_Notices.png
new file mode 100644
index 0000000000..601502d374
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Group_Notices.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Hierarchy_View_Disabled.png b/indra/newview/skins/classic/textures/icons/Hierarchy_View_Disabled.png
new file mode 100644
index 0000000000..6d8ea5fd93
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Hierarchy_View_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Hierarchy_View_On.png b/indra/newview/skins/classic/textures/icons/Hierarchy_View_On.png
new file mode 100644
index 0000000000..24f5210286
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Hierarchy_View_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Attachment_Large.png b/indra/newview/skins/classic/textures/icons/Icon_Attachment_Large.png
new file mode 100644
index 0000000000..fb57265dac
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Attachment_Large.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Attachment_Small.png b/indra/newview/skins/classic/textures/icons/Icon_Attachment_Small.png
new file mode 100644
index 0000000000..907113cbb7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Attachment_Small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Color_Palette.png b/indra/newview/skins/classic/textures/icons/Icon_Color_Palette.png
new file mode 100644
index 0000000000..28906001ea
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Color_Palette.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Font_Size.png b/indra/newview/skins/classic/textures/icons/Icon_Font_Size.png
new file mode 100644
index 0000000000..37bdde69aa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Font_Size.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_For_Sale.png b/indra/newview/skins/classic/textures/icons/Icon_For_Sale.png
new file mode 100644
index 0000000000..57a376f1bf
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_For_Sale.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Notification_Condense.png b/indra/newview/skins/classic/textures/icons/Icon_Notification_Condense.png
new file mode 100644
index 0000000000..3a19e79f82
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Notification_Condense.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Notification_Expand.png b/indra/newview/skins/classic/textures/icons/Icon_Notification_Expand.png
new file mode 100644
index 0000000000..f5331feb02
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Notification_Expand.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Icon_Pointer.png b/indra/newview/skins/classic/textures/icons/Icon_Pointer.png
new file mode 100644
index 0000000000..021942a8aa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Icon_Pointer.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Info.png b/indra/newview/skins/classic/textures/icons/Info.png
new file mode 100644
index 0000000000..e05a585f0b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Info.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Info_Over.png b/indra/newview/skins/classic/textures/icons/Info_Over.png
new file mode 100644
index 0000000000..6399cd6715
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Info_Small.png b/indra/newview/skins/classic/textures/icons/Info_Small.png
new file mode 100644
index 0000000000..c4ce13e132
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Info_Small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Alpha.png b/indra/newview/skins/classic/textures/icons/Inv_Alpha.png
new file mode 100644
index 0000000000..fdad36e2d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Alpha.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Animation.png b/indra/newview/skins/classic/textures/icons/Inv_Animation.png
new file mode 100644
index 0000000000..6715c736e7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Animation.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_BodyShape.png b/indra/newview/skins/classic/textures/icons/Inv_BodyShape.png
new file mode 100644
index 0000000000..cb908a39fb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_BodyShape.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_CallingCard.png b/indra/newview/skins/classic/textures/icons/Inv_CallingCard.png
new file mode 100644
index 0000000000..ee87f8e595
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_CallingCard.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Clothing.png b/indra/newview/skins/classic/textures/icons/Inv_Clothing.png
new file mode 100644
index 0000000000..430dca6b5e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Clothing.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Eye.png b/indra/newview/skins/classic/textures/icons/Inv_Eye.png
new file mode 100644
index 0000000000..d715f135d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Eye.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Content.png b/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Content.png
new file mode 100644
index 0000000000..b71b202234
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Content.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Full.png b/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Full.png
new file mode 100644
index 0000000000..7d55fb5cfe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Favorite_Star_Full.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_FolderClosed.png b/indra/newview/skins/classic/textures/icons/Inv_FolderClosed.png
new file mode 100644
index 0000000000..ec99eaee9e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_FolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_FolderOpen.png b/indra/newview/skins/classic/textures/icons/Inv_FolderOpen.png
new file mode 100644
index 0000000000..615a6ec11b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_FolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Gesture.png b/indra/newview/skins/classic/textures/icons/Inv_Gesture.png
new file mode 100644
index 0000000000..9fee34915e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Gesture.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Gloves.png b/indra/newview/skins/classic/textures/icons/Inv_Gloves.png
new file mode 100644
index 0000000000..aa151d5404
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Gloves.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Hair.png b/indra/newview/skins/classic/textures/icons/Inv_Hair.png
new file mode 100644
index 0000000000..62b3ae81c2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Hair.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Invalid.png b/indra/newview/skins/classic/textures/icons/Inv_Invalid.png
new file mode 100644
index 0000000000..6ab5ba5217
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Invalid.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Jacket.png b/indra/newview/skins/classic/textures/icons/Inv_Jacket.png
new file mode 100644
index 0000000000..26514f1c0f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Jacket.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Landmark.png b/indra/newview/skins/classic/textures/icons/Inv_Landmark.png
new file mode 100644
index 0000000000..338323fcee
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Landmark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Link.png b/indra/newview/skins/classic/textures/icons/Inv_Link.png
new file mode 100644
index 0000000000..28c5f3635a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Link.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LinkFolder.png b/indra/newview/skins/classic/textures/icons/Inv_LinkFolder.png
new file mode 100644
index 0000000000..7c43ed3a43
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LinkFolder.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LinkItem.png b/indra/newview/skins/classic/textures/icons/Inv_LinkItem.png
new file mode 100644
index 0000000000..7c43ed3a43
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LinkItem.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LookFolderClosed.png b/indra/newview/skins/classic/textures/icons/Inv_LookFolderClosed.png
new file mode 100644
index 0000000000..46f2038279
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LookFolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LookFolderOpen.png b/indra/newview/skins/classic/textures/icons/Inv_LookFolderOpen.png
new file mode 100644
index 0000000000..06a1b05983
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LookFolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LostClosed.png b/indra/newview/skins/classic/textures/icons/Inv_LostClosed.png
new file mode 100644
index 0000000000..fc9a2a2156
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LostClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_LostOpen.png b/indra/newview/skins/classic/textures/icons/Inv_LostOpen.png
new file mode 100644
index 0000000000..b15dc3cfa3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_LostOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Material.png b/indra/newview/skins/classic/textures/icons/Inv_Material.png
new file mode 100644
index 0000000000..5cbb4fc5c9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Material.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Mesh.png b/indra/newview/skins/classic/textures/icons/Inv_Mesh.png
new file mode 100644
index 0000000000..69217d1cdc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Mesh.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Notecard.png b/indra/newview/skins/classic/textures/icons/Inv_Notecard.png
new file mode 100644
index 0000000000..96f45bc55e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Notecard.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Object.png b/indra/newview/skins/classic/textures/icons/Inv_Object.png
new file mode 100644
index 0000000000..fe6b201570
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Object.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Object_Multi.png b/indra/newview/skins/classic/textures/icons/Inv_Object_Multi.png
new file mode 100644
index 0000000000..3793594059
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Object_Multi.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Pants.png b/indra/newview/skins/classic/textures/icons/Inv_Pants.png
new file mode 100644
index 0000000000..5673bc29ed
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Pants.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Physics.png b/indra/newview/skins/classic/textures/icons/Inv_Physics.png
new file mode 100644
index 0000000000..43bd082d8a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Physics.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Script.png b/indra/newview/skins/classic/textures/icons/Inv_Script.png
new file mode 100644
index 0000000000..68d2ac425f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Script.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Settings.png b/indra/newview/skins/classic/textures/icons/Inv_Settings.png
new file mode 100644
index 0000000000..ca6cf10314
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Settings.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_SettingsDay.png b/indra/newview/skins/classic/textures/icons/Inv_SettingsDay.png
new file mode 100644
index 0000000000..d0c4b2cdcd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_SettingsDay.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_SettingsSky.png b/indra/newview/skins/classic/textures/icons/Inv_SettingsSky.png
new file mode 100644
index 0000000000..5332404d37
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_SettingsSky.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_SettingsWater.png b/indra/newview/skins/classic/textures/icons/Inv_SettingsWater.png
new file mode 100644
index 0000000000..88ff803756
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_SettingsWater.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Shape.png b/indra/newview/skins/classic/textures/icons/Inv_Shape.png
new file mode 100644
index 0000000000..e5db447b36
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Shape.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Shirt.png b/indra/newview/skins/classic/textures/icons/Inv_Shirt.png
new file mode 100644
index 0000000000..ffabff9c6c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Shirt.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Shoe.png b/indra/newview/skins/classic/textures/icons/Inv_Shoe.png
new file mode 100644
index 0000000000..784d1d23a3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Shoe.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Skin.png b/indra/newview/skins/classic/textures/icons/Inv_Skin.png
new file mode 100644
index 0000000000..a232c5ac67
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Skin.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Skirt.png b/indra/newview/skins/classic/textures/icons/Inv_Skirt.png
new file mode 100644
index 0000000000..5970f39b1b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Skirt.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Snapshot.png b/indra/newview/skins/classic/textures/icons/Inv_Snapshot.png
new file mode 100644
index 0000000000..9eaca9e7ef
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Snapshot.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Socks.png b/indra/newview/skins/classic/textures/icons/Inv_Socks.png
new file mode 100644
index 0000000000..95a3a68de6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Socks.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Sound.png b/indra/newview/skins/classic/textures/icons/Inv_Sound.png
new file mode 100644
index 0000000000..138d4c5c36
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Sound.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_StockFolderClosed.png b/indra/newview/skins/classic/textures/icons/Inv_StockFolderClosed.png
new file mode 100644
index 0000000000..c3aae7c736
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_StockFolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_StockFolderOpen.png b/indra/newview/skins/classic/textures/icons/Inv_StockFolderOpen.png
new file mode 100644
index 0000000000..15fd8225fc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_StockFolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_SysClosed.png b/indra/newview/skins/classic/textures/icons/Inv_SysClosed.png
new file mode 100644
index 0000000000..2550cae0d4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_SysClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_SysOpen.png b/indra/newview/skins/classic/textures/icons/Inv_SysOpen.png
new file mode 100644
index 0000000000..5b56d86184
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_SysOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Tattoo.png b/indra/newview/skins/classic/textures/icons/Inv_Tattoo.png
new file mode 100644
index 0000000000..af5a780685
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Tattoo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Texture.png b/indra/newview/skins/classic/textures/icons/Inv_Texture.png
new file mode 100644
index 0000000000..168a97515a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Texture.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Toolbar_SearchVisibility.png b/indra/newview/skins/classic/textures/icons/Inv_Toolbar_SearchVisibility.png
new file mode 100644
index 0000000000..c4b186c3de
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Toolbar_SearchVisibility.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_TrashClosed.png b/indra/newview/skins/classic/textures/icons/Inv_TrashClosed.png
new file mode 100644
index 0000000000..89f0caa5a2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_TrashClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_TrashOpen.png b/indra/newview/skins/classic/textures/icons/Inv_TrashOpen.png
new file mode 100644
index 0000000000..d1f1eeaf42
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_TrashOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Underpants.png b/indra/newview/skins/classic/textures/icons/Inv_Underpants.png
new file mode 100644
index 0000000000..77f8e55270
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Underpants.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Undershirt.png b/indra/newview/skins/classic/textures/icons/Inv_Undershirt.png
new file mode 100644
index 0000000000..477d76cf11
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Undershirt.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_Universal.png b/indra/newview/skins/classic/textures/icons/Inv_Universal.png
new file mode 100644
index 0000000000..65b2f88f02
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_Universal.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_UnknownObject.png b/indra/newview/skins/classic/textures/icons/Inv_UnknownObject.png
new file mode 100644
index 0000000000..603a6d7aaa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_UnknownObject.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_VersionFolderClosed.png b/indra/newview/skins/classic/textures/icons/Inv_VersionFolderClosed.png
new file mode 100644
index 0000000000..cd561d24ba
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_VersionFolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Inv_VersionFolderOpen.png b/indra/newview/skins/classic/textures/icons/Inv_VersionFolderOpen.png
new file mode 100644
index 0000000000..6dc9d451cc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Inv_VersionFolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/List_View_Disabled.png b/indra/newview/skins/classic/textures/icons/List_View_Disabled.png
new file mode 100644
index 0000000000..125034b0cb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/List_View_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/List_View_On.png b/indra/newview/skins/classic/textures/icons/List_View_On.png
new file mode 100644
index 0000000000..fcf77f004f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/List_View_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Lock.png b/indra/newview/skins/classic/textures/icons/Lock.png
new file mode 100644
index 0000000000..2db6ed0213
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Lock.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Locked_Icon.png b/indra/newview/skins/classic/textures/icons/Locked_Icon.png
new file mode 100644
index 0000000000..4985af1be1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Locked_Icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/MP_Logo.png b/indra/newview/skins/classic/textures/icons/MP_Logo.png
new file mode 100644
index 0000000000..6aba54189f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/MP_Logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Male.png b/indra/newview/skins/classic/textures/icons/Male.png
new file mode 100644
index 0000000000..803171f5c6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Male.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Microphone_On.png b/indra/newview/skins/classic/textures/icons/Microphone_On.png
new file mode 100644
index 0000000000..7a7d39d982
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Microphone_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/MinusItem_Disabled.png b/indra/newview/skins/classic/textures/icons/MinusItem_Disabled.png
new file mode 100644
index 0000000000..b62ed35182
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/MinusItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/MinusItem_Off.png b/indra/newview/skins/classic/textures/icons/MinusItem_Off.png
new file mode 100644
index 0000000000..eb7b8838f7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/MinusItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/MinusItem_Press.png b/indra/newview/skins/classic/textures/icons/MinusItem_Press.png
new file mode 100644
index 0000000000..2dc6081cb0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/MinusItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/MusicNote.png b/indra/newview/skins/classic/textures/icons/MusicNote.png
new file mode 100644
index 0000000000..8d3534a94b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/MusicNote.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OptionsMenu_Disabled.png b/indra/newview/skins/classic/textures/icons/OptionsMenu_Disabled.png
new file mode 100644
index 0000000000..5755315e23
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OptionsMenu_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OptionsMenu_Off.png b/indra/newview/skins/classic/textures/icons/OptionsMenu_Off.png
new file mode 100644
index 0000000000..2e9a5faa21
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OptionsMenu_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OptionsMenu_Press.png b/indra/newview/skins/classic/textures/icons/OptionsMenu_Press.png
new file mode 100644
index 0000000000..1b08648b51
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OptionsMenu_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Disabled.png
new file mode 100644
index 0000000000..1d2dbd6349
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Off.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Off.png
new file mode 100644
index 0000000000..f8f3367c42
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_On.png b/indra/newview/skins/classic/textures/icons/OutboxPush_On.png
new file mode 100644
index 0000000000..b1fd734100
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/classic/textures/icons/OutboxPush_On_Over.png
new file mode 100644
index 0000000000..e234400b72
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Over.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Over.png
new file mode 100644
index 0000000000..9e1b0e2dfc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Press.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Press.png
new file mode 100644
index 0000000000..14d9eacc52
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_1.png
new file mode 100644
index 0000000000..85015fc913
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_2.png
new file mode 100644
index 0000000000..6158242b68
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_3.png
new file mode 100644
index 0000000000..7105380bff
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_4.png
new file mode 100644
index 0000000000..0e65a60fc8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_5.png
new file mode 100644
index 0000000000..7acef05891
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_6.png
new file mode 100644
index 0000000000..4f5b34a643
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected.png
new file mode 100644
index 0000000000..d58826da67
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Disabled.png
new file mode 100644
index 0000000000..cad9f118b1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Over.png
new file mode 100644
index 0000000000..65d914c6b3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Press.png
new file mode 100644
index 0000000000..cd50d41903
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/OutboxPush_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Dark.png
new file mode 100644
index 0000000000..dd12d94ad2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Light.png
new file mode 100644
index 0000000000..4739c501ad
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_BuildNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Build_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Build_Dark.png
new file mode 100644
index 0000000000..9826491efd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Build_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_DamageNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_DamageNo_Dark.png
new file mode 100644
index 0000000000..7634e5fab0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_DamageNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Damage_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Damage_Dark.png
new file mode 100644
index 0000000000..7ecd645df2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Damage_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Exp_Color.png b/indra/newview/skins/classic/textures/icons/Parcel_Exp_Color.png
new file mode 100644
index 0000000000..a1b0faa008
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Exp_Color.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Dark.png
new file mode 100644
index 0000000000..831c25a34b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Light.png
new file mode 100644
index 0000000000..be829fb5ef
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_FlyNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Fly_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Fly_Dark.png
new file mode 100644
index 0000000000..579bfe58f8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Fly_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_ForSale_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_ForSale_Light.png
new file mode 100644
index 0000000000..3f4ee0b482
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_ForSale_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Health_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Health_Dark.png
new file mode 100644
index 0000000000..98618de927
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Health_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_M_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_M_Dark.png
new file mode 100644
index 0000000000..ab5a1680a7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_M_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_M_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_M_Light.png
new file mode 100644
index 0000000000..2db94e37c9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_M_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_PG_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_PG_Dark.png
new file mode 100644
index 0000000000..e1f7613d04
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_PG_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_PG_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_PG_Light.png
new file mode 100644
index 0000000000..04d13027d2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_PG_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Dark.png
new file mode 100644
index 0000000000..2867004014
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Light.png
new file mode 100644
index 0000000000..a3a51973af
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_PushNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Push_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Push_Dark.png
new file mode 100644
index 0000000000..e8487ca092
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Push_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_R_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_R_Dark.png
new file mode 100644
index 0000000000..5c165c2fac
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_R_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_R_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_R_Light.png
new file mode 100644
index 0000000000..dbf43152b3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_R_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_ScriptsNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_ScriptsNo_Dark.png
new file mode 100644
index 0000000000..bfc55fc403
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_ScriptsNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Scripts_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Scripts_Dark.png
new file mode 100644
index 0000000000..3477e0654c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Scripts_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Dark.png
new file mode 100644
index 0000000000..eff089487e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Light.png
new file mode 100644
index 0000000000..68f0b14d44
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOff_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Dark.png
new file mode 100644
index 0000000000..200e04a59f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Light.png
new file mode 100644
index 0000000000..14cafc5bd2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_SeeAVsOn_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Dark.png
new file mode 100644
index 0000000000..ec316e822e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Light.png
new file mode 100644
index 0000000000..de3532a70b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_VoiceNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Voice_Dark.png b/indra/newview/skins/classic/textures/icons/Parcel_Voice_Dark.png
new file mode 100644
index 0000000000..329620fa69
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Voice_Dark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Parcel_Voice_Light.png b/indra/newview/skins/classic/textures/icons/Parcel_Voice_Light.png
new file mode 100644
index 0000000000..81e0fa7bc4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Parcel_Voice_Light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Pathfinding_Dirty.png b/indra/newview/skins/classic/textures/icons/Pathfinding_Dirty.png
new file mode 100644
index 0000000000..d8fee0fef7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Pathfinding_Dirty.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Pathfinding_Disabled.png b/indra/newview/skins/classic/textures/icons/Pathfinding_Disabled.png
new file mode 100644
index 0000000000..ea2ad79611
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Pathfinding_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Pause_Off.png b/indra/newview/skins/classic/textures/icons/Pause_Off.png
new file mode 100644
index 0000000000..5d44412783
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Pause_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Pause_Over.png b/indra/newview/skins/classic/textures/icons/Pause_Over.png
new file mode 100644
index 0000000000..d1609a144b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Pause_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Pause_Press.png b/indra/newview/skins/classic/textures/icons/Pause_Press.png
new file mode 100644
index 0000000000..6b918d1ae6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Pause_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Permission_Ungranted.png b/indra/newview/skins/classic/textures/icons/Permission_Ungranted.png
new file mode 100644
index 0000000000..d206af4433
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Permission_Ungranted.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Person_Check.png b/indra/newview/skins/classic/textures/icons/Person_Check.png
new file mode 100644
index 0000000000..39a63a70cf
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Person_Check.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Person_Star.png b/indra/newview/skins/classic/textures/icons/Person_Star.png
new file mode 100644
index 0000000000..c4e625b3c1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Person_Star.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Play_Off.png b/indra/newview/skins/classic/textures/icons/Play_Off.png
new file mode 100644
index 0000000000..dac2f2d6db
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Play_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Play_Over.png b/indra/newview/skins/classic/textures/icons/Play_Over.png
new file mode 100644
index 0000000000..1d261efcda
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Play_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Play_Press.png b/indra/newview/skins/classic/textures/icons/Play_Press.png
new file mode 100644
index 0000000000..f7251ce549
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Play_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Presets_Icon.png b/indra/newview/skins/classic/textures/icons/Presets_Icon.png
new file mode 100644
index 0000000000..13642e88d1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Presets_Icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Presets_Icon_Graphic.png b/indra/newview/skins/classic/textures/icons/Presets_Icon_Graphic.png
new file mode 100644
index 0000000000..96d1021f81
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Presets_Icon_Graphic.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Friend_Offline.png b/indra/newview/skins/classic/textures/icons/Profile_Friend_Offline.png
new file mode 100644
index 0000000000..55d922cda7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Friend_Offline.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Friend_Online.png b/indra/newview/skins/classic/textures/icons/Profile_Friend_Online.png
new file mode 100644
index 0000000000..febe8e78fa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Friend_Online.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Disabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Disabled.png
new file mode 100644
index 0000000000..2632eb173b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Enabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Enabled.png
new file mode 100644
index 0000000000..fd8b152c12
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Find_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Disabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Disabled.png
new file mode 100644
index 0000000000..cef3ec4e5a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Enabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Enabled.png
new file mode 100644
index 0000000000..5821566703
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Objects_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Disabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Disabled.png
new file mode 100644
index 0000000000..ea1b55eca0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Enabled.png b/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Enabled.png
new file mode 100644
index 0000000000..eb3fc9e713
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Profile_Perm_Online_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_1.png b/indra/newview/skins/classic/textures/icons/Progress_1.png
new file mode 100644
index 0000000000..bc7a1e7e96
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_10.png b/indra/newview/skins/classic/textures/icons/Progress_10.png
new file mode 100644
index 0000000000..acf4d21aba
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_10.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_11.png b/indra/newview/skins/classic/textures/icons/Progress_11.png
new file mode 100644
index 0000000000..1842cd09d0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_11.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_12.png b/indra/newview/skins/classic/textures/icons/Progress_12.png
new file mode 100644
index 0000000000..0ea9dda83e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_12.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_2.png b/indra/newview/skins/classic/textures/icons/Progress_2.png
new file mode 100644
index 0000000000..29d6bbcbcb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_3.png b/indra/newview/skins/classic/textures/icons/Progress_3.png
new file mode 100644
index 0000000000..52a03125e9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_4.png b/indra/newview/skins/classic/textures/icons/Progress_4.png
new file mode 100644
index 0000000000..4b2798519f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_5.png b/indra/newview/skins/classic/textures/icons/Progress_5.png
new file mode 100644
index 0000000000..3f02b8f31a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_6.png b/indra/newview/skins/classic/textures/icons/Progress_6.png
new file mode 100644
index 0000000000..04c8f716d4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_7.png b/indra/newview/skins/classic/textures/icons/Progress_7.png
new file mode 100644
index 0000000000..c96b4c08d6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_7.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_8.png b/indra/newview/skins/classic/textures/icons/Progress_8.png
new file mode 100644
index 0000000000..9463f50707
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_8.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Progress_9.png b/indra/newview/skins/classic/textures/icons/Progress_9.png
new file mode 100644
index 0000000000..928a3e934e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Progress_9.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Refresh_Off.png b/indra/newview/skins/classic/textures/icons/Refresh_Off.png
new file mode 100644
index 0000000000..e645a8159f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Refresh_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/SL_Logo.png b/indra/newview/skins/classic/textures/icons/SL_Logo.png
new file mode 100644
index 0000000000..5e376c72f9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/SL_Logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Search_Icon.png b/indra/newview/skins/classic/textures/icons/Search_Icon.png
new file mode 100644
index 0000000000..0ea7b14f81
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Search_Icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Shirt_Large.png b/indra/newview/skins/classic/textures/icons/Shirt_Large.png
new file mode 100644
index 0000000000..06fce6bbaa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Shirt_Large.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Shop.png b/indra/newview/skins/classic/textures/icons/Shop.png
new file mode 100644
index 0000000000..93353cf2fe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Shop.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/SkipBackward_Off.png b/indra/newview/skins/classic/textures/icons/SkipBackward_Off.png
new file mode 100644
index 0000000000..20fd2b8e22
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/SkipBackward_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/SkipForward_Off.png b/indra/newview/skins/classic/textures/icons/SkipForward_Off.png
new file mode 100644
index 0000000000..30e28d3d31
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/SkipForward_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/StopReload_Off.png b/indra/newview/skins/classic/textures/icons/StopReload_Off.png
new file mode 100644
index 0000000000..500a81d715
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/StopReload_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/StopReload_Over.png b/indra/newview/skins/classic/textures/icons/StopReload_Over.png
new file mode 100644
index 0000000000..a065a37d14
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/StopReload_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Stop_Off.png b/indra/newview/skins/classic/textures/icons/Stop_Off.png
new file mode 100644
index 0000000000..2d00083e2e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Stop_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Disabled.png b/indra/newview/skins/classic/textures/icons/Sync_Disabled.png
new file mode 100644
index 0000000000..7b39e7cd6f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Enabled.png b/indra/newview/skins/classic/textures/icons/Sync_Enabled.png
new file mode 100644
index 0000000000..0e7e5157cb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_1.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_1.png
new file mode 100644
index 0000000000..218edaa986
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_2.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_2.png
new file mode 100644
index 0000000000..23cb9d63c0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_3.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_3.png
new file mode 100644
index 0000000000..490826011a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_4.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_4.png
new file mode 100644
index 0000000000..de1c815e90
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_5.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_5.png
new file mode 100644
index 0000000000..2897b37382
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Sync_Progress_6.png b/indra/newview/skins/classic/textures/icons/Sync_Progress_6.png
new file mode 100644
index 0000000000..862410e9e4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Sync_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/System_Notification_Large.png b/indra/newview/skins/classic/textures/icons/System_Notification_Large.png
new file mode 100644
index 0000000000..01c6e31f41
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/System_Notification_Large.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/System_Notification_Small.png b/indra/newview/skins/classic/textures/icons/System_Notification_Small.png
new file mode 100644
index 0000000000..69b823d852
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/System_Notification_Small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/TrashItem_Disabled.png b/indra/newview/skins/classic/textures/icons/TrashItem_Disabled.png
new file mode 100644
index 0000000000..800d9434d2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/TrashItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/TrashItem_Off.png b/indra/newview/skins/classic/textures/icons/TrashItem_Off.png
new file mode 100644
index 0000000000..0cbff4f1d7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/TrashItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/TrashItem_Press.png b/indra/newview/skins/classic/textures/icons/TrashItem_Press.png
new file mode 100644
index 0000000000..fac13226e7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/TrashItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/UnZoom_Off.png b/indra/newview/skins/classic/textures/icons/UnZoom_Off.png
new file mode 100644
index 0000000000..34ec3f5de8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/UnZoom_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/UpArrow_Off.png b/indra/newview/skins/classic/textures/icons/UpArrow_Off.png
new file mode 100644
index 0000000000..d5ddc353e7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/UpArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Video_URL_Off.png b/indra/newview/skins/classic/textures/icons/Video_URL_Off.png
new file mode 100644
index 0000000000..d37a189645
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Video_URL_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoiceMute_Off.png b/indra/newview/skins/classic/textures/icons/VoiceMute_Off.png
new file mode 100644
index 0000000000..425ba267a5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoiceMute_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl1.png b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl1.png
new file mode 100644
index 0000000000..cc3407b57d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl1.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl2.png b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl2.png
new file mode 100644
index 0000000000..49f58d7cd0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl2.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl3.png b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl3.png
new file mode 100644
index 0000000000..a4a171bd81
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoicePTT_Lvl3.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoicePTT_Off.png b/indra/newview/skins/classic/textures/icons/VoicePTT_Off.png
new file mode 100644
index 0000000000..533663a4fa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoicePTT_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/VoicePTT_On.png b/indra/newview/skins/classic/textures/icons/VoicePTT_On.png
new file mode 100644
index 0000000000..204c4a376e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/VoicePTT_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Web_Profile_Off.png b/indra/newview/skins/classic/textures/icons/Web_Profile_Off.png
new file mode 100644
index 0000000000..cf8f9c8f94
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Web_Profile_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/YouAreHere_Badge.png b/indra/newview/skins/classic/textures/icons/YouAreHere_Badge.png
new file mode 100644
index 0000000000..ed1805c096
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/YouAreHere_Badge.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/Zoom_Off.png b/indra/newview/skins/classic/textures/icons/Zoom_Off.png
new file mode 100644
index 0000000000..833e608201
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/Zoom_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/add_icon.png b/indra/newview/skins/classic/textures/icons/add_icon.png
new file mode 100644
index 0000000000..b5b09ae6e0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/add_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/back_arrow_off.png b/indra/newview/skins/classic/textures/icons/back_arrow_off.png
new file mode 100644
index 0000000000..c9c7bf5fec
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/back_arrow_off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/back_arrow_over.png b/indra/newview/skins/classic/textures/icons/back_arrow_over.png
new file mode 100644
index 0000000000..ee6acc2653
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/back_arrow_over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/back_arrow_press.png b/indra/newview/skins/classic/textures/icons/back_arrow_press.png
new file mode 100644
index 0000000000..9876b4eeb7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/back_arrow_press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/check_mark.png b/indra/newview/skins/classic/textures/icons/check_mark.png
new file mode 100644
index 0000000000..95ca9dbd6c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/check_mark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/collapse_to_one_line.png b/indra/newview/skins/classic/textures/icons/collapse_to_one_line.png
new file mode 100644
index 0000000000..3730924ad8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/collapse_to_one_line.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/copy_clipboard.png b/indra/newview/skins/classic/textures/icons/copy_clipboard.png
new file mode 100644
index 0000000000..9ce67d8547
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/copy_clipboard.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/delete_icon.png b/indra/newview/skins/classic/textures/icons/delete_icon.png
new file mode 100644
index 0000000000..5a80155d8b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/delete_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/edit_mine.png b/indra/newview/skins/classic/textures/icons/edit_mine.png
new file mode 100644
index 0000000000..2fb10deba2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/edit_mine.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/edit_theirs.png b/indra/newview/skins/classic/textures/icons/edit_theirs.png
new file mode 100644
index 0000000000..586c08c181
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/edit_theirs.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/emoji_picker_icon.png b/indra/newview/skins/classic/textures/icons/emoji_picker_icon.png
new file mode 100644
index 0000000000..6c1a1a3c62
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/emoji_picker_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/expand_one_liner.png b/indra/newview/skins/classic/textures/icons/expand_one_liner.png
new file mode 100644
index 0000000000..0d1a60547a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/expand_one_liner.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/file_upload.png b/indra/newview/skins/classic/textures/icons/file_upload.png
new file mode 100644
index 0000000000..78b75fdd72
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/file_upload.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/hand.png b/indra/newview/skins/classic/textures/icons/hand.png
new file mode 100644
index 0000000000..5fbdb70c2b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/hand.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/map_placeholder.png b/indra/newview/skins/classic/textures/icons/map_placeholder.png
new file mode 100644
index 0000000000..80e5deac7e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/map_placeholder.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/multi_folder_mode.png b/indra/newview/skins/classic/textures/icons/multi_folder_mode.png
new file mode 100644
index 0000000000..b363848aba
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/multi_folder_mode.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/nearby_chat_icon.png b/indra/newview/skins/classic/textures/icons/nearby_chat_icon.png
new file mode 100644
index 0000000000..c5f52f010e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/nearby_chat_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/object_icon.png b/indra/newview/skins/classic/textures/icons/object_icon.png
new file mode 100644
index 0000000000..51bf0b0649
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/object_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/paste_clipboard.png b/indra/newview/skins/classic/textures/icons/paste_clipboard.png
new file mode 100644
index 0000000000..ff8493d4ad
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/paste_clipboard.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/pop_up_caution.png b/indra/newview/skins/classic/textures/icons/pop_up_caution.png
new file mode 100644
index 0000000000..63b5cdfe83
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/pop_up_caution.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_beta.png b/indra/newview/skins/classic/textures/icons/profile_badge_beta.png
new file mode 100644
index 0000000000..95e277aab0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_beta.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_beta_lifetime.png b/indra/newview/skins/classic/textures/icons/profile_badge_beta_lifetime.png
new file mode 100644
index 0000000000..fb145901e2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_beta_lifetime.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_lifetime.png b/indra/newview/skins/classic/textures/icons/profile_badge_lifetime.png
new file mode 100644
index 0000000000..3f7fd343b3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_lifetime.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_linden.png b/indra/newview/skins/classic/textures/icons/profile_badge_linden.png
new file mode 100644
index 0000000000..6ab9fcebea
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_linden.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_pplus_lifetime.png b/indra/newview/skins/classic/textures/icons/profile_badge_pplus_lifetime.png
new file mode 100644
index 0000000000..5c68ad40ce
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_pplus_lifetime.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_badge_premium_lifetime.png b/indra/newview/skins/classic/textures/icons/profile_badge_premium_lifetime.png
new file mode 100644
index 0000000000..58957b7b96
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_badge_premium_lifetime.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off.png b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off.png
new file mode 100644
index 0000000000..331553492c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off_pressed.png b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off_pressed.png
new file mode 100644
index 0000000000..e9e9c1b626
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_off_pressed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on.png b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on.png
new file mode 100644
index 0000000000..4f5374d614
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on_pressed.png b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on_pressed.png
new file mode 100644
index 0000000000..e8a64541ee
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/profile_group_visibility_eye_on_pressed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/remove_icon.png b/indra/newview/skins/classic/textures/icons/remove_icon.png
new file mode 100644
index 0000000000..d8a45cc21c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/remove_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/see_me_online.png b/indra/newview/skins/classic/textures/icons/see_me_online.png
new file mode 100644
index 0000000000..adc37f5528
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/see_me_online.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/see_on_map.png b/indra/newview/skins/classic/textures/icons/see_on_map.png
new file mode 100644
index 0000000000..73415b9afe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/see_on_map.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/see_them_on_map.png b/indra/newview/skins/classic/textures/icons/see_them_on_map.png
new file mode 100644
index 0000000000..e5f2978dc0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/see_them_on_map.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/see_them_online.png b/indra/newview/skins/classic/textures/icons/see_them_online.png
new file mode 100644
index 0000000000..7ddd41f9a0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/see_them_online.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/single_folder_back.png b/indra/newview/skins/classic/textures/icons/single_folder_back.png
new file mode 100644
index 0000000000..b93bb2525a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/single_folder_back.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/single_folder_forward.png b/indra/newview/skins/classic/textures/icons/single_folder_forward.png
new file mode 100644
index 0000000000..12a21b2bba
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/single_folder_forward.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/single_folder_mode.png b/indra/newview/skins/classic/textures/icons/single_folder_mode.png
new file mode 100644
index 0000000000..0fc8475917
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/single_folder_mode.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/single_folder_up.png b/indra/newview/skins/classic/textures/icons/single_folder_up.png
new file mode 100644
index 0000000000..c1c8c63870
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/single_folder_up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/snapshot_icon.png b/indra/newview/skins/classic/textures/icons/snapshot_icon.png
new file mode 100644
index 0000000000..9b6ac6eeb0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/snapshot_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/texture_icon.png b/indra/newview/skins/classic/textures/icons/texture_icon.png
new file mode 100644
index 0000000000..f5c205208c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/texture_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/thumbnail_fallback_icon.png b/indra/newview/skins/classic/textures/icons/thumbnail_fallback_icon.png
new file mode 100644
index 0000000000..19629aba04
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/thumbnail_fallback_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/icons/unknown_icon.png b/indra/newview/skins/classic/textures/icons/unknown_icon.png
new file mode 100644
index 0000000000..9a4e7f8616
--- /dev/null
+++ b/indra/newview/skins/classic/textures/icons/unknown_icon.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/fps_button.png b/indra/newview/skins/classic/textures/megapahit/fps_button.png
new file mode 100644
index 0000000000..fa436a620d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/fps_button.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_blue_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_blue_bullet.png
new file mode 100644
index 0000000000..1a27570786
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_blue_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_green_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_green_bullet.png
new file mode 100644
index 0000000000..f4c28e4bc9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_green_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_help_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_help_bullet.png
new file mode 100644
index 0000000000..64c8933a78
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_help_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_info_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_info_bullet.png
new file mode 100644
index 0000000000..c90767b9ac
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_info_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_red_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_red_bullet.png
new file mode 100644
index 0000000000..aeaa52b53b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_red_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/megapahit/mp_yellow_bullet.png b/indra/newview/skins/classic/textures/megapahit/mp_yellow_bullet.png
new file mode 100644
index 0000000000..026fbaf56d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/megapahit/mp_yellow_bullet.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/model_wizard/progress_bar_bg.png b/indra/newview/skins/classic/textures/model_wizard/progress_bar_bg.png
new file mode 100644
index 0000000000..7c6920205f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/model_wizard/progress_bar_bg.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/model_wizard/progress_light.png b/indra/newview/skins/classic/textures/model_wizard/progress_light.png
new file mode 100644
index 0000000000..2e64604a4d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/model_wizard/progress_light.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Arrow_Left_Off.png b/indra/newview/skins/classic/textures/navbar/Arrow_Left_Off.png
new file mode 100644
index 0000000000..19569501fe
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Arrow_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Arrow_Right_Off.png b/indra/newview/skins/classic/textures/navbar/Arrow_Right_Off.png
new file mode 100644
index 0000000000..3648c42656
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Arrow_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/classic/textures/navbar/BuyArrow_Over.png
new file mode 100644
index 0000000000..3d9c758574
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/BuyArrow_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/classic/textures/navbar/BuyArrow_Press.png
new file mode 100644
index 0000000000..69b0d43900
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/BuyArrow_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Favorite_Link_Over.png b/indra/newview/skins/classic/textures/navbar/Favorite_Link_Over.png
new file mode 100644
index 0000000000..d4f126f969
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Favorite_Link_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Active.png
new file mode 100644
index 0000000000..fce54942d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Favorite_Star_Off.png b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Off.png
new file mode 100644
index 0000000000..82d044d817
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Over.png
new file mode 100644
index 0000000000..8cc3f02c5a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Favorite_Star_Press.png b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Press.png
new file mode 100644
index 0000000000..6670667022
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Favorite_Star_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/FileMenu_Divider.png b/indra/newview/skins/classic/textures/navbar/FileMenu_Divider.png
new file mode 100644
index 0000000000..5ab4abc5b8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/FileMenu_Divider.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Flag.png b/indra/newview/skins/classic/textures/navbar/Flag.png
new file mode 100644
index 0000000000..df53c89224
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Flag.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Help_Press.png b/indra/newview/skins/classic/textures/navbar/Help_Press.png
new file mode 100644
index 0000000000..ed3695f9d5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Help_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Home_Off.png b/indra/newview/skins/classic/textures/navbar/Home_Off.png
new file mode 100644
index 0000000000..fe3bc63b77
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Home_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Info_Off.png b/indra/newview/skins/classic/textures/navbar/Info_Off.png
new file mode 100644
index 0000000000..6399cd6715
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Info_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Info_Over.png b/indra/newview/skins/classic/textures/navbar/Info_Over.png
new file mode 100644
index 0000000000..a296d2014f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Info_Press.png b/indra/newview/skins/classic/textures/navbar/Info_Press.png
new file mode 100644
index 0000000000..2afc4a9143
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Info_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Landmarks.png b/indra/newview/skins/classic/textures/navbar/Landmarks.png
new file mode 100644
index 0000000000..2b35de913b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Landmarks.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Lock.png b/indra/newview/skins/classic/textures/navbar/Lock.png
new file mode 100644
index 0000000000..cf569d6ad2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Lock.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/NavBar_BG.png b/indra/newview/skins/classic/textures/navbar/NavBar_BG.png
new file mode 100644
index 0000000000..6a91700ae0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/NavBar_BG.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoFav_Bevel.png b/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoFav_Bevel.png
new file mode 100644
index 0000000000..c61dcde58c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoFav_Bevel.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoNav_Bevel.png b/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoNav_Bevel.png
new file mode 100644
index 0000000000..9e3da34596
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/NavBar_BG_NoNav_Bevel.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Row_Selection.png b/indra/newview/skins/classic/textures/navbar/Row_Selection.png
new file mode 100644
index 0000000000..cfc31f8d32
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Row_Selection.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/Search.png b/indra/newview/skins/classic/textures/navbar/Search.png
new file mode 100644
index 0000000000..4c29e57f7b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/Search.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/navbar/separator.png b/indra/newview/skins/classic/textures/navbar/separator.png
new file mode 100644
index 0000000000..c1d74e5a64
--- /dev/null
+++ b/indra/newview/skins/classic/textures/navbar/separator.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/Activate_Checkmark.png b/indra/newview/skins/classic/textures/taskpanel/Activate_Checkmark.png
new file mode 100644
index 0000000000..213acbe87b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/Activate_Checkmark.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Foreground.png b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Foreground.png
new file mode 100644
index 0000000000..4e59042e33
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Press.png b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Press.png
new file mode 100644
index 0000000000..be7b298bb8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Dock_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Foreground.png b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Foreground.png
new file mode 100644
index 0000000000..1e234ff09b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Press.png b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Press.png
new file mode 100644
index 0000000000..48c78b453d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/Sidebar_Icon_Undock_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Close_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Close_Off.png
new file mode 100644
index 0000000000..bc4e00c646
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Close_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Home_Selected.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Home_Selected.png
new file mode 100644
index 0000000000..293aeef5e6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Home_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Me_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Me_Off.png
new file mode 100644
index 0000000000..760db9360d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Me_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Open_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Open_Off.png
new file mode 100644
index 0000000000..4556602f58
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Open_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_People_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_People_Off.png
new file mode 100644
index 0000000000..691b600510
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_People_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Places_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Places_Off.png
new file mode 100644
index 0000000000..f5a5f7a846
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Places_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TabIcon_Things_Off.png b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Things_Off.png
new file mode 100644
index 0000000000..e56eda9802
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TabIcon_Things_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Off.png b/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Off.png
new file mode 100644
index 0000000000..4ed7a2b183
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Selected.png b/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Selected.png
new file mode 100644
index 0000000000..b3316386b9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/taskpanel/TaskPanel_Tab_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/textures.xml b/indra/newview/skins/classic/textures/textures.xml
new file mode 100644
index 0000000000..a8fc8faa44
--- /dev/null
+++ b/indra/newview/skins/classic/textures/textures.xml
@@ -0,0 +1,931 @@
+<!--
+This file contains metadata about how to load, display, and scale textures for rendering in the UI.
+Images do *NOT* have to appear in this file in order to use them as textures in the UI...simply refer
+to them by filename (relative to textures directory).
+NOTE: if you want to reuse an image file with different metadata, simply create a new texture entry
+with the same filename but different name
+
+<texture
+ name="MyTexture" (mandatory)
+ - this is the name you reference the texture by in XUI. For example, <button image_unselected="MyTexture"/>
+ file_name="images/my_texture.png" (optional)
+ - this is the path to the actual file asset, relative to the current skins "textures" directory.
+ If not supplied, the filename will be taken from the texture name itself, "MyTexture" in this case.
+ NOTE: you need to provide an extension on the filename (".png", ".tga", ".jpg") for us to decode the image properly
+ preload="true" (optional, false by default)
+ - If true, we will attempt to load the image before displaying any UI.
+ If false, we will load in the background after initializing the UI.
+ use_mips="true" (currently unused)
+ scale.left="1"
+ scale.bottom="1"
+ scale.top="15"
+ scale.right="31"
+ - Specifies the segmentation for 9-slice image scaling. Specifically, the pixel offsets from the LOWER LEFT corner
+ that define the region of the image that is stretched to make the whole image fit in the required space.
+ In this example, if the source image is 32x16 pixels, we have defined a center region that starts one pixel up
+ and to the right from the bottom left corner and extends to 31 pixels right and 15 pixels up from the bottom left
+ corner. The end result is that the image will keep a 1 pixel border all around while stretching to fit the required
+ region.
+-->
+
+<textures version="101">
+ <!-- Please add new files alphabetically to prevent merge conflicts. JC -->
+ <texture name="Accordion_ArrowClosed_Off" file_name="containers/Accordion_ArrowClosed_Off.png" preload="false" />
+ <texture name="Accordion_ArrowClosed_Press" file_name="containers/Accordion_ArrowClosed_Press.png" preload="false" />
+ <texture name="Accordion_ArrowOpened_Off" file_name="containers/Accordion_ArrowOpened_Off.png" preload="false" />
+ <texture name="Accordion_ArrowOpened_Press" file_name="containers/Accordion_ArrowOpened_Press.png" preload="false" />
+ <texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" />
+ <texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" />
+ <texture name="Accordion_Over" file_name="containers/Accordion_Over.png" preload="false" />
+ <texture name="Accordion_Selected" file_name="containers/Accordion_Selected.png" preload="false" />
+
+ <texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" />
+
+ <texture name="AddItem_Disabled" file_name="icons/AddItem_Disabled.png" preload="false" />
+ <texture name="AddItem_Off" file_name="icons/AddItem_Off.png" preload="false" />
+ <texture name="AddItem_Press" file_name="icons/AddItem_Press.png" preload="false" />
+
+ <texture name="add_payment_image_center" file_name="windows/add_payment_image_center.png" preload="true" />
+ <texture name="add_payment_image_left" file_name="windows/add_payment_image_left.png" preload="true" />
+ <texture name="add_payment_image_right" file_name="windows/add_payment_image_right.png" preload="true" />
+
+ <texture name="Arrow_Left_Off" file_name="navbar/Arrow_Left_Off.png" preload="true" />
+ <texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true" />
+
+ <texture name="Arrow_Small_Up" file_name="widgets/Arrow_Small_Up.png" preload="true" />
+ <texture name="Arrow_Small_Left" file_name="widgets/Arrow_Small_Left.png" preload="true" />
+ <texture name="Arrow_Small_Right" file_name="widgets/Arrow_Small_Right.png" preload="true" />
+
+ <texture name="Arrow_Down" file_name="widgets/Arrow_Down.png" preload="true" />
+ <texture name="Arrow_Up" file_name="widgets/Arrow_Up.png" preload="true" />
+ <texture name="Arrow_Left" file_name="widgets/Arrow_Left.png" preload="true" />
+ <texture name="Arrow_Right" file_name="widgets/Arrow_Right.png" preload="true" />
+
+ <texture name="AudioMute_Off" file_name="icons/AudioMute_Off.png" preload="false" />
+ <texture name="AudioMute_Over" file_name="icons/AudioMute_Over.png" preload="false" />
+ <texture name="VoiceMute_Off" file_name="icons/VoiceMute_Off.png" preload="false" />
+
+ <texture name="Audio_Off" file_name="icons/Audio_Off.png" preload="false" />
+ <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" />
+
+ <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />
+
+ <texture name="BackButton_Off" file_name="icons/back_arrow_off.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+ <texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+ <texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+
+ <texture name="Error_Tag_Background" file_name="widgets/Error_Tag_Background.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" />
+ <texture name="New_Tag_Background" file_name="widgets/New_Tag_Background.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" />
+ <texture name="New_Tag_Border" file_name="widgets/New_Tag_Border.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" />
+
+ <texture name="Badge_Background" file_name="widgets/Badge_Background.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="Badge_Border" file_name="widgets/Badge_Border.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
+ <texture name="Blank" file_name="Blank.png" preload="false" />
+
+ <texture name="BreadCrumbBtn_Left_Disabled" file_name="widgets/BreadCrumbBtn_Left_Disabled.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Left_Press" file_name="widgets/BreadCrumbBtn_Left_Press.png" preload="false"/>
+
+ <texture name="BreadCrumbBtn_Middle_Disabled" file_name="widgets/BreadCrumbBtn_Middle_Disabled.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Middle_Off" file_name="widgets/BreadCrumbBtn_Middle_Off.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Middle_Over" file_name="widgets/BreadCrumbBtn_Middle_Over.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Middle_Press" file_name="widgets/BreadCrumbBtn_Middle_Press.png" preload="false"/>
+
+ <texture name="BreadCrumbBtn_Right_Disabled" file_name="widgets/BreadCrumbBtn_Right_Disabled.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Right_Off" file_name="widgets/BreadCrumbBtn_Right_Off.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Right_Over" file_name="widgets/BreadCrumbBtn_Right_Over.png" preload="false"/>
+ <texture name="BreadCrumbBtn_Right_Press" file_name="widgets/BreadCrumbBtn_Right_Press.png" preload="false"/>
+
+ <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+
+ <texture name="Cam_Avatar_Off" file_name="bottomtray/Cam_Avatar_Off.png" preload="true" />
+ <texture name="Cam_FreeCam_Off" file_name="bottomtray/Cam_FreeCam_Off.png" preload="false" />
+ <texture name="Cam_Orbit_Off" file_name="bottomtray/Cam_Orbit_Off.png" preload="false" />
+ <texture name="Cam_Pan_Off" file_name="bottomtray/Cam_Pan_Off.png" preload="false" />
+
+ <texture name="Cam_Preset_Back_Off" file_name="bottomtray/Cam_Preset_Back_Off.png" preload="false" />
+ <texture name="Cam_Preset_Back_On" file_name="bottomtray/Cam_Preset_Back_On.png" preload="false" />
+ <texture name="Cam_Preset_Eye_Off" file_name="bottomtray/Cam_Preset_Eye_Off.png" preload="false" />
+ <texture name="Cam_Preset_Front_Off" file_name="bottomtray/Cam_Preset_Front_Off.png" preload="false" />
+ <texture name="Cam_Preset_Front_On" file_name="bottomtray/Cam_Preset_Front_On.png" preload="false" />
+ <texture name="Cam_Preset_Side_Off" file_name="bottomtray/Cam_Preset_Side_Off.png" preload="false" />
+ <texture name="Cam_Preset_Side_On" file_name="bottomtray/Cam_Preset_Side_On.png" preload="false" />
+
+ <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" />
+ <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" />
+ <texture name="Cam_Rotate_Center" file_name="bottomtray/Cam_Rotate_Center.png" preload="false" />
+ <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" />
+ <texture name="Cam_Tracking_Out" file_name="bottomtray/Cam_Tracking_Out.png" preload="false" />
+ <texture name="Cam_Tracking_Center" file_name="bottomtray/Cam_Tracking_Center.png" preload="false" />
+
+ <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
+ <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />
+ <texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" />
+ <texture name="Checkbox_On" file_name="widgets/Checkbox_On.png" preload="true" />
+ <texture name="Checkbox_On_Press" file_name="widgets/Checkbox_On_Press.png" preload="true" />
+ <texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" />
+ <texture name="Check_Mark" file_name="icons/check_mark.png" preload="true" />
+
+ <texture name="Checker" file_name="checker.png" preload="false" />
+
+ <texture name="Command_360_Capture_Icon" file_name="toolbar_icons/360_capture.png" preload="true" />
+ <texture name="Command_AboutLand_Icon" file_name="toolbar_icons/land.png" preload="true" />
+ <texture name="Command_Appearance_Icon" file_name="toolbar_icons/appearance.png" preload="true" />
+ <texture name="Command_Avatar_Icon" file_name="toolbar_icons/avatars.png" preload="true" />
+ <texture name="Command_Build_Icon" file_name="toolbar_icons/build.png" preload="true" />
+ <texture name="Command_Chat_Icon" file_name="toolbar_icons/chat.png" preload="true" />
+ <texture name="Command_Compass_Icon" file_name="toolbar_icons/land.png" preload="true" />
+ <texture name="Command_Destinations_Icon" file_name="toolbar_icons/destinations.png" preload="true" />
+ <texture name="Command_Gestures_Icon" file_name="toolbar_icons/gestures.png" preload="true" />
+ <texture name="Command_Grid_Status_Icon" file_name="toolbar_icons/grid_status.png" preload="true" />
+ <texture name="Command_HowTo_Icon" file_name="toolbar_icons/howto.png" preload="true" />
+ <texture name="Command_Inventory_Icon" file_name="toolbar_icons/inventory.png" preload="true" />
+ <texture name="Command_Map_Icon" file_name="toolbar_icons/map.png" preload="true" />
+ <texture name="Command_Marketplace_Icon" file_name="toolbar_icons/marketplace.png" preload="true" />
+ <texture name="Command_MktListings_Icon" file_name="toolbar_icons/mktlistings.png" preload="true" />
+ <texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" />
+ <texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" />
+ <texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" />
+ <texture name="Command_Environments_Icon" file_name="toolbar_icons/environments.png" preload="true" />
+ <texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" />
+ <texture name="Command_Performance_Icon" file_name="toolbar_icons/performance.png" preload="true" />
+ <texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" />
+ <texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" />
+ <texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" />
+ <texture name="Command_Profile_Icon" file_name="toolbar_icons/profile.png" preload="true" />
+ <texture name="Command_Report_Abuse_Icon" file_name="toolbar_icons/report_abuse.png" preload="true" />
+ <texture name="Command_Search_Icon" file_name="toolbar_icons/search.png" preload="true" />
+ <texture name="Command_Snapshot_Icon" file_name="toolbar_icons/snapshot.png" preload="true" />
+ <texture name="Command_Speak_Icon" file_name="toolbar_icons/speak.png" preload="true" />
+ <texture name="Command_View_Icon" file_name="toolbar_icons/view.png" preload="true" />
+ <texture name="Command_Voice_Icon" file_name="toolbar_icons/nearbyvoice.png" preload="true" />
+ <texture name="Command_FavoriteFolder_Icon" file_name="toolbar_icons/favorite_folder.png" preload="true" />
+ <texture name="Command_Resync_Animations" file_name="toolbar_icons/resync_animations.png" preload="true" />
+ <texture name="Caret_Bottom_Icon" file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />
+ <texture name="Caret_Right_Icon" file_name="toolbar_icons/caret_right.png" preload="true" scale.left="5" scale.top="15" scale.right="28" scale.bottom="1" />
+ <texture name="Caret_Left_Icon" file_name="toolbar_icons/caret_left.png" preload="true" scale.left="1" scale.top="15" scale.right="23" scale.bottom="1" />
+
+ <texture name="ComboButton_Disabled" file_name="widgets/ComboButton_Disabled.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_UpSelected" file_name="widgets/ComboButton_UpSelected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+
+ <texture name="Container" file_name="containers/Container.png" preload="false" />
+
+ <texture name="Conv_toolbar_add_person" file_name="icons/Conv_toolbar_add_person.png" preload="false" />
+ <texture name="Conv_toolbar_arrow_ne" file_name="icons/Conv_toolbar_arrow_ne.png" preload="false" />
+ <texture name="Conv_toolbar_arrow_sw" file_name="icons/Conv_toolbar_arrow_sw.png" preload="false" />
+ <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" />
+ <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" />
+ <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" />
+ <texture name="Conv_collapse_to_one_line" file_name="icons/collapse_to_one_line.png" preload="false" />
+ <texture name="Conv_expand_one_line" file_name="icons/expand_one_liner.png" preload="false" />
+ <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" />
+ <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" />
+ <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" />
+ <texture name="Conv_toolbar_plus" file_name="icons/Conv_toolbar_plus.png" preload="false" />
+ <texture name="Conv_toolbar_sort" file_name="icons/Conv_toolbar_sort.png" preload="false" />
+ <texture name="Conv_log_inbox" file_name="icons/Conv_log_inbox.png" preload="false" />
+
+ <texture name="Copy" file_name="icons/Copy.png" preload="false" />
+ <texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" />
+
+ <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" />
+
+ <texture name="ChatBarHandle" file_name="bottomtray/ChatBarHandle.png" preload="false" />
+ <texture name="DownArrow" file_name="bottomtray/DownArrow.png" preload="false" />
+ <texture name="DownArrow_Off" file_name="icons/DownArrow_Off.png" preload="false" />
+ <texture name="Dragbar" file_name="windows/Dragbar.png" preload="false" scale.left="35" scale.top="5" scale.right="29" scale.bottom="5" />
+
+ <texture name="DropDown_Disabled" file_name="widgets/DropDown_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="99" scale.bottom="4" />
+ <texture name="DropDown_Press" file_name="widgets/DropDown_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="99" scale.bottom="4" />
+ <texture name="DropDown_On" file_name="widgets/DropDown_On.png" preload="true" scale.left="4" scale.top="19" scale.right="99" scale.bottom="4" />
+ <texture name="DropDown_Off" file_name="widgets/DropDown_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="99" scale.bottom="4" />
+
+ <texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" />
+
+ <texture name="Emoji_Picker_Icon" file_name="icons/emoji_picker_icon.png" preload="true" />
+ <texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />
+ <texture name="Edit_Wrench" file_name="icons/Edit_Wrench.png" preload="false" />
+
+ <texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" />
+
+ <texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" />
+ <texture name="Presets_Icon_Graphic" file_name="icons/Presets_Icon_Graphic.png" preload="true" />
+ <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />
+ <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />
+ <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
+ <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
+ <texture name="Favorite_Link_Over" file_name="navbar/Favorite_Link_Over.png" preload="false" />
+
+
+ <texture name="Flag" file_name="navbar/Flag.png" preload="false" />
+
+ <texture name="Flyout_Left" file_name="windows/Flyout_Left.png" preload="false" />
+ <texture name="Flyout_Pointer" file_name="windows/Flyout_Pointer.png" preload="false" />
+ <texture name="Flyout_Right" file_name="windows/Flyout_Right.png" preload="false" />
+
+ <texture name="Folder_Arrow" file_name="folder_arrow.tga" preload="false" />
+ <texture name="ForSale_Badge" file_name="icons/ForSale_Badge.png" preload="false" />
+ <texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
+ <texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" />
+
+ <texture name="Generic_Experience" file_name="Blank.png" preload="false" />
+ <texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" />
+ <texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" />
+ <texture name="icon_group.tga" file_name="icons/Generic_Group.png" preload="false" />
+ <texture name="Generic_Object_Small" file_name="icons/Generic_Object_Small.png" preload="false" />
+ <texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" />
+ <texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" />
+
+ <texture name="Group_Notices" file_name="icons/Group_Notices.png" preload="false" />
+
+ <texture name="Hand" file_name="icons/hand.png" preload="false" />
+
+ <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" />
+
+ <texture name="Hierarchy_View_Disabled" file_name="icons/Hierarchy_View_Disabled.png" preload="false" />
+ <texture name="Hierarchy_View_On" file_name="icons/Hierarchy_View_On.png" preload="false" />
+
+
+ <texture name="Home_Off" file_name="navbar/Home_Off.png" preload="false" />
+ <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png" scale.left="8" scale.right="120" scale.bottom="1" scale.top="6" scale_type="scale_outer"/>
+
+ <texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" />
+ <texture name="Icon_Close_Press" file_name="windows/Icon_Close_Press.png" preload="true" />
+ <texture name="Icon_Close_Toast" file_name="windows/Icon_Close_Toast.png" preload="true" />
+
+ <texture name="Icon_Copy" file_name="icons/copy_clipboard.png" preload="true" />
+
+ <texture name="Icon_Delete" file_name="icons/delete_icon.png" preload="true" />
+
+ <texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
+ <texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
+
+ <texture name="Icon_File_Upload" file_name="icons/file_upload.png" preload="true" />
+
+ <texture name="Icon_For_Sale" file_name="icons/Icon_For_Sale.png" preload="false" />
+
+ <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
+ <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" />
+ <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="false" />
+ <texture name="Icon_Gear" file_name="windows/Icon_Gear.png" preload="false" />
+
+ <texture name="Icon_Help_Foreground" file_name="windows/Icon_Help_Foreground.png" preload="true" />
+ <texture name="Icon_Help_Press" file_name="windows/Icon_Help_Press.png" preload="true" />
+
+ <texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" />
+ <texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" />
+
+ <texture name="Icon_Paste" file_name="icons/paste_clipboard.png" preload="true" />
+
+ <texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" />
+ <texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" />
+
+ <texture name="Icon_Snapshot" file_name="icons/snapshot_icon.png" preload="true" />
+
+ <texture name="Icon_Use_Texture" file_name="icons/texture_icon.png" preload="true" />
+
+ <texture name="Info" file_name="icons/Info.png" preload="false" />
+ <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
+ <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+ <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" />
+ <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
+
+ <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+ <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" />
+ <texture name="Inspector_I" file_name="windows/Inspector_I.png" preload="false" />
+
+ <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" />
+ <texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" />
+ <texture name="Inv_BodyShape" file_name="icons/Inv_BodyShape.png" preload="false" />
+ <texture name="Inv_CallingCard" file_name="icons/Inv_CallingCard.png" preload="false" />
+ <texture name="Inv_Clothing" file_name="icons/Inv_Clothing.png" preload="false" />
+ <texture name="Inv_Eye" file_name="icons/Inv_Eye.png" preload="false" />
+ <texture name="Inv_Favorite_Star_Content" file_name="icons/Inv_Favorite_Star_Content.png" preload="false" />
+ <texture name="Inv_Favorite_Star_Full" file_name="icons/Inv_Favorite_Star_Full.png" preload="false" />
+ <texture name="Inv_FolderClosed" file_name="icons/Inv_FolderClosed.png" preload="false" />
+ <texture name="Inv_FolderOpen" file_name="icons/Inv_FolderOpen.png" preload="false" />
+ <texture name="Inv_Gesture" file_name="icons/Inv_Gesture.png" preload="false" />
+ <texture name="Inv_Gloves" file_name="icons/Inv_Gloves.png" preload="false" />
+ <texture name="Inv_Hair" file_name="icons/Inv_Hair.png" preload="false" />
+ <texture name="Inv_LinkItem" file_name="icons/Inv_LinkItem.png" preload="false" />
+ <texture name="Inv_LinkFolder" file_name="icons/Inv_LinkFolder.png" preload="false" />
+ <texture name="Inv_Jacket" file_name="icons/Inv_Jacket.png" preload="false" />
+ <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" />
+ <texture name="Inv_LookFolderClosed" file_name="icons/Inv_LookFolderClosed.png" preload="false" />
+ <texture name="Inv_LostClosed" file_name="icons/Inv_LostClosed.png" preload="false" />
+ <texture name="Inv_LostOpen" file_name="icons/Inv_LostOpen.png" preload="false" />
+ <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
+ <texture name="Inv_Material" file_name="icons/Inv_Material.png" preload="false" />
+ <texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" />
+ <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
+ <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
+ <texture name="Inv_Object_Multi" file_name="icons/Inv_Object_Multi.png" preload="false" />
+ <texture name="Inv_Pants" file_name="icons/Inv_Pants.png" preload="false" />
+ <texture name="Inv_Script" file_name="icons/Inv_Script.png" preload="false" />
+ <texture name="Inv_Shirt" file_name="icons/Inv_Shirt.png" preload="false" />
+ <texture name="Inv_Shoe" file_name="icons/Inv_Shoe.png" preload="false" />
+ <texture name="Inv_Skin" file_name="icons/Inv_Skin.png" preload="false" />
+ <texture name="Inv_Skirt" file_name="icons/Inv_Skirt.png" preload="false" />
+ <texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" />
+ <texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" />
+ <texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" />
+ <texture name="Inv_StockFolderClosed" file_name="icons/Inv_StockFolderClosed.png" preload="false" />
+ <texture name="Inv_StockFolderOpen" file_name="icons/Inv_StockFolderOpen.png" preload="false" />
+ <texture name="Inv_SysClosed" file_name="icons/Inv_SysClosed.png" preload="false" />
+ <texture name="Inv_SysOpen" file_name="icons/Inv_SysOpen.png" preload="false" />
+ <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
+ <texture name="Inv_Universal" file_name="icons/Inv_Universal.png" preload="false" />
+ <texture name="Inv_Physics" file_name="icons/Inv_Physics.png" preload="false" />
+ <texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
+ <texture name="Inv_TrashClosed" file_name="icons/Inv_TrashClosed.png" preload="false" />
+ <texture name="Inv_TrashOpen" file_name="icons/Inv_TrashOpen.png" preload="false" />
+ <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
+ <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />
+ <texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" />
+ <texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" />
+ <texture name="Inv_SettingsSky" file_name="icons/Inv_SettingsSky.png" preload="false" />
+ <texture name="Inv_SettingsWater" file_name="icons/Inv_SettingsWater.png" preload="false" />
+ <texture name="Inv_SettingsDay" file_name="icons/Inv_SettingsDay.png" preload="false" />
+
+ <texture name="Inv_Invalid" file_name="icons/Inv_Invalid.png" preload="false" />
+ <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
+ <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
+ <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
+
+ <texture name="Inv_Toolbar_SearchVisibility" file_name="icons/Inv_Toolbar_SearchVisibility.png" preload="false" />
+
+ <texture name="Landmarks_overlay" file_name="navbar/Landmarks.png" preload="false" />
+
+ <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
+ <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
+
+ <texture name="ListItem_Select" file_name="widgets/ListItem_Select.png" preload="true" scale.left="2" scale.bottom="2" scale.top="22" scale.right="278" />
+ <texture name="ListItem_Over" file_name="widgets/ListItem_Over.png" preload="true" scale.left="2" scale.bottom="2" scale.top="22" scale.right="278" />
+
+ <texture name="List_View_Disabled" file_name="icons/List_View_Disabled.png" preload="false" />
+ <texture name="List_View_On" file_name="icons/List_View_On.png" preload="false" />
+
+ <texture name="Lock" file_name="icons/Lock.png" preload="false" />
+ <texture name="Lock2" file_name="navbar/Lock.png" preload="false" />
+
+ <texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
+
+ <texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" />
+
+ <texture name="Marketplace_Dropzone_Background" file_name="widgets/Marketplace_Dropzone_Background.png" preload="true" />
+ <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
+ <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
+
+ <texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
+
+ <texture name="MinusItem_Disabled" file_name="icons/MinusItem_Disabled.png" preload="false" />
+ <texture name="MinusItem_Off" file_name="icons/MinusItem_Off.png" preload="false" />
+ <texture name="MinusItem_Press" file_name="icons/MinusItem_Press.png" preload="false" />
+
+ <texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" />
+
+ <texture name="ModelImport_Status_Good" file_name="green_checkmark.png" preload="false"/>
+ <texture name="ModelImport_Status_Warning" file_name="lag_status_warning.tga" preload="false"/>
+ <texture name="ModelImport_Status_Error" file_name="red_x.png" preload="false"/>
+
+ <texture name="MouseLook_View_Off" file_name="bottomtray/Mouselook_View_Off.png" preload="false" />
+ <texture name="MouseLook_View_On" file_name="bottomtray/Mouselook_View_On.png" preload="false" />
+
+ <texture name="Move_Fly_Off" file_name="bottomtray/Move_Fly_Off.png" preload="false" />
+ <texture name="Move_Run_Off" file_name="bottomtray/Move_Run_Off.png" preload="false" />
+ <texture name="Move_Walk_Off" file_name="bottomtray/Move_Walk_Off.png" preload="false" />
+ <texture name="Movement_Backward_Off" file_name="bottomtray/Movement_Backward_Off.png" preload="false" />
+ <texture name="Movement_Backward_On" file_name="bottomtray/Movement_Backward_On.png" preload="false" />
+ <texture name="Movement_Down_Off" file_name="bottomtray/Movement_Down_Off.png" preload="false" />
+ <texture name="Movement_Down_On" file_name="bottomtray/Movement_Down_On.png" preload="false" />
+ <texture name="Movement_Forward_Off" file_name="bottomtray/Movement_Forward_Off.png" preload="false" />
+ <texture name="Movement_Forward_On" file_name="bottomtray/Movement_Forward_On.png" preload="false" />
+ <texture name="Movement_Left_Off" file_name="bottomtray/Movement_Left_Off.png" preload="false" />
+ <texture name="Movement_Left_On" file_name="bottomtray/Movement_Left_On.png" preload="false" />
+ <texture name="Movement_Right_Off" file_name="bottomtray/Movement_Right_Off.png" preload="false" />
+ <texture name="Movement_Right_On" file_name="bottomtray/Movement_Right_On.png" preload="false" />
+ <texture name="Movement_TurnLeft_Off" file_name="bottomtray/Movement_TurnLeft_Off.png" preload="false" />
+ <texture name="Movement_TurnLeft_On" file_name="bottomtray/Movement_TurnLeft_On.png" preload="false" />
+ <texture name="Movement_TurnRight_Off" file_name="bottomtray/Movement_TurnRight_Off.png" preload="false" />
+ <texture name="Movement_TurnRight_On" file_name="bottomtray/Movement_TurnRight_On.png" preload="false" />
+ <texture name="Movement_Up_Off" file_name="bottomtray/Movement_Up_Off.png" preload="false" />
+ <texture name="Movement_Up_On" file_name="bottomtray/Movement_Up_On.png" preload="false" />
+
+ <texture name="NavBar_BG" file_name="navbar/NavBar_BG.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="NavBar_BG_NoFav_Bevel" file_name="navbar/NavBar_BG_NoFav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="NavBar_BG_NoNav_Bevel" file_name="navbar/NavBar_BG_NoNav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+
+ <texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" />
+
+ <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" />
+
+ <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
+ <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
+
+ <texture name="Object_Cone" file_name="build/Object_Cone.png" preload="false" />
+ <texture name="Object_Cone_Selected" file_name="build/Object_Cone_Selected.png" preload="false" />
+ <texture name="Object_Cube" file_name="build/Object_Cube.png" preload="false" />
+ <texture name="Object_Cube_Selected" file_name="build/Object_Cube_Selected.png" preload="false" />
+ <texture name="Object_Cylinder" file_name="build/Object_Cylinder.png" preload="false" />
+ <texture name="Object_Cylinder_Selected" file_name="build/Object_Cylinder_Selected.png" preload="false" />
+ <texture name="Object_Grass" file_name="build/Object_Grass.png" preload="false" />
+ <texture name="Object_Grass_Selected" file_name="build/Object_Grass_Selected.png" preload="false" />
+ <texture name="Object_Hemi_Cone" file_name="build/Object_Hemi_Cone.png" preload="false" />
+ <texture name="Object_Hemi_Cone_Selected" file_name="build/Object_Hemi_Cone_Selected.png" preload="false" />
+ <texture name="Object_Hemi_Cylinder" file_name="build/Object_Hemi_Cylinder.png" preload="false" />
+ <texture name="Object_Hemi_Cylinder_Selected" file_name="build/Object_Hemi_Cylinder_Selected.png" preload="false" />
+ <texture name="Object_Hemi_Sphere" file_name="build/Object_Hemi_Sphere.png" preload="false" />
+ <texture name="Object_Hemi_Sphere_Selected" file_name="build/Object_Hemi_Sphere_Selected.png" preload="false" />
+ <texture name="Object_Prism" file_name="build/Object_Prism.png" preload="false" />
+ <texture name="Object_Prism_Selected" file_name="build/Object_Prism_Selected.png" preload="false" />
+ <texture name="Object_Pyramid" file_name="build/Object_Pyramid.png" preload="false" />
+ <texture name="Object_Pyramid_Selected" file_name="build/Object_Pyramid_Selected.png" preload="false" />
+ <texture name="Object_Ring" file_name="build/Object_Ring.png" preload="false" />
+ <texture name="Object_Ring_Selected" file_name="build/Object_Ring_Selected.png" preload="false" />
+ <texture name="Object_Sphere" file_name="build/Object_Sphere.png" preload="false" />
+ <texture name="Object_Sphere_Selected" file_name="build/Object_Sphere_Selected.png" preload="false" />
+ <texture name="Object_Tetrahedron" file_name="build/Object_Tetrahedron.png" preload="false" />
+ <texture name="Object_Tetrahedron_Selected" file_name="build/Object_Tetrahedron_Selected.png" preload="false" />
+ <texture name="Object_Torus" file_name="build/Object_Torus.png" preload="false" />
+ <texture name="Object_Torus_Selected" file_name="build/Object_Torus_Selected.png" preload="false" />
+ <texture name="Object_Tree" file_name="build/Object_Tree.png" preload="false" />
+ <texture name="Object_Tree_Selected" file_name="build/Object_Tree_Selected.png" preload="false" />
+ <texture name="Object_Tube" file_name="build/Object_Tube.png" preload="false" />
+ <texture name="Object_Tube_Selected" file_name="build/Object_Tube_Selected.png" preload="false" />
+
+ <texture name="Object_View_Off" file_name="bottomtray/Object_View_Off.png" preload="false" />
+ <texture name="Object_View_On" file_name="bottomtray/Object_View_On.png" preload="false" />
+
+ <texture name="OptionsMenu_Disabled" file_name="icons/OptionsMenu_Disabled.png" preload="false" />
+ <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
+ <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
+
+ <texture name="ClipboardSmallMenu_Disabled" file_name="icons/ClipboardSmallMenu_Disabled.png" preload="false" />
+ <texture name="ClipboardSmallMenu_Off" file_name="icons/ClipboardSmallMenu_Off.png" preload="false" />
+ <texture name="ClipboardSmallMenu_Press" file_name="icons/ClipboardSmallMenu_Press.png" preload="false" />
+ <texture name="ClipboardMenu_Disabled" file_name="icons/ClipboardMenu_Disabled.png" preload="false" />
+ <texture name="ClipboardMenu_Off" file_name="icons/ClipboardMenu_Off.png" preload="false" />
+ <texture name="ClipboardMenu_Press" file_name="icons/ClipboardMenu_Press.png" preload="false" />
+
+ <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" />
+ <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" />
+ <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" />
+
+ <texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" />
+
+ <texture name="Parcel_Exp_Color" file_name="icons/Parcel_Exp_Color.png" preload="false" />
+
+ <texture name="Parcel_Build_Dark" file_name="icons/Parcel_Build_Dark.png" preload="false" />
+ <texture name="Parcel_BuildNo_Dark" file_name="icons/Parcel_BuildNo_Dark.png" preload="false" />
+ <texture name="Parcel_Damage_Dark" file_name="icons/Parcel_Damage_Dark.png" preload="false" />
+ <texture name="Parcel_DamageNo_Dark" file_name="icons/Parcel_DamageNo_Dark.png" preload="false" />
+ <texture name="Parcel_Fly_Dark" file_name="icons/Parcel_Fly_Dark.png" preload="false" />
+ <texture name="Parcel_FlyNo_Dark" file_name="icons/Parcel_FlyNo_Dark.png" preload="false" />
+ <texture name="Parcel_Health_Dark" file_name="icons/Parcel_Health_Dark.png" preload="false" />
+ <texture name="Parcel_M_Dark" file_name="icons/Parcel_M_Dark.png" preload="false" />
+ <texture name="Parcel_PG_Dark" file_name="icons/Parcel_PG_Dark.png" preload="false" />
+ <texture name="Parcel_Push_Dark" file_name="icons/Parcel_Push_Dark.png" preload="false" />
+ <texture name="Parcel_PushNo_Dark" file_name="icons/Parcel_PushNo_Dark.png" preload="false" />
+ <texture name="Parcel_R_Dark" file_name="icons/Parcel_R_Dark.png" preload="false" />
+ <texture name="Parcel_Scripts_Dark" file_name="icons/Parcel_Scripts_Dark.png" preload="false" />
+ <texture name="Parcel_ScriptsNo_Dark" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />
+ <texture name="Parcel_Voice_Dark" file_name="icons/Parcel_Voice_Dark.png" preload="false" />
+ <texture name="Parcel_VoiceNo_Dark" file_name="icons/Parcel_VoiceNo_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOff_Dark" file_name="icons/Parcel_SeeAVsOff_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOn_Dark" file_name="icons/Parcel_SeeAVsOn_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOff_Light" file_name="icons/Parcel_SeeAVsOff_Light.png" preload="false" />
+ <texture name="Parcel_SeeAVsOn_Light" file_name="icons/Parcel_SeeAVsOn_Light.png" preload="false" />
+
+ <texture name="Parcel_BuildNo_Light" file_name="icons/Parcel_BuildNo_Light.png" preload="false" />
+ <texture name="Parcel_FlyNo_Light" file_name="icons/Parcel_FlyNo_Light.png" preload="false" />
+ <texture name="Parcel_ForSale_Light" file_name="icons/Parcel_ForSale_Light.png" preload="false" />
+ <texture name="Parcel_M_Light" file_name="icons/Parcel_M_Light.png" preload="false" />
+ <texture name="Parcel_PG_Light" file_name="icons/Parcel_PG_Light.png" preload="false" />
+ <texture name="Parcel_PushNo_Light" file_name="icons/Parcel_PushNo_Light.png" preload="false" />
+ <texture name="Parcel_R_Light" file_name="icons/Parcel_R_Light.png" preload="false" />
+ <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />
+ <texture name="Parcel_Voice_Light" file_name="icons/Parcel_Voice_Light.png" preload="false" />
+ <texture name="Parcel_VoiceNo_Light" file_name="icons/Parcel_VoiceNo_Light.png" preload="false" />
+
+ <texture name="Pathfinding_Dirty" file_name="icons/Pathfinding_Dirty.png" preload="false" />
+ <texture name="Pathfinding_Disabled" file_name="icons/Pathfinding_Disabled.png" preload="false" />
+
+ <texture name="Pause_Off" file_name="icons/Pause_Off.png" preload="false" />
+ <texture name="Pause_Over" file_name="icons/Pause_Over.png" preload="false" />
+ <texture name="Pause_Press" file_name="icons/Pause_Press.png" preload="false" />
+ <texture name="Person_Check" file_name="icons/Person_Check.png" preload="false" />
+ <texture name="Person_Star" file_name="icons/Person_Star.png" preload="false" />
+
+ <texture name="Permission_Visible_Online" file_name="icons/see_me_online.png" preload="false" />
+ <texture name="Permission_Visible_Map" file_name="icons/see_on_map.png" preload="false" />
+ <texture name="Permission_Edit_Objects_Mine" file_name="icons/edit_mine.png" preload="false" />
+ <texture name="Permission_Edit_Objects_Theirs" file_name="icons/edit_theirs.png" preload="false" />
+
+ <texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" />
+ <texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" />
+ <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />
+
+ <texture name="Profile_Badge_Beta" file_name="icons/profile_badge_beta.png" preload="true"/>
+ <texture name="Profile_Badge_Beta_Lifetime" file_name="icons/profile_badge_beta_lifetime.png" preload="true"/>
+ <texture name="Profile_Badge_Lifetime" file_name="icons/profile_badge_lifetime.png" preload="true"/>
+ <texture name="Profile_Badge_Linden" file_name="icons/profile_badge_linden.png" preload="true"/>
+ <texture name="Profile_Badge_Pplus_Lifetime" file_name="icons/profile_badge_pplus_lifetime.png" preload="true"/>
+ <texture name="Profile_Badge_Premium_Lifetime" file_name="icons/profile_badge_premium_lifetime.png" preload="true"/>
+ <texture name="Profile_Group_Visibility_Off" file_name="icons/profile_group_visibility_eye_off.png" preload="true"/>
+ <texture name="Profile_Group_Visibility_Off_Pressed" file_name="icons/profile_group_visibility_eye_off_pressed.png" preload="true"/>
+ <texture name="Profile_Group_Visibility_On" file_name="icons/profile_group_visibility_eye_on.png" preload="true"/>
+ <texture name="Profile_Group_Visibility_On_Pressed" file_name="icons/profile_group_visibility_eye_on_pressed.png" preload="true"/>
+ <texture name="Profile_Friend_Offline" file_name="icons/Profile_Friend_Offline.png" preload="true"/>
+ <texture name="Profile_Friend_Online" file_name="icons/Profile_Friend_Online.png" preload="true"/>
+ <texture name="Profile_Perm_Find_Disabled" file_name="icons/Profile_Perm_Find_Disabled.png" preload="true"/>
+ <texture name="Profile_Perm_Find_Enabled" file_name="icons/Profile_Perm_Find_Enabled.png" preload="true"/>
+ <texture name="Profile_Perm_Objects_Disabled" file_name="icons/Profile_Perm_Objects_Disabled.png" preload="true"/>
+ <texture name="Profile_Perm_Objects_Enabled" file_name="icons/Profile_Perm_Objects_Enabled.png" preload="true"/>
+ <texture name="Profile_Perm_Online_Disabled" file_name="icons/Profile_Perm_Online_Disabled.png" preload="true"/>
+ <texture name="Profile_Perm_Online_Enabled" file_name="icons/Profile_Perm_Online_Enabled.png" preload="true"/>
+
+ <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
+ <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
+ <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
+
+ <texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Off" file_name="widgets/PushButton_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_On" file_name="widgets/PushButton_On.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_On_Selected" file_name="widgets/PushButton_On_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Over" file_name="widgets/PushButton_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Press" file_name="widgets/PushButton_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected" file_name="widgets/PushButton_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected_Press" file_name="widgets/PushButton_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected_Disabled" file_name="widgets/PushButton_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+
+ <texture name="PushButton_Login" file_name="widgets/PushButton_Login.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Login_Over" file_name="widgets/PushButton_Login_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Login_Pressed" file_name="widgets/PushButton_Login_Pressed.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+
+
+ <texture name="RadioButton_Press" file_name="widgets/RadioButton_Press.png" preload="true" />
+ <texture name="RadioButton_On_Press" file_name="widgets/RadioButton_On_Press.png" preload="true" />
+ <texture name="RadioButton_Off" file_name="widgets/RadioButton_Off.png" preload="true" />
+ <texture name="RadioButton_On" file_name="widgets/RadioButton_On.png" preload="true" />
+ <texture name="RadioButton_Disabled" file_name="widgets/RadioButton_Disabled.png" preload="true" />
+ <texture name="RadioButton_On_Disabled" file_name="widgets/RadioButton_On_Disabled.png" preload="true" />
+
+
+ <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="true" />
+
+ <texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
+
+ <texture name="Rounded_Rect" file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="26" scale.right="58" scale.bottom="6" />
+ <texture name="Rounded_Rect_Top" file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="8" scale.right="58" scale.bottom="0" clip.left="0" clip.right="64" clip.bottom="16" clip.top="32" />
+ <texture name="Rounded_Rect_Bottom" file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="16" scale.right="58" scale.bottom="8" clip.left="0" clip.right="64" clip.bottom="0" clip.top="16" />
+ <texture name="Rounded_Rect_Left" file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="26" scale.right="32" scale.bottom="6" clip.left="0" clip.right="32" clip.bottom="0" clip.top="32" />
+ <texture name="Rounded_Rect_Right" file_name="Rounded_Rect.png" preload="true" scale.left="0" scale.top="26" scale.right="26" scale.bottom="6" clip.left="32" clip.right="64" clip.bottom="0" clip.top="32" />
+ <texture name="Rounded_Square" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
+ <texture name="Row_Selection" file_name="navbar/Row_Selection.png" preload="false" />
+
+ <texture name="ScrollArrow_Down" file_name="widgets/ScrollArrow_Down.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Left" file_name="widgets/ScrollArrow_Left.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Right" file_name="widgets/ScrollArrow_Right.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Up" file_name="widgets/ScrollArrow_Up.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+
+ <texture name="ScrollThumb_Horiz" file_name="widgets/ScrollThumb_Horiz.png" preload="true" scale.left="4" scale.top="0" scale.bottom="0" scale.right="2" />
+ <texture name="ScrollThumb_Vert" file_name="widgets/ScrollThumb_Vert.png" preload="true" scale.left="4" scale.top="53" scale.bottom="10" scale.right="4" />
+ <texture name="ScrollTrack_Vert" file_name="widgets/ScrollTrack_Vert.png" preload="true" scale.left="2" scale.top="40" scale.bottom="13" scale.right="0" />
+ <texture name="ScrollTrack_Horiz" file_name="widgets/ScrollTrack_Horiz.png" preload="true" scale.left="4" scale.top="0" scale.bottom="0" scale.right="2" />
+
+
+ <texture name="Search" file_name="navbar/Search.png" preload="false" />
+
+ <texture name="Search_Icon" file_name="icons/Search_Icon.png" preload="false" />
+
+ <texture name="SegmentedBtn_Left_Off" file_name="widgets/SegmentedBtn_Left_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Over" file_name="widgets/SegmentedBtn_Left_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Press" file_name="widgets/SegmentedBtn_Left_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Disabled" file_name="widgets/SegmentedBtn_Left_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected" file_name="widgets/SegmentedBtn_Left_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Over" file_name="widgets/SegmentedBtn_Left_Selected_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Press" file_name="widgets/SegmentedBtn_Left_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Disabled" file_name="widgets/SegmentedBtn_Left_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="SegmentedBtn_Middle_Disabled" file_name="widgets/SegmentedBtn_Middle_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected" file_name="widgets/SegmentedBtn_Middle_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected_Press" file_name="widgets/SegmentedBtn_Middle_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected_Disabled" file_name="widgets/SegmentedBtn_Middle_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="SegmentedBtn_Right_Off" file_name="widgets/SegmentedBtn_Right_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Over" file_name="widgets/SegmentedBtn_Right_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Press" file_name="widgets/SegmentedBtn_Right_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Disabled" file_name="widgets/SegmentedBtn_Right_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected" file_name="widgets/SegmentedBtn_Right_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected_Press" file_name="widgets/SegmentedBtn_Right_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected_Disabled" file_name="widgets/SegmentedBtn_Right_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="Shirt_Large" file_name="icons/Shirt_Large.png" preload="false" />
+
+ <texture name="Sidebar_Icon_Dock_Foreground" file_name="taskpanel/Sidebar_Icon_Dock_Foreground.png" preload="false" />
+ <texture name="Sidebar_Icon_Dock_Press" file_name="taskpanel/Sidebar_Icon_Dock_Press.png" preload="false" />
+ <texture name="Sidebar_Icon_Undock_Foreground" file_name="taskpanel/Sidebar_Icon_Undock_Foreground.png" preload="false" />
+ <texture name="Sidebar_Icon_Undock_Press" file_name="taskpanel/Sidebar_Icon_Undock_Press.png" preload="false" />
+
+ <texture name="Shop" file_name="icons/Shop.png" preload="false" />
+
+ <texture name="SkipBackward_Off" file_name="icons/SkipBackward_Off.png" preload="false" />
+ <texture name="SkipForward_Off" file_name="icons/SkipForward_Off.png" preload="false" />
+
+ <texture name="SliderTrack_Horiz" file_name="widgets/SliderTrack_Horiz.png" scale.left="4" scale.top="4" scale.right="100" scale.bottom="2" />
+ <texture name="SliderTrack_Vert" file_name="widgets/SliderTrack_Vert.png" scale.left="2" scale.top="100" scale.right="4" scale.bottom="4" />
+ <texture name="SliderThumb_Off" file_name="widgets/SliderThumb_Off.png" />
+ <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />
+ <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" />
+
+ <texture name="SL_Logo" file_name="icons/MP_Logo.png" preload="true" />
+ <texture name="OBJECT_Icon" file_name="icons/object_icon.png" preload="true" />
+ <texture name="Unknown_Icon" file_name="icons/unknown_icon.png" preload="true" />
+
+ <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="Snapshot_Download" file_name="snapshot_download.png" preload="false" />
+ <texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" />
+ <texture name="Snapshot_Inventory" file_name="toolbar_icons/inventory.png" preload="false" />
+ <texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" />
+ <texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" />
+
+ <texture name="login_mp_logo" file_name="windows/login_mp_logo.png" preload="true" />
+ <texture name="login_mp_logo_small" file_name="windows/login_mp_logo_small.png" preload="true" />
+ <texture name="first_login_image" file_name="windows/first_login_image.jpg" preload="true" />
+
+ <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="false" />
+ <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="false" />
+ <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" />
+ <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" />
+
+ <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="true" />
+ <texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
+ <texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
+
+ <texture name="Sync_Disabled" file_name="icons/Sync_Disabled.png" preload="true" />
+ <texture name="Sync_Enabled" file_name="icons/Sync_Enabled.png" preload="true" />
+ <texture name="Sync_Progress_1" file_name="icons/Sync_Progress_1.png" preload="true" />
+ <texture name="Sync_Progress_2" file_name="icons/Sync_Progress_2.png" preload="true" />
+ <texture name="Sync_Progress_3" file_name="icons/Sync_Progress_3.png" preload="true" />
+ <texture name="Sync_Progress_4" file_name="icons/Sync_Progress_4.png" preload="true" />
+ <texture name="Sync_Progress_5" file_name="icons/Sync_Progress_5.png" preload="true" />
+ <texture name="Sync_Progress_6" file_name="icons/Sync_Progress_6.png" preload="true" />
+
+ <texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
+ <texture name="TabIcon_Home_Selected" file_name="taskpanel/TabIcon_Home_Selected.png" preload="false" />
+ <texture name="TabIcon_Me_Off" file_name="taskpanel/TabIcon_Me_Off.png" preload="false" />
+ <texture name="TabIcon_Open_Off" file_name="taskpanel/TabIcon_Open_Off.png" preload="false" />
+ <texture name="TabIcon_People_Off" file_name="taskpanel/TabIcon_People_Off.png" preload="false" />
+ <texture name="TabIcon_Places_Off" file_name="taskpanel/TabIcon_Places_Off.png" preload="false" />
+ <texture name="TabIcon_Things_Off" file_name="taskpanel/TabIcon_Things_Off.png" preload="false" />
+
+ <texture name="TabTop_Right_Off" file_name="containers/TabTop_Right_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Right_Selected" file_name="containers/TabTop_Right_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Right_Flashing" file_name="containers/TabTop_Right_Flashing.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Middle_Off" file_name="containers/TabTop_Middle_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="TabTop_Middle_Selected" file_name="containers/TabTop_Middle_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
+ <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
+
+ <texture name="TaskPanel_Tab_Off" file_name="taskpanel/TaskPanel_Tab_Off.png" preload="false" scale.left="4" scale.top="29" scale.right="36" scale.bottom="4" />
+ <texture name="TaskPanel_Tab_Selected" file_name="taskpanel/TaskPanel_Tab_Selected.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" />
+
+ <texture name="TextField_Search_Disabled" file_name="widgets/TextField_Search_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Off" file_name="widgets/TextField_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Active" file_name="widgets/TextField_Search_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Highlight" file_name="widgets/TextField_Search_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
+ <texture name="Thumbnail_Fallback" file_name="icons/thumbnail_fallback_icon.png" preload="true" />
+
+ <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
+ <texture name="Toast_Background" file_name="windows/Toast_Background.png" preload="true"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+ <texture name="Toast_Over" file_name="windows/Toast_Over.png" preload="true"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+
+ <texture name="Tool_Create" file_name="build/Tool_Create.png" preload="false" />
+ <texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" />
+ <texture name="Tool_Face" file_name="build/Tool_Face.png" preload="false" />
+ <texture name="Tool_Grab" file_name="build/Tool_Grab.png" preload="false" />
+ <texture name="Tool_Zoom" file_name="build/Tool_Zoom.png" preload="false" />
+
+ <texture name="Toolbar_Left_Flash" file_name="containers/Toolbar_Left_Flash.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Left_Off" file_name="containers/Toolbar_Left_Off.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Left_Over" file_name="containers/Toolbar_Left_Over.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Left_Selected" file_name="containers/Toolbar_Left_Selected.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Off" file_name="containers/Toolbar_Middle_Off.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Over" file_name="containers/Toolbar_Middle_Over.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Selected" file_name="containers/Toolbar_Middle_Selected.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Flash" file_name="containers/Toolbar_Middle_Flash.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Right_Off" file_name="containers/Toolbar_Right_Off.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+ <texture name="Toolbar_Right_Over" file_name="containers/Toolbar_Right_Over.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+ <texture name="Toolbar_Right_Selected" file_name="containers/Toolbar_Right_Selected.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+ <texture name="Toolbar_Right_Flash" file_name="containers/Toolbar_Right_Flash.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+
+ <texture name="Tooltip" file_name="widgets/Tooltip.png" preload="true" scale.left="2" scale.top="16" scale.right="100" scale.bottom="3" />
+
+ <texture name="TrashItem_Disabled" file_name="icons/TrashItem_Disabled.png" preload="false" />
+ <texture name="TrashItem_Off" file_name="icons/TrashItem_Off.png" preload="false" />
+ <texture name="TrashItem_Press" file_name="icons/TrashItem_Press.png" preload="false" />
+
+ <texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />
+
+ <texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" />
+
+ <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" />
+
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
+
+ <texture name="VirtualTrackball_Moon_Back" file_name="widgets/track_control_moon_back.png" />
+ <texture name="VirtualTrackball_Moon_Front" file_name="widgets/track_control_moon_front.png" />
+ <texture name="VirtualTrackball_Rotate_Bottom" file_name="widgets/track_control_rotate_bottom.png" />
+ <texture name="VirtualTrackball_Rotate_Left" file_name="widgets/track_control_rotate_left_side.png" />
+ <texture name="VirtualTrackball_Rotate_Right" file_name="widgets/track_control_rotate_right_side.png" />
+ <texture name="VirtualTrackball_Rotate_Top" file_name="widgets/track_control_rotate_top.png" />
+ <texture name="VirtualTrackball_Rotate_Bottom_Active" file_name="widgets/track_control_rotate_bottom_active.png" />
+ <texture name="VirtualTrackball_Rotate_Left_Active" file_name="widgets/track_control_rotate_left_side_active.png" />
+ <texture name="VirtualTrackball_Rotate_Right_Active" file_name="widgets/track_control_rotate_right_side_active.png" />
+ <texture name="VirtualTrackball_Rotate_Top_Active" file_name="widgets/track_control_rotate_top_active.png" />
+ <texture name="VirtualTrackball_Sphere" file_name="widgets/track_control_sphere.png" />
+ <texture name="VirtualTrackball_Sun_Back" file_name="widgets/track_control_sun_back.png" />
+ <texture name="VirtualTrackball_Sun_Front" file_name="widgets/track_control_sun_front.png" />
+
+ <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
+ scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
+
+ <texture name="VoicePTT_Lvl1" file_name="bottomtray/VoicePTT_Lvl1.png" preload="false" />
+ <texture name="VoicePTT_Lvl2" file_name="bottomtray/VoicePTT_Lvl2.png" preload="false" />
+ <texture name="VoicePTT_Lvl3" file_name="bottomtray/VoicePTT_Lvl3.png" preload="false" />
+ <texture name="VoicePTT_Off" file_name="bottomtray/VoicePTT_Off.png" preload="false" />
+ <texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" />
+
+ <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" />
+
+ <texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" />
+ <texture name="Remove_Icon" file_name="icons/remove_icon.png" preload="false" />
+
+ <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" />
+
+ <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+
+ <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_NoTitle_Background" file_name="windows/Window_Background.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_NoTitle_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+
+ <texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" />
+
+ <texture name="Zoom_Off" file_name="icons/Zoom_Off.png" preload="false" />
+ <texture name="UnZoom_Off" file_name="icons/UnZoom_Off.png" preload="false" />
+
+ <texture name="pixiesmall.j2c" use_mips="true" />
+ <texture name="script_error.j2c" use_mips="true" />
+ <texture name="silhouette.j2c" use_mips="true" />
+ <texture name="foot_shadow.j2c" use_mips="true" />
+ <texture name="cloud-particle.png" use_mips="true" />
+ <texture name="transparent.j2c" use_mips="true" />
+
+ <!--WARNING OLD ART BELOW *do not use*-->
+ <texture name="icn_media_web.tga" preload="true" />
+ <texture name="icn_media_movie.tga" preload="true" />
+
+ <texture name="jump_left_out.tga" file_name="widgets/jump_left_out.png" />
+ <texture name="jump_left_in.tga" file_name="widgets/jump_left_in.png" />
+ <texture name="jump_right_out.tga" file_name="widgets/jump_right_out.png" />
+ <texture name="jump_right_in.tga" file_name="widgets/jump_right_in.png" />
+
+ <texture name="scrollbutton_left_out_blue.tga" file_name="widgets/ScrollArrow_Left_Opaque.png" />
+ <texture name="scrollbutton_left_in_blue.tga" file_name="widgets/ScrollArrow_Left_Over_Opaque.png" />
+ <texture name="scrollbutton_right_out_blue.tga" file_name="widgets/ScrollArrow_Right_Opaque.png" />
+ <texture name="scrollbutton_right_in_blue.tga" file_name="widgets/ScrollArrow_Right_Over_Opaque.png" />
+ <texture name="scrollbutton_up_out_blue.tga" file_name="widgets/ScrollArrow_Up_Opaque.png" />
+ <texture name="scrollbutton_up_in_blue.tga" file_name="widgets/ScrollArrow_Up_Over_Opaque.png" />
+ <texture name="scrollbutton_down_out_blue.tga" file_name="widgets/ScrollArrow_Down_Opaque.png" />
+ <texture name="scrollbutton_down_in_blue.tga" file_name="widgets/ScrollArrow_Down_Over_Opaque.png" />
+
+ <texture name="up_arrow.tga" file_name="up_arrow.png" />
+ <texture name="down_arrow.tga" file_name="down_arrow.png" />
+ <texture name="arrow_down.tga" />
+
+ <texture name="tearoffbox.tga" />
+ <texture name="tearoff_pressed.tga" />
+
+ <texture name="color_swatch_alpha.tga" preload="true" />
+
+ <texture name="button_anim_pause.tga" />
+ <texture name="button_anim_pause_selected.tga" />
+ <texture name="button_anim_play.tga" />
+ <texture name="button_anim_play_selected.tga" />
+ <texture name="crosshairs.tga" />
+ <texture name="direction_arrow.tga" file_name="world/BeaconArrow.png" />
+
+ <texture name="icon_avatar_offline.tga" />
+ <texture name="icon_avatar_online.tga" />
+ <texture name="icon_diurnal.tga" />
+ <texture name="icon_for_sale.tga" file_name="icons/Icon_For_Sale.png" />
+ <texture name="icon_auction.tga"/>
+ <texture name="icon_place.tga"/>
+ <texture name="icon_top_pick.tga" />
+
+ <texture name="icon_event.tga"/>
+ <texture name="icon_event_adult.tga"/>
+ <texture name="icon_event_mature.tga" />
+
+ <texture name="lag_status_critical.tga" />
+ <texture name="lag_status_good.tga" />
+ <texture name="lag_status_warning.tga" />
+
+ <texture name="legend.tga" />
+
+ <texture name="map_avatar_16.tga" />
+ <texture name="map_avatar_8.tga" />
+ <texture name="map_event.tga" />
+ <texture name="map_home.tga" />
+ <texture name="map_infohub.tga" />
+ <texture name="map_telehub.tga" />
+ <texture name="map_track_16.tga" />
+ <texture name="map_ui_collapse_icon.png" />
+ <texture name="map_ui_expand_icon.png" />
+
+ <texture name="notify_caution_icon.tga" />
+
+ <texture name="default_land_picture.j2c" />
+ <texture name="default_profile_picture.j2c" />
+ <texture name="locked_image.j2c" />
+ <texture name="badge_note.j2c" />
+ <texture name="badge_warn.j2c" />
+ <texture name="badge_ok.j2c" />
+ <texture name="materials_ui_x_24.png" />
+
+ <texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" />
+ <texture name="Progress_2" file_name="icons/Progress_2.png" preload="true" />
+ <texture name="Progress_3" file_name="icons/Progress_3.png" preload="true" />
+ <texture name="Progress_4" file_name="icons/Progress_4.png" preload="true" />
+ <texture name="Progress_5" file_name="icons/Progress_5.png" preload="true" />
+ <texture name="Progress_6" file_name="icons/Progress_6.png" preload="true" />
+ <texture name="Progress_7" file_name="icons/Progress_7.png" preload="true" />
+ <texture name="Progress_8" file_name="icons/Progress_8.png" preload="true" />
+ <texture name="Progress_9" file_name="icons/Progress_9.png" preload="true" />
+ <texture name="Progress_10" file_name="icons/Progress_10.png" preload="true" />
+ <texture name="Progress_11" file_name="icons/Progress_11.png" preload="true" />
+ <texture name="Progress_12" file_name="icons/Progress_12.png" preload="true" />
+
+ <texture name="bevel_background" file_name="widgets/bevel_background.png" preload="true" scale.left="12" scale.top="15" scale.right="108" scale.bottom="2"/>
+ <texture name="buy_off" file_name="widgets/buy_off.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
+ <texture name="buy_over" file_name="widgets/buy_over.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
+ <texture name="buy_press" file_name="widgets/buy_press.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
+
+ <texture name="hint_background" file_name="windows/hint_background.png" preload="false" scale.left="8" scale.top="70" scale.right="195" scale.bottom="11"/>
+ <texture name="hint_arrow_left" file_name="windows/hint_arrow_left.png" preload="false"/>
+ <texture name="hint_arrow_right" file_name="windows/hint_arrow_right.png" preload="false"/>
+ <texture name="hint_arrow_up" file_name="windows/hint_arrow_up.png" preload="false"/>
+ <texture name="hint_arrow_down" file_name="windows/hint_arrow_down.png" preload="false"/>
+ <texture name="hint_arrow_lower_left" file_name="windows/hint_arrow_lower_left.png" preload="false"/>
+
+ <texture name="Yellow_Gradient" file_name="windows/yellow_gradient.png"/>
+ <texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>
+ <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
+ <texture name="NavBar Separator" file_name="navbar/separator.png"/>
+
+ <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/>
+ <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/>
+ <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/>
+ <texture name="System_Notification" file_name="icons/MP_Logo.png" preload="true"/>
+ <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/>
+ <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/>
+
+ <texture name="Single_Folder_Mode" file_name="icons/single_folder_mode.png" preload="true"/>
+ <texture name="Multi_Folder_Mode" file_name="icons/multi_folder_mode.png" preload="true"/>
+ <texture name="Single_Folder_Back" file_name="icons/single_folder_back.png" preload="true"/>
+ <texture name="Single_Folder_Forward" file_name="icons/single_folder_forward.png" preload="true"/>
+ <texture name="Single_Folder_Up" file_name="icons/single_folder_up.png" preload="true"/>
+ <texture name="Icon_Color_Palette" file_name="icons/Icon_Color_Palette.png" preload="false"/>
+ <texture name="Icon_Font_Size" file_name="icons/Icon_Font_Size.png" preload="false"/>
+ <texture name="Icon_Pointer" file_name="icons/Icon_Pointer.png" preload="false"/>
+
+ <texture name="mp_fpsButton" file_name="megapahit/fps_button.png" preload="false" />
+
+ <texture name="mp_red_bullet" file_name="megapahit/mp_red_bullet.png" preload="false" />
+ <texture name="mp_yellow_bullet" file_name="megapahit/mp_yellow_bullet.png" preload="false" />
+ <texture name="mp_green_bullet" file_name="megapahit/mp_green_bullet.png" preload="false" />
+ <texture name="mp_blue_bullet" file_name="megapahit/mp_blue_bullet.png" preload="false" />
+ <texture name="mp_help_bullet" file_name="megapahit/mp_help_bullet.png" preload="false" />
+ <texture name="mp_info_bullet" file_name="megapahit/mp_info_bullet.png" preload="false" />
+
+</textures>
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/360_capture.png b/indra/newview/skins/classic/textures/toolbar_icons/360_capture.png
new file mode 100644
index 0000000000..163cebe29f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/360_capture.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/appearance.png b/indra/newview/skins/classic/textures/toolbar_icons/appearance.png
new file mode 100644
index 0000000000..e6b1365388
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/appearance.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/avatars.png b/indra/newview/skins/classic/textures/toolbar_icons/avatars.png
new file mode 100644
index 0000000000..8fa0600cee
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/avatars.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/build.png b/indra/newview/skins/classic/textures/toolbar_icons/build.png
new file mode 100644
index 0000000000..e21ab3f0e4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/build.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/caret_bottom.png b/indra/newview/skins/classic/textures/toolbar_icons/caret_bottom.png
new file mode 100644
index 0000000000..5f6a01eaa1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/caret_bottom.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/caret_left.png b/indra/newview/skins/classic/textures/toolbar_icons/caret_left.png
new file mode 100644
index 0000000000..0b8090314c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/caret_left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/caret_right.png b/indra/newview/skins/classic/textures/toolbar_icons/caret_right.png
new file mode 100644
index 0000000000..044751560f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/caret_right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/chat.png b/indra/newview/skins/classic/textures/toolbar_icons/chat.png
new file mode 100644
index 0000000000..e0dbac495f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/chat.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/destinations.png b/indra/newview/skins/classic/textures/toolbar_icons/destinations.png
new file mode 100644
index 0000000000..e2325f083a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/destinations.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/environments.png b/indra/newview/skins/classic/textures/toolbar_icons/environments.png
new file mode 100644
index 0000000000..620db9f793
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/environments.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/facebook.png b/indra/newview/skins/classic/textures/toolbar_icons/facebook.png
new file mode 100644
index 0000000000..ae524b643f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/facebook.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/favorite_folder.png b/indra/newview/skins/classic/textures/toolbar_icons/favorite_folder.png
new file mode 100644
index 0000000000..811efffc0b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/favorite_folder.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/flickr.png b/indra/newview/skins/classic/textures/toolbar_icons/flickr.png
new file mode 100644
index 0000000000..7fce9f0df2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/flickr.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/gestures.png b/indra/newview/skins/classic/textures/toolbar_icons/gestures.png
new file mode 100644
index 0000000000..2404bb4e25
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/gestures.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/grid_status.png b/indra/newview/skins/classic/textures/toolbar_icons/grid_status.png
new file mode 100644
index 0000000000..b92b93cfb4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/grid_status.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/highlighting.png b/indra/newview/skins/classic/textures/toolbar_icons/highlighting.png
new file mode 100644
index 0000000000..093bace257
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/highlighting.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/highlighting_selected.png b/indra/newview/skins/classic/textures/toolbar_icons/highlighting_selected.png
new file mode 100644
index 0000000000..ac75b22761
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/highlighting_selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/howto.png b/indra/newview/skins/classic/textures/toolbar_icons/howto.png
new file mode 100644
index 0000000000..8594d71113
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/howto.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/inventory.png b/indra/newview/skins/classic/textures/toolbar_icons/inventory.png
new file mode 100644
index 0000000000..ab3191255e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/inventory.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/land.png b/indra/newview/skins/classic/textures/toolbar_icons/land.png
new file mode 100644
index 0000000000..89ea7604a4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/land.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/map.png b/indra/newview/skins/classic/textures/toolbar_icons/map.png
new file mode 100644
index 0000000000..ed1049b7db
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/map.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/marketplace.png b/indra/newview/skins/classic/textures/toolbar_icons/marketplace.png
new file mode 100644
index 0000000000..62bad20be6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/marketplace.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/mini_cart.png b/indra/newview/skins/classic/textures/toolbar_icons/mini_cart.png
new file mode 100644
index 0000000000..9eeb1d4e09
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/mini_cart.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/mini_map.png b/indra/newview/skins/classic/textures/toolbar_icons/mini_map.png
new file mode 100644
index 0000000000..ab0a654056
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/mini_map.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/mktlistings.png b/indra/newview/skins/classic/textures/toolbar_icons/mktlistings.png
new file mode 100644
index 0000000000..a6f90461d7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/mktlistings.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/move.png b/indra/newview/skins/classic/textures/toolbar_icons/move.png
new file mode 100644
index 0000000000..5c2ced7375
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/move.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/nearbyvoice.png b/indra/newview/skins/classic/textures/toolbar_icons/nearbyvoice.png
new file mode 100644
index 0000000000..77a7cd5f44
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/nearbyvoice.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/outbox.png b/indra/newview/skins/classic/textures/toolbar_icons/outbox.png
new file mode 100644
index 0000000000..0f3db1c47c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/outbox.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/people.png b/indra/newview/skins/classic/textures/toolbar_icons/people.png
new file mode 100644
index 0000000000..7228ae8e2f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/people.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/performance.png b/indra/newview/skins/classic/textures/toolbar_icons/performance.png
new file mode 100644
index 0000000000..91baf849c8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/performance.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/picks.png b/indra/newview/skins/classic/textures/toolbar_icons/picks.png
new file mode 100644
index 0000000000..befda04b42
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/picks.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/places.png b/indra/newview/skins/classic/textures/toolbar_icons/places.png
new file mode 100644
index 0000000000..97d9fa066c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/places.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/preferences.png b/indra/newview/skins/classic/textures/toolbar_icons/preferences.png
new file mode 100644
index 0000000000..4ccd7b8ae1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/preferences.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/profile.png b/indra/newview/skins/classic/textures/toolbar_icons/profile.png
new file mode 100644
index 0000000000..32fe2bf8ac
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/profile.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/report_abuse.png b/indra/newview/skins/classic/textures/toolbar_icons/report_abuse.png
new file mode 100644
index 0000000000..d5cb6ca259
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/report_abuse.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/resync_animations.png b/indra/newview/skins/classic/textures/toolbar_icons/resync_animations.png
new file mode 100644
index 0000000000..dc9ee9c428
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/resync_animations.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/search.png b/indra/newview/skins/classic/textures/toolbar_icons/search.png
new file mode 100644
index 0000000000..bcb11e950d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/search.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/snapshot.png b/indra/newview/skins/classic/textures/toolbar_icons/snapshot.png
new file mode 100644
index 0000000000..d26da9b1d2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/snapshot.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/speak.png b/indra/newview/skins/classic/textures/toolbar_icons/speak.png
new file mode 100644
index 0000000000..10cd354c5c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/speak.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/twitter.png b/indra/newview/skins/classic/textures/toolbar_icons/twitter.png
new file mode 100644
index 0000000000..0ad56f7802
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/twitter.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/toolbar_icons/view.png b/indra/newview/skins/classic/textures/toolbar_icons/view.png
new file mode 100644
index 0000000000..ddf0df7c26
--- /dev/null
+++ b/indra/newview/skins/classic/textures/toolbar_icons/view.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Down.png b/indra/newview/skins/classic/textures/widgets/Arrow_Down.png
new file mode 100644
index 0000000000..8b592ed840
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Down.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Left.png b/indra/newview/skins/classic/textures/widgets/Arrow_Left.png
new file mode 100644
index 0000000000..04416541b9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Right.png b/indra/newview/skins/classic/textures/widgets/Arrow_Right.png
new file mode 100644
index 0000000000..e57452a558
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Small_Down.png b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Down.png
new file mode 100644
index 0000000000..8694cdf2d4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Down.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Small_Left.png b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Left.png
new file mode 100644
index 0000000000..a1b82d5101
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Small_Right.png b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Right.png
new file mode 100644
index 0000000000..0e05d76852
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Small_Up.png b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Up.png
new file mode 100644
index 0000000000..348bc4c019
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Small_Up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Arrow_Up.png b/indra/newview/skins/classic/textures/widgets/Arrow_Up.png
new file mode 100644
index 0000000000..8b3da09d79
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Arrow_Up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Badge_Background.png b/indra/newview/skins/classic/textures/widgets/Badge_Background.png
new file mode 100644
index 0000000000..5abc1bf489
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Badge_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Badge_Border.png b/indra/newview/skins/classic/textures/widgets/Badge_Border.png
new file mode 100644
index 0000000000..57d3be2320
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Badge_Border.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Disabled.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Disabled.png
new file mode 100644
index 0000000000..139d71ae2e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Off.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Off.png
new file mode 100644
index 0000000000..f7a6aaa275
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Over.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Over.png
new file mode 100644
index 0000000000..48c21de265
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Press.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Press.png
new file mode 100644
index 0000000000..3078c13d10
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Left_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Disabled.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Disabled.png
new file mode 100644
index 0000000000..2cf3de24c0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Off.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Off.png
new file mode 100644
index 0000000000..fe2cfb3318
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Over.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Over.png
new file mode 100644
index 0000000000..e0e05b19d0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Press.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Press.png
new file mode 100644
index 0000000000..2abb81e2b4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Middle_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Disabled.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Disabled.png
new file mode 100644
index 0000000000..d9c9692114
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Off.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Off.png
new file mode 100644
index 0000000000..f1effe6ad5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Over.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Over.png
new file mode 100644
index 0000000000..f0109f1f78
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Press.png b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Press.png
new file mode 100644
index 0000000000..3f2ea8737d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/BreadCrumbBtn_Right_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_Disabled.png b/indra/newview/skins/classic/textures/widgets/Checkbox_Disabled.png
new file mode 100644
index 0000000000..8439f82e29
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_Off.png b/indra/newview/skins/classic/textures/widgets/Checkbox_Off.png
new file mode 100644
index 0000000000..cb9a04d84f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_On.png b/indra/newview/skins/classic/textures/widgets/Checkbox_On.png
new file mode 100644
index 0000000000..0ec090504a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_On_Disabled.png b/indra/newview/skins/classic/textures/widgets/Checkbox_On_Disabled.png
new file mode 100644
index 0000000000..5759f7de69
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_On_Press.png b/indra/newview/skins/classic/textures/widgets/Checkbox_On_Press.png
new file mode 100644
index 0000000000..ba46e91c55
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Checkbox_Press.png b/indra/newview/skins/classic/textures/widgets/Checkbox_Press.png
new file mode 100644
index 0000000000..5f5a33d878
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Checkbox_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_Disabled.png b/indra/newview/skins/classic/textures/widgets/ComboButton_Disabled.png
new file mode 100644
index 0000000000..ebeb813349
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_Hover.png b/indra/newview/skins/classic/textures/widgets/ComboButton_Hover.png
new file mode 100644
index 0000000000..1377d35e1a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_Hover.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_Off.png b/indra/newview/skins/classic/textures/widgets/ComboButton_Off.png
new file mode 100644
index 0000000000..8c315a9d25
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_On.png b/indra/newview/skins/classic/textures/widgets/ComboButton_On.png
new file mode 100644
index 0000000000..368f907a1f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_Selected.png b/indra/newview/skins/classic/textures/widgets/ComboButton_Selected.png
new file mode 100644
index 0000000000..15afcb04a1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_UpOff.png b/indra/newview/skins/classic/textures/widgets/ComboButton_UpOff.png
new file mode 100644
index 0000000000..34edea9421
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_UpOff.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ComboButton_UpSelected.png b/indra/newview/skins/classic/textures/widgets/ComboButton_UpSelected.png
new file mode 100644
index 0000000000..9583f05507
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ComboButton_UpSelected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DisclosureArrow_Opened_Off.png b/indra/newview/skins/classic/textures/widgets/DisclosureArrow_Opened_Off.png
new file mode 100644
index 0000000000..115ec7a11f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DisclosureArrow_Opened_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DropDown_Disabled.png b/indra/newview/skins/classic/textures/widgets/DropDown_Disabled.png
new file mode 100644
index 0000000000..9a69f7e0d9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DropDown_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DropDown_Off.png b/indra/newview/skins/classic/textures/widgets/DropDown_Off.png
new file mode 100644
index 0000000000..b118e7a7d4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DropDown_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DropDown_On.png b/indra/newview/skins/classic/textures/widgets/DropDown_On.png
new file mode 100644
index 0000000000..3613e42a3f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DropDown_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DropDown_Press.png b/indra/newview/skins/classic/textures/widgets/DropDown_Press.png
new file mode 100644
index 0000000000..ec0ffc2e88
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DropDown_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/DropTarget.png b/indra/newview/skins/classic/textures/widgets/DropTarget.png
new file mode 100644
index 0000000000..01e7a88861
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/DropTarget.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Error_Tag_Background.png b/indra/newview/skins/classic/textures/widgets/Error_Tag_Background.png
new file mode 100644
index 0000000000..439fce3dd3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Error_Tag_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Alert.png b/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Alert.png
new file mode 100644
index 0000000000..76e078100f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Alert.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Background.png b/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Background.png
new file mode 100644
index 0000000000..6e71ef7b72
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Linden_Dollar_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ListItem_Over.png b/indra/newview/skins/classic/textures/widgets/ListItem_Over.png
new file mode 100644
index 0000000000..8c80522232
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ListItem_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ListItem_Select.png b/indra/newview/skins/classic/textures/widgets/ListItem_Select.png
new file mode 100644
index 0000000000..b27e0ee787
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ListItem_Select.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Off.png
new file mode 100644
index 0000000000..de71f763d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Selected.png
new file mode 100644
index 0000000000..6020fadc5a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/MarketplaceBtn_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Marketplace_Dropzone_Background.png b/indra/newview/skins/classic/textures/widgets/Marketplace_Dropzone_Background.png
new file mode 100644
index 0000000000..9eb4a5c55d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Marketplace_Dropzone_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/New_Tag_Background.png b/indra/newview/skins/classic/textures/widgets/New_Tag_Background.png
new file mode 100644
index 0000000000..3631d90825
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/New_Tag_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/New_Tag_Border.png b/indra/newview/skins/classic/textures/widgets/New_Tag_Border.png
new file mode 100644
index 0000000000..d9b78eeea4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/New_Tag_Border.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ProgressBar.png b/indra/newview/skins/classic/textures/widgets/ProgressBar.png
new file mode 100644
index 0000000000..492d9b6fc4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ProgressBar.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ProgressBarSolid.png b/indra/newview/skins/classic/textures/widgets/ProgressBarSolid.png
new file mode 100644
index 0000000000..59a798464d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ProgressBarSolid.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ProgressTrack.png b/indra/newview/skins/classic/textures/widgets/ProgressTrack.png
new file mode 100644
index 0000000000..f4be9f5ccd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ProgressTrack.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Disabled.png b/indra/newview/skins/classic/textures/widgets/PushButton_Disabled.png
new file mode 100644
index 0000000000..e99ec4b14b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Login.png b/indra/newview/skins/classic/textures/widgets/PushButton_Login.png
new file mode 100644
index 0000000000..8e7d932ab1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Login.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Login_Over.png b/indra/newview/skins/classic/textures/widgets/PushButton_Login_Over.png
new file mode 100644
index 0000000000..038ba23be2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Login_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Login_Pressed.png b/indra/newview/skins/classic/textures/widgets/PushButton_Login_Pressed.png
new file mode 100644
index 0000000000..828aa1a139
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Login_Pressed.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Off.png b/indra/newview/skins/classic/textures/widgets/PushButton_Off.png
new file mode 100644
index 0000000000..c74cea62d3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_On.png b/indra/newview/skins/classic/textures/widgets/PushButton_On.png
new file mode 100644
index 0000000000..e387c7e313
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_On_Selected.png b/indra/newview/skins/classic/textures/widgets/PushButton_On_Selected.png
new file mode 100644
index 0000000000..ee1329e842
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Over.png b/indra/newview/skins/classic/textures/widgets/PushButton_Over.png
new file mode 100644
index 0000000000..34a64a3ade
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Press.png b/indra/newview/skins/classic/textures/widgets/PushButton_Press.png
new file mode 100644
index 0000000000..79fc601f27
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Selected.png b/indra/newview/skins/classic/textures/widgets/PushButton_Selected.png
new file mode 100644
index 0000000000..7d9cb29a7b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Disabled.png b/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Disabled.png
new file mode 100644
index 0000000000..6332412692
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Press.png b/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Press.png
new file mode 100644
index 0000000000..e2818da352
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/PushButton_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_Disabled.png b/indra/newview/skins/classic/textures/widgets/RadioButton_Disabled.png
new file mode 100644
index 0000000000..32ec25fe0e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_Off.png b/indra/newview/skins/classic/textures/widgets/RadioButton_Off.png
new file mode 100644
index 0000000000..5d267af5dc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_On.png b/indra/newview/skins/classic/textures/widgets/RadioButton_On.png
new file mode 100644
index 0000000000..e6bf0db157
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_On.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_On_Disabled.png b/indra/newview/skins/classic/textures/widgets/RadioButton_On_Disabled.png
new file mode 100644
index 0000000000..72aae43618
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_On_Press.png b/indra/newview/skins/classic/textures/widgets/RadioButton_On_Press.png
new file mode 100644
index 0000000000..f3883b82b3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/RadioButton_Press.png b/indra/newview/skins/classic/textures/widgets/RadioButton_Press.png
new file mode 100644
index 0000000000..0025256045
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/RadioButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down.png
new file mode 100644
index 0000000000..768909d447
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Opaque.png
new file mode 100644
index 0000000000..1c57521e9e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Over_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Over_Opaque.png
new file mode 100644
index 0000000000..3db7be9ffa
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Down_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left.png
new file mode 100644
index 0000000000..9ef73f48a5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Opaque.png
new file mode 100644
index 0000000000..0fb0671036
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Over_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Over_Opaque.png
new file mode 100644
index 0000000000..464130c359
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Left_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right.png
new file mode 100644
index 0000000000..8a59274b8a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Opaque.png
new file mode 100644
index 0000000000..ab1f1ac90b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Over_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Over_Opaque.png
new file mode 100644
index 0000000000..e5a94429a3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Right_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up.png
new file mode 100644
index 0000000000..064580f0c8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Opaque.png
new file mode 100644
index 0000000000..2cc4857d27
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Over_Opaque.png b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Over_Opaque.png
new file mode 100644
index 0000000000..2018b53af9
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollArrow_Up_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollThumb_Horiz.png b/indra/newview/skins/classic/textures/widgets/ScrollThumb_Horiz.png
new file mode 100644
index 0000000000..9afc907c1c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollThumb_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollThumb_Vert.png b/indra/newview/skins/classic/textures/widgets/ScrollThumb_Vert.png
new file mode 100644
index 0000000000..ede643e528
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollThumb_Vert.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollTrack_Horiz.png b/indra/newview/skins/classic/textures/widgets/ScrollTrack_Horiz.png
new file mode 100644
index 0000000000..35da770073
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollTrack_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/ScrollTrack_Vert.png b/indra/newview/skins/classic/textures/widgets/ScrollTrack_Vert.png
new file mode 100644
index 0000000000..cf67c23133
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/ScrollTrack_Vert.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Disabled.png
new file mode 100644
index 0000000000..ef50fb5d51
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Off.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Off.png
new file mode 100644
index 0000000000..191dbf08fc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Over.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Over.png
new file mode 100644
index 0000000000..d5882bce85
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Press.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Press.png
new file mode 100644
index 0000000000..ddaab1cfcd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected.png
new file mode 100644
index 0000000000..c8634b1294
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png
new file mode 100644
index 0000000000..465ce8d7da
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Over.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Over.png
new file mode 100644
index 0000000000..9ff1e05a52
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Press.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Press.png
new file mode 100644
index 0000000000..4775dab43b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Left_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Disabled.png
new file mode 100644
index 0000000000..65d082b993
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected.png
new file mode 100644
index 0000000000..12f55c599e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
new file mode 100644
index 0000000000..6a023156c5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Press.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
new file mode 100644
index 0000000000..457644e69a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Disabled.png
new file mode 100644
index 0000000000..ccea8fc784
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Off.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Off.png
new file mode 100644
index 0000000000..f90ede3b71
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_On_Selected.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_On_Selected.png
new file mode 100644
index 0000000000..524d3b6bfd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Over.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Over.png
new file mode 100644
index 0000000000..cadcec085a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Press.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Press.png
new file mode 100644
index 0000000000..889d06a690
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected.png
new file mode 100644
index 0000000000..aa3906d236
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png
new file mode 100644
index 0000000000..255fd1c415
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Press.png b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Press.png
new file mode 100644
index 0000000000..a69d0b525f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SegmentedBtn_Right_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SliderThumb_Disabled.png b/indra/newview/skins/classic/textures/widgets/SliderThumb_Disabled.png
new file mode 100644
index 0000000000..5cfa3ae4e1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SliderThumb_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SliderThumb_Off.png b/indra/newview/skins/classic/textures/widgets/SliderThumb_Off.png
new file mode 100644
index 0000000000..66cdcbeb94
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SliderThumb_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SliderThumb_Press.png b/indra/newview/skins/classic/textures/widgets/SliderThumb_Press.png
new file mode 100644
index 0000000000..0bf8e43e81
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SliderThumb_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SliderTrack_Horiz.png b/indra/newview/skins/classic/textures/widgets/SliderTrack_Horiz.png
new file mode 100644
index 0000000000..720830f83f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SliderTrack_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/SliderTrack_Vert.png b/indra/newview/skins/classic/textures/widgets/SliderTrack_Vert.png
new file mode 100644
index 0000000000..c01db44707
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/SliderTrack_Vert.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Stepper_Down_Off.png b/indra/newview/skins/classic/textures/widgets/Stepper_Down_Off.png
new file mode 100644
index 0000000000..ff21034095
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Stepper_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Stepper_Down_Press.png b/indra/newview/skins/classic/textures/widgets/Stepper_Down_Press.png
new file mode 100644
index 0000000000..e888e1e045
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Stepper_Down_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Stepper_Up_Off.png b/indra/newview/skins/classic/textures/widgets/Stepper_Up_Off.png
new file mode 100644
index 0000000000..133845bdbc
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Stepper_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Stepper_Up_Press.png b/indra/newview/skins/classic/textures/widgets/Stepper_Up_Press.png
new file mode 100644
index 0000000000..dffd557bbd
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Stepper_Up_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Active.png b/indra/newview/skins/classic/textures/widgets/TextField_Active.png
new file mode 100644
index 0000000000..66c3867b81
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Disabled.png b/indra/newview/skins/classic/textures/widgets/TextField_Disabled.png
new file mode 100644
index 0000000000..baf747f581
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Off.png b/indra/newview/skins/classic/textures/widgets/TextField_Off.png
new file mode 100644
index 0000000000..a35562f950
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Search_Active.png b/indra/newview/skins/classic/textures/widgets/TextField_Search_Active.png
new file mode 100644
index 0000000000..572535f1ab
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Search_Active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Search_Disabled.png b/indra/newview/skins/classic/textures/widgets/TextField_Search_Disabled.png
new file mode 100644
index 0000000000..94b4b158f7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Search_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/classic/textures/widgets/TextField_Search_Highlight.png
new file mode 100644
index 0000000000..7768da04e8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Search_Highlight.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/TextField_Search_Off.png b/indra/newview/skins/classic/textures/widgets/TextField_Search_Off.png
new file mode 100644
index 0000000000..fccd38c807
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/TextField_Search_Off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/Tooltip.png b/indra/newview/skins/classic/textures/widgets/Tooltip.png
new file mode 100644
index 0000000000..1be53bdaa2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/Tooltip.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/bevel_background.png b/indra/newview/skins/classic/textures/widgets/bevel_background.png
new file mode 100644
index 0000000000..6304124aec
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/bevel_background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/buy_off.png b/indra/newview/skins/classic/textures/widgets/buy_off.png
new file mode 100644
index 0000000000..517e6f9e54
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/buy_off.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/buy_over.png b/indra/newview/skins/classic/textures/widgets/buy_over.png
new file mode 100644
index 0000000000..c17395d2e7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/buy_over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/buy_press.png b/indra/newview/skins/classic/textures/widgets/buy_press.png
new file mode 100644
index 0000000000..96f818e69f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/buy_press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/classic/textures/widgets/horizontal_drag_handle.png
new file mode 100644
index 0000000000..631d653968
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/horizontal_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/jump_left_in.png b/indra/newview/skins/classic/textures/widgets/jump_left_in.png
new file mode 100644
index 0000000000..073606628c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/jump_left_in.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/jump_left_out.png b/indra/newview/skins/classic/textures/widgets/jump_left_out.png
new file mode 100644
index 0000000000..71d5c5c36a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/jump_left_out.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/jump_right_in.png b/indra/newview/skins/classic/textures/widgets/jump_right_in.png
new file mode 100644
index 0000000000..96f8501932
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/jump_right_in.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/jump_right_out.png b/indra/newview/skins/classic/textures/widgets/jump_right_out.png
new file mode 100644
index 0000000000..9c02f5f649
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/jump_right_out.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_moon_back.png b/indra/newview/skins/classic/textures/widgets/track_control_moon_back.png
new file mode 100644
index 0000000000..03d1e805e1
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_moon_back.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_moon_front.png b/indra/newview/skins/classic/textures/widgets/track_control_moon_front.png
new file mode 100644
index 0000000000..cdc52fe08a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_moon_front.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom.png
new file mode 100644
index 0000000000..c08b54c269
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom_active.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom_active.png
new file mode 100644
index 0000000000..a2b37d1b43
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_bottom_active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side.png
new file mode 100644
index 0000000000..3439e8717f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side_active.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side_active.png
new file mode 100644
index 0000000000..fa745175be
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_left_side_active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side.png
new file mode 100644
index 0000000000..f92fdb3d92
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side_active.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side_active.png
new file mode 100644
index 0000000000..23571d6473
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_right_side_active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_top.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_top.png
new file mode 100644
index 0000000000..ae67084a7d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_top.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_rotate_top_active.png b/indra/newview/skins/classic/textures/widgets/track_control_rotate_top_active.png
new file mode 100644
index 0000000000..4e1d0ad096
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_rotate_top_active.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_sphere.png b/indra/newview/skins/classic/textures/widgets/track_control_sphere.png
new file mode 100644
index 0000000000..b6592b5992
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_sphere.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_sun_back.png b/indra/newview/skins/classic/textures/widgets/track_control_sun_back.png
new file mode 100644
index 0000000000..b3191ccc5d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_sun_back.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/track_control_sun_front.png b/indra/newview/skins/classic/textures/widgets/track_control_sun_front.png
new file mode 100644
index 0000000000..1cdcbf7861
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/track_control_sun_front.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/classic/textures/widgets/vertical_drag_handle.png
new file mode 100644
index 0000000000..d78e898a9c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/widgets/vertical_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Dragbar.png b/indra/newview/skins/classic/textures/windows/Dragbar.png
new file mode 100644
index 0000000000..3a998abdc3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Dragbar.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Flyout_Left.png b/indra/newview/skins/classic/textures/windows/Flyout_Left.png
new file mode 100644
index 0000000000..3110d7f6b5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Flyout_Left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Flyout_Pointer.png b/indra/newview/skins/classic/textures/windows/Flyout_Pointer.png
new file mode 100644
index 0000000000..4076bb393e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Flyout_Pointer.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Flyout_Right.png b/indra/newview/skins/classic/textures/windows/Flyout_Right.png
new file mode 100644
index 0000000000..4c55cd6287
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Flyout_Right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Close_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Close_Foreground.png
new file mode 100644
index 0000000000..cb516886a2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Close_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Close_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Close_Press.png
new file mode 100644
index 0000000000..283981f6ea
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Close_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Close_Toast.png b/indra/newview/skins/classic/textures/windows/Icon_Close_Toast.png
new file mode 100644
index 0000000000..b08ffbc742
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Close_Toast.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Dock_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Dock_Foreground.png
new file mode 100644
index 0000000000..7508fcb25e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Dock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Dock_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Dock_Press.png
new file mode 100644
index 0000000000..3f2c560398
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Dock_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Gear.png b/indra/newview/skins/classic/textures/windows/Icon_Gear.png
new file mode 100644
index 0000000000..7cf85bece4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Gear.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Gear_Background.png b/indra/newview/skins/classic/textures/windows/Icon_Gear_Background.png
new file mode 100644
index 0000000000..09d83e62e4
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Gear_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Gear_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Gear_Foreground.png
new file mode 100644
index 0000000000..fa998eee5d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Gear_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Gear_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Gear_Press.png
new file mode 100644
index 0000000000..603fa2f388
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Gear_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Help_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Help_Foreground.png
new file mode 100644
index 0000000000..1bde4c040a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Help_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Help_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Help_Press.png
new file mode 100644
index 0000000000..f3b885283f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Help_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Minimize_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Minimize_Foreground.png
new file mode 100644
index 0000000000..942efb40f7
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Minimize_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Minimize_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Minimize_Press.png
new file mode 100644
index 0000000000..1fe37b7a2e
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Minimize_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Restore_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Restore_Foreground.png
new file mode 100644
index 0000000000..7840deccb8
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Restore_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Restore_Press.png b/indra/newview/skins/classic/textures/windows/Icon_Restore_Press.png
new file mode 100644
index 0000000000..33258a0bc5
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Restore_Press.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Icon_Undock_Foreground.png b/indra/newview/skins/classic/textures/windows/Icon_Undock_Foreground.png
new file mode 100644
index 0000000000..df826226e6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Icon_Undock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Inspector_Background.png b/indra/newview/skins/classic/textures/windows/Inspector_Background.png
new file mode 100644
index 0000000000..3053269b84
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Inspector_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Inspector_Hover.png b/indra/newview/skins/classic/textures/windows/Inspector_Hover.png
new file mode 100644
index 0000000000..0cb846eba0
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Inspector_Hover.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Inspector_I.png b/indra/newview/skins/classic/textures/windows/Inspector_I.png
new file mode 100644
index 0000000000..0d1719c66f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Inspector_I.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Resize_Corner.png b/indra/newview/skins/classic/textures/windows/Resize_Corner.png
new file mode 100644
index 0000000000..4a533011df
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Resize_Corner.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Toast_Background.png b/indra/newview/skins/classic/textures/windows/Toast_Background.png
new file mode 100644
index 0000000000..00676350ca
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Toast_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Toast_CloseBtn.png b/indra/newview/skins/classic/textures/windows/Toast_CloseBtn.png
new file mode 100644
index 0000000000..f37d8d085d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Toast_CloseBtn.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Toast_Over.png b/indra/newview/skins/classic/textures/windows/Toast_Over.png
new file mode 100644
index 0000000000..5191e0858d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Toast_Over.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Volume_Background.png b/indra/newview/skins/classic/textures/windows/Volume_Background.png
new file mode 100644
index 0000000000..9f8680d079
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Volume_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Wearables_Divider.png b/indra/newview/skins/classic/textures/windows/Wearables_Divider.png
new file mode 100644
index 0000000000..8795ccd661
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Wearables_Divider.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Window_Background.png b/indra/newview/skins/classic/textures/windows/Window_Background.png
new file mode 100644
index 0000000000..f19fb0300b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Window_Background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/Window_Foreground.png b/indra/newview/skins/classic/textures/windows/Window_Foreground.png
new file mode 100644
index 0000000000..15d2ff72b6
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/Window_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/add_payment_image_center.png b/indra/newview/skins/classic/textures/windows/add_payment_image_center.png
new file mode 100644
index 0000000000..0b99a72f32
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/add_payment_image_center.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/add_payment_image_left.png b/indra/newview/skins/classic/textures/windows/add_payment_image_left.png
new file mode 100644
index 0000000000..a5b28d7023
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/add_payment_image_left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/add_payment_image_right.png b/indra/newview/skins/classic/textures/windows/add_payment_image_right.png
new file mode 100644
index 0000000000..5724d39744
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/add_payment_image_right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/first_login_image.jpg b/indra/newview/skins/classic/textures/windows/first_login_image.jpg
new file mode 100644
index 0000000000..30f31341ed
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/first_login_image.jpg
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_arrow_down.png b/indra/newview/skins/classic/textures/windows/hint_arrow_down.png
new file mode 100644
index 0000000000..b449d3be7c
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_arrow_down.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_arrow_left.png b/indra/newview/skins/classic/textures/windows/hint_arrow_left.png
new file mode 100644
index 0000000000..d93d621067
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_arrow_left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_arrow_lower_left.png b/indra/newview/skins/classic/textures/windows/hint_arrow_lower_left.png
new file mode 100644
index 0000000000..5e8def5a5b
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_arrow_lower_left.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_arrow_right.png b/indra/newview/skins/classic/textures/windows/hint_arrow_right.png
new file mode 100644
index 0000000000..3524487fb3
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_arrow_right.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_arrow_up.png b/indra/newview/skins/classic/textures/windows/hint_arrow_up.png
new file mode 100644
index 0000000000..aca440d712
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_arrow_up.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/hint_background.png b/indra/newview/skins/classic/textures/windows/hint_background.png
new file mode 100644
index 0000000000..d045bc5e29
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/hint_background.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/login_mp_logo.png b/indra/newview/skins/classic/textures/windows/login_mp_logo.png
new file mode 100644
index 0000000000..7526374ba2
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/login_mp_logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/login_mp_logo_small.png b/indra/newview/skins/classic/textures/windows/login_mp_logo_small.png
new file mode 100644
index 0000000000..779d8ff649
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/login_mp_logo_small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/login_sl_logo.png b/indra/newview/skins/classic/textures/windows/login_sl_logo.png
new file mode 100644
index 0000000000..e4d4eb3ebf
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/login_sl_logo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/login_sl_logo_small.png b/indra/newview/skins/classic/textures/windows/login_sl_logo_small.png
index 36fb15de08..36fb15de08 100644
--- a/indra/newview/skins/default/textures/windows/login_sl_logo_small.png
+++ b/indra/newview/skins/classic/textures/windows/login_sl_logo_small.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/startup_logo.png b/indra/newview/skins/classic/textures/windows/startup_logo.png
new file mode 100644
index 0000000000..6a81a6451d
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/startup_logo.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/windows/yellow_gradient.png b/indra/newview/skins/classic/textures/windows/yellow_gradient.png
new file mode 100644
index 0000000000..4a07282ecb
--- /dev/null
+++ b/indra/newview/skins/classic/textures/windows/yellow_gradient.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/world/BeaconArrow.png b/indra/newview/skins/classic/textures/world/BeaconArrow.png
new file mode 100644
index 0000000000..54934f738a
--- /dev/null
+++ b/indra/newview/skins/classic/textures/world/BeaconArrow.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/world/CameraDragDot.png b/indra/newview/skins/classic/textures/world/CameraDragDot.png
new file mode 100644
index 0000000000..2ccf098e0f
--- /dev/null
+++ b/indra/newview/skins/classic/textures/world/CameraDragDot.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/world/NoEntryLines.png b/indra/newview/skins/classic/textures/world/NoEntryLines.png
new file mode 100644
index 0000000000..b295ba1281
--- /dev/null
+++ b/indra/newview/skins/classic/textures/world/NoEntryLines.png
Binary files differ
diff --git a/indra/newview/skins/classic/textures/world/NoEntryPassLines.png b/indra/newview/skins/classic/textures/world/NoEntryPassLines.png
new file mode 100644
index 0000000000..34900e2c02
--- /dev/null
+++ b/indra/newview/skins/classic/textures/world/NoEntryPassLines.png
Binary files differ
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 699b727212..838b6da5a8 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -1,905 +1,920 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<colors>
- <!-- Named Colors -->
- <color
- name="EmphasisColor"
- value="0.25 0.48 0.70 1" />
- <color
- name="EmphasisColor_13"
- value="0.25 0.48 0.70 0.13" />
- <color
- name="EmphasisColor_35"
- value="0.25 0.48 0.70 0.35" />
- <color
- name="BeaconColor"
- value="0.749 0.298 0 1" />
- <color
- name="White"
- value="1 1 1 1" />
- <color
- name="White_05"
- value="1 1 1 0.05" />
- <color
- name="White_10"
- value="1 1 1 0.1" />
- <color
- name="White_25"
- value="1 1 1 0.25" />
- <color
- name="White_50"
- value="1 1 1 0.5" />
- <color
- name="LtGray"
- value="0.75 0.75 0.75 1" />
- <color
- name="LtGray_35"
- value="0.75 0.75 0.75 0.35" />
- <color
- name="LtGray_50"
- value="0.75 0.75 0.75 0.50" />
- <color
- name="Gray"
- value="0.5 0.5 0.5 1" />
- <color
- name="DkGray0"
- value="0.27 0.27 0.27 1" />
- <color
- name="DkGray"
- value="0.125 0.125 0.125 1" />
- <color
- name="DkGray_66"
- value="0.125 0.125 0.125 .66" />
- <color
- name="DkGray2"
- value="0.169 0.169 0.169 1" />
- <color
- name="MouseGray"
- value="0.191 0.191 0.191 1" />
- <color
- name="Black"
- value="0 0 0 1" />
- <color
- name="Black_10"
- value="0 0 0 0.1" />
- <color
- name="Black_25"
- value="0 0 0 0.25" />
- <color
- name="Black_50"
- value="0 0 0 0.5" />
- <color
- name="FrogGreen"
- value="0.26 0.33 0.42 1" />
- <!-- ^(Not actually green) -->
- <color
- name="Red"
- value="1 0 0 1" />
- <color
- name="Blue"
- value="0 0 1 1" />
- <color
- name="Yellow"
- value="1 1 0 1" />
- <color
- name="Green"
- value="0 1 0 1" />
- <color
- name="Transparent"
- value="0 0 0 0" />
- <color
- name="Purple"
- value="1 0 1 1" />
- <color
- name="Lime"
- value=".8 1 .73 1" />
- <color
- name="LtYellow"
- value="1 1 .79 1" />
- <color
- name="DrYellow"
- value="1 0.86 0 1" />
- <color
- name="LtOrange"
- value="1 .85 .73 1" />
- <color
- name="MdBlue"
- value=".07 .38 .51 1" />
- <color
- name="DkBlue"
- value=".06 .06 .3 1" />
- <color
- name="LtRed"
- value="1 0.2 0.2 1" />
- <color
- name="LtGreen"
- value="0.2 1 0.2 1" />
- <color
- name="Red_80"
- value="1 0 0 0.8" />
- <color
- name="DkRed"
- value="0.3 0.06 0.06 1" />
- <color
- name="Green_80"
- value="0 1 0 0.8" />
- <color
- name="Blue_80"
- value="0 0 1 0.8" />
- <color
- name="Orange"
- value="1 .82 .46 1" />
+ <!-- Named Colors -->
+ <color
+ name="EmphasisColor"
+ value="0.25 0.48 0.70 1" />
+ <color
+ name="EmphasisColor_35"
+ value="0.25 0.48 0.70 0.35" />
+ <color
+ name="SelectionColor"
+ value="0.706 0.851 1 1" />
+ <color
+ name="ScrollHoveredColor"
+ value="0.18 0.26 0.33 1" />
+ <color
+ name="BeaconColor"
+ value="0.749 0.298 0 1" />
+ <color
+ name="White"
+ value="1 1 1 1" />
+ <color
+ name="White_05"
+ value="1 1 1 0.05" />
+ <color
+ name="White_10"
+ value="1 1 1 0.1" />
+ <color
+ name="White_25"
+ value="1 1 1 0.25" />
+ <color
+ name="White_50"
+ value="1 1 1 0.5" />
+ <color
+ name="LtGray"
+ value="0.75 0.75 0.75 1" />
+ <color
+ name="LtGray_35"
+ value="0.75 0.75 0.75 0.35" />
+ <color
+ name="LtGray_50"
+ value="0.75 0.75 0.75 0.50" />
+ <color
+ name="Gray"
+ value="0.5 0.5 0.5 1" />
+ <color
+ name="DkGray0"
+ value="0.27 0.27 0.27 1" />
+ <color
+ name="DkGray"
+ value="0.125 0.125 0.125 1" />
+ <color
+ name="DkGray_66"
+ value="0.125 0.125 0.125 .66" />
+ <color
+ name="DkGray2"
+ value="0.169 0.169 0.169 1" />
+ <color
+ name="DkGrayLogin"
+ value="0.129 0.133 0.137 1" />
+ <color
+ name="MouseGray"
+ value="0.191 0.191 0.191 1" />
+ <color
+ name="Black"
+ value="0 0 0 1" />
+ <color
+ name="Black_10"
+ value="0 0 0 0.1" />
+ <color
+ name="Black_25"
+ value="0 0 0 0.25" />
+ <color
+ name="Black_50"
+ value="0 0 0 0.5" />
+ <color
+ name="FrogGreen"
+ value="0.26 0.33 0.42 1" />
+ <!-- ^(Not actually green) -->
+ <color
+ name="Red"
+ value="1 0 0 1" />
+ <color
+ name="Blue"
+ value="0 0 1 1" />
+ <color
+ name="Yellow"
+ value="1 1 0 1" />
+ <color
+ name="Green"
+ value="0 1 0 1" />
+ <color
+ name="Transparent"
+ value="0 0 0 0" />
+ <color
+ name="Purple"
+ value="1 0 1 1" />
+ <color
+ name="Lime"
+ value=".8 1 .73 1" />
+ <color
+ name="LtYellow"
+ value="1 1 .79 1" />
+ <color
+ name="DrYellow"
+ value="1 0.86 0 1" />
+ <color
+ name="LtOrange"
+ value="1 .85 .73 1" />
+ <color
+ name="MdBlue"
+ value=".07 .38 .51 1" />
+ <color
+ name="DkBlue"
+ value=".06 .06 .3 1" />
+ <color
+ name="LtRed"
+ value="1 0.2 0.2 1" />
+ <color
+ name="LtGreen"
+ value="0.2 1 0.2 1" />
+ <color
+ name="Red_80"
+ value="1 0 0 0.8" />
+ <color
+ name="DkRed"
+ value="0.3 0.06 0.06 1" />
+ <color
+ name="Green_80"
+ value="0 1 0 0.8" />
+ <color
+ name="Blue_80"
+ value="0 0 1 0.8" />
+ <color
+ name="Orange"
+ value="1 .82 .46 1" />
- <!-- This color name makes potentially unused colors show up bright purple.
- Leave this here until all Unused? are removed below, otherwise
- the viewer generates many warnings on startup. -->
- <color
- name="Unused?"
- value=".831 1 0 1" />
+ <!-- This color name makes potentially unused colors show up bright purple.
+ Leave this here until all Unused? are removed below, otherwise
+ the viewer generates many warnings on startup. -->
+ <color
+ name="Unused?"
+ value=".831 1 0 1" />
- <!-- UI Definitions -->
+ <!-- UI Definitions -->
<color
- name="AccordionHeaderTextColor"
- reference="LtGray" />
+ name="AccordionHeaderTextColor"
+ reference="LtGray" />
<color
- name="AgentChatColor"
- reference="White" />
+ name="AgentChatColor"
+ reference="White" />
<color
- name="AlertBoxColor"
- value="0.24 0.24 0.24 1" />
+ name="AlertBoxColor"
+ value="0.24 0.24 0.24 1" />
<color
- name="AlertCautionBoxColor"
- value="1 0.82 0.46 1" />
+ name="AlertCautionBoxColor"
+ value="1 0.82 0.46 1" />
<color
- name="AlertCautionTextColor"
- reference="LtYellow" />
+ name="AlertCautionTextColor"
+ reference="LtYellow" />
<color
- name="AvatarListItemIconDefaultColor"
- reference="White" />
+ name="AvatarListItemIconDefaultColor"
+ reference="White" />
<color
- name="AvatarListItemIconOnlineColor"
- reference="White" />
+ name="AvatarListItemIconOnlineColor"
+ reference="White" />
<color
- name="AvatarListItemIconOfflineColor"
- value="0.5 0.5 0.5 0.5" />
+ name="AvatarListItemIconOfflineColor"
+ value="0.5 0.5 0.5 0.5" />
<color
- name="AvatarListItemIconVoiceInvitedColor"
- reference="AvatarListItemIconOfflineColor" />
+ name="AvatarListItemIconVoiceInvitedColor"
+ reference="AvatarListItemIconOfflineColor" />
<color
- name="AvatarListItemIconVoiceJoinedColor"
- reference="AvatarListItemIconOnlineColor" />
+ name="AvatarListItemIconVoiceJoinedColor"
+ reference="AvatarListItemIconOnlineColor" />
<color
- name="AvatarListItemIconVoiceLeftColor"
- reference="AvatarListItemIconOfflineColor" />
+ name="AvatarListItemIconVoiceLeftColor"
+ reference="AvatarListItemIconOfflineColor" />
<color
- name="BadgeImageColor"
- value="1.0 0.40 0.0 1.0" />
+ name="BadgeImageColor"
+ value="1.0 0.40 0.0 1.0" />
<color
- name="BadgeBorderColor"
- value="0.9 0.9 0.9 1.0" />
+ name="BadgeBorderColor"
+ value="0.9 0.9 0.9 1.0" />
<color
- name="BadgeLabelColor"
- reference="White" />
+ name="BadgeLabelColor"
+ reference="White" />
<color
- name="ButtonBorderColor"
- reference="Unused?" />
+ name="ButtonBorderColor"
+ reference="Unused?" />
<color
- name="ButtonCautionImageColor"
- reference="Unused?" />
+ name="ButtonCautionImageColor"
+ reference="Unused?" />
<color
- name="ButtonColor"
- reference="Unused?" />
+ name="ButtonColor"
+ reference="Unused?" />
<color
- name="ButtonFlashBgColor"
- reference="Unused?" />
+ name="ButtonFlashBgColor"
+ reference="Unused?" />
<color
- name="ButtonImageColor"
- reference="White" />
+ name="ButtonImageColor"
+ reference="White" />
<color
- name="ButtonLabelColor"
- reference="LtGray" />
+ name="ButtonLabelColor"
+ reference="LtGray" />
<color
- name="ButtonLabelDisabledColor"
- reference="White_25" />
+ name="ButtonLabelDisabledColor"
+ reference="White_25" />
<color
- name="ButtonLabelSelectedColor"
- reference="White" />
+ name="ButtonLabelSelectedColor"
+ reference="White" />
<color
- name="ButtonLabelSelectedDisabledColor"
- reference="White_25" />
+ name="ButtonLabelSelectedDisabledColor"
+ reference="White_25" />
<color
- name="ButtonSelectedBgColor"
- reference="Unused?" />
+ name="ButtonSelectedBgColor"
+ reference="Unused?" />
<color
- name="ButtonSelectedColor"
- reference="Unused?" />
+ name="ButtonSelectedColor"
+ reference="Unused?" />
<color
- name="ButtonUnselectedBgColor"
- reference="Unused?" />
+ name="ButtonUnselectedBgColor"
+ reference="Unused?" />
<color
- name="ButtonUnselectedFgColor"
- reference="Unused?" />
+ name="ButtonUnselectedFgColor"
+ reference="Unused?" />
<color
- name="ChatHistoryBgColor"
- reference="Transparent" />
+ name="ChatHistoryBgColor"
+ reference="Transparent" />
<color
- name="ChatHistoryTextColor"
- reference="LtGray" />
+ name="ChatHistoryTextColor"
+ reference="LtGray" />
<color
- name="ChicletFlashColor"
- value="0.114 0.65 0.1" />
+ name="ChicletFlashColor"
+ value="0.114 0.65 0.1" />
<color
- name="ColorDropShadow"
- reference="Black_50" />
+ name="ColorDropShadow"
+ reference="Black_50" />
<color
- name="ColorPaletteEntry01"
- reference="Black" />
+ name="ColorPaletteEntry01"
+ reference="Black" />
<color
- name="ColorPaletteEntry02"
- reference="Gray" />
+ name="ColorPaletteEntry02"
+ reference="Gray" />
<color
- name="ColorPaletteEntry03"
- value="0.5 0 0 1" />
+ name="ColorPaletteEntry03"
+ value="0.5 0 0 1" />
<color
- name="ColorPaletteEntry04"
- value="0.5 0.5 0 1" />
+ name="ColorPaletteEntry04"
+ value="0.5 0.5 0 1" />
<color
- name="ColorPaletteEntry05"
- value="0 0.5 0 1" />
+ name="ColorPaletteEntry05"
+ value="0 0.5 0 1" />
<color
- name="ColorPaletteEntry06"
- value="0 0.5 0.5 1" />
+ name="ColorPaletteEntry06"
+ value="0 0.5 0.5 1" />
<color
- name="ColorPaletteEntry07"
- value="0 0 0.5 1" />
+ name="ColorPaletteEntry07"
+ value="0 0 0.5 1" />
<color
- name="ColorPaletteEntry08"
- value="0.5 0 0.5 1" />
+ name="ColorPaletteEntry08"
+ value="0.5 0 0.5 1" />
<color
- name="ColorPaletteEntry09"
- value="0.5 0.5 0 1" />
+ name="ColorPaletteEntry09"
+ value="0.5 0.5 0 1" />
<color
- name="ColorPaletteEntry10"
- value="0 0.25 0.25 1" />
+ name="ColorPaletteEntry10"
+ value="0 0.25 0.25 1" />
<color
- name="ColorPaletteEntry11"
- value="0 0.5 1 1" />
+ name="ColorPaletteEntry11"
+ value="0 0.5 1 1" />
<color
- name="ColorPaletteEntry12"
- value="0 0.25 0.5 1" />
+ name="ColorPaletteEntry12"
+ value="0 0.25 0.5 1" />
<color
- name="ColorPaletteEntry13"
- value="0.5 0 1 1" />
+ name="ColorPaletteEntry13"
+ value="0.5 0 1 1" />
<color
- name="ColorPaletteEntry14"
- value="0.5 0.25 0 1" />
+ name="ColorPaletteEntry14"
+ value="0.5 0.25 0 1" />
<color
- name="ColorPaletteEntry15"
- reference="White" />
+ name="ColorPaletteEntry15"
+ reference="White" />
<color
- name="ColorPaletteEntry16"
- reference="LtYellow" />
+ name="ColorPaletteEntry16"
+ reference="LtYellow" />
<color
- name="ColorPaletteEntry17"
- reference="White" />
+ name="ColorPaletteEntry17"
+ reference="White" />
<color
- name="ColorPaletteEntry18"
- reference="LtGray" />
+ name="ColorPaletteEntry18"
+ reference="LtGray" />
<color
- name="ColorPaletteEntry19"
- reference="Red" />
+ name="ColorPaletteEntry19"
+ reference="Red" />
<color
- name="ColorPaletteEntry20"
- reference="Yellow" />
+ name="ColorPaletteEntry20"
+ reference="Yellow" />
<color
- name="ColorPaletteEntry21"
- reference="Green" />
+ name="ColorPaletteEntry21"
+ reference="Green" />
<color
- name="ColorPaletteEntry22"
- value="0 1 1 1" />
+ name="ColorPaletteEntry22"
+ value="0 1 1 1" />
<color
- name="ColorPaletteEntry23"
- reference="Blue" />
+ name="ColorPaletteEntry23"
+ reference="Blue" />
<color
- name="ColorPaletteEntry24"
- reference="Purple" />
+ name="ColorPaletteEntry24"
+ reference="Purple" />
<color
- name="ColorPaletteEntry25"
- value="1 1 0.5 1" />
+ name="ColorPaletteEntry25"
+ value="1 1 0.5 1" />
<color
- name="ColorPaletteEntry26"
- value="0 1 0.5 1" />
+ name="ColorPaletteEntry26"
+ value="0 1 0.5 1" />
<color
- name="ColorPaletteEntry27"
- value="0.5 1 1 1" />
+ name="ColorPaletteEntry27"
+ value="0.5 1 1 1" />
<color
- name="ColorPaletteEntry28"
- value="0.5 0.5 1 1" />
+ name="ColorPaletteEntry28"
+ value="0.5 0.5 1 1" />
<color
- name="ColorPaletteEntry29"
- value="1 0 0.5 1" />
+ name="ColorPaletteEntry29"
+ value="1 0 0.5 1" />
<color
- name="ColorPaletteEntry30"
- value="1 0.5 0 1" />
+ name="ColorPaletteEntry30"
+ value="1 0.5 0 1" />
<color
- name="ColorPaletteEntry31"
- reference="White" />
+ name="ColorPaletteEntry31"
+ reference="White" />
<color
- name="ColorPaletteEntry32"
- reference="White" />
+ name="ColorPaletteEntry32"
+ reference="White" />
<color
- name="ComboListBgColor"
- reference="DkGray" />
+ name="ComboListBgColor"
+ reference="DkGray" />
<color
- name="ConsoleBackground"
- reference="Black" />
+ name="ConsoleBackground"
+ reference="Black" />
<color
- name="ContextSilhouetteColor"
- reference="EmphasisColor" />
+ name="ContextSilhouetteColor"
+ reference="EmphasisColor" />
<color
- name="ConversationFriendColor"
- value="0.5 0.7 0.85 1" />
+ name="ConversationFriendColor"
+ reference="SelectionColor" />
<color
- name="DefaultHighlightDark"
- reference="White_10" />
+ name="DefaultHighlightDark"
+ reference="White_10" />
<color
- name="DefaultHighlightLight"
- reference="White_25" />
+ name="DefaultHighlightLight"
+ reference="White_25" />
<color
- name="DefaultShadowDark"
- reference="Black_50" />
+ name="DefaultShadowDark"
+ reference="Black_50" />
<color
- name="DefaultShadowLight"
- reference="Black_50" />
+ name="DefaultShadowLight"
+ reference="Black_50" />
<color
- name="EffectColor"
- reference="White" />
- <color
- name="FilterBackgroundColor"
- reference="Black" />
+ name="EffectColor"
+ reference="White" />
<color
- name="FilterTextColor"
- reference="EmphasisColor" />
- <color
- name="FloaterButtonImageColor"
- reference="LtGray" />
+ name="FilterBackgroundColor"
+ reference="Black" />
<color
- name="FloaterDefaultBackgroundColor"
- reference="DkGray_66" />
+ name="FilterTextColor"
+ reference="EmphasisColor" />
<color
- name="FloaterFocusBackgroundColor"
- reference="DkGray2" />
+ name="FloaterButtonImageColor"
+ reference="LtGray" />
<color
- name="FloaterFocusBorderColor"
- reference="Black_50" />
+ name="FloaterDefaultBackgroundColor"
+ reference="DkGray_66" />
<color
- name="FloaterUnfocusBorderColor"
- reference="Black_50" />
+ name="FloaterFocusBackgroundColor"
+ reference="DkGray2" />
<color
- name="FocusColor"
- reference="EmphasisColor" />
+ name="FloaterFocusBorderColor"
+ reference="Black_50" />
<color
- name="FolderViewLoadingMessageTextColor"
- value="0.3344 0.545 0.645 1" />
+ name="FloaterUnfocusBorderColor"
+ reference="Black_50" />
<color
- name="FpsTextColor"
- value="0.34 0.51 0.64 0.8" />
+ name="FocusColor"
+ value="0.7 0.7 0.7 1" />
<color
- name="GridFocusPointColor"
- reference="White_50" />
+ name="FolderViewLoadingMessageTextColor"
+ value="0.3344 0.545 0.645 1" />
<color
- name="GridlineBGColor"
- value="0.92 0.92 1 0.78" />
+ name="FpsTextColor"
+ value="0.34 0.51 0.64 0.8" />
<color
- name="GridlineColor"
- reference="White" />
+ name="GridFocusPointColor"
+ reference="White_50" />
<color
- name="GridlineShadowColor"
- value="0 0 0 0.31" />
+ name="GridlineBGColor"
+ value="0.92 0.92 1 0.78" />
<color
- name="GroupNotifyBoxColor"
- value="0.3344 0.5456 0.5159 1" />
+ name="GridlineColor"
+ reference="White" />
<color
- name="GroupNotifyTextColor"
- reference="White"/>
+ name="GridlineShadowColor"
+ value="0 0 0 0.31" />
<color
- name="GroupNotifyDimmedTextColor"
- reference="LtGray" />
+ name="GroupNotifyBoxColor"
+ value="0.3344 0.5456 0.5159 1" />
<color
- name="GroupOverTierColor"
- value="0.43 0.06 0.06 1" />
+ name="GroupNotifyTextColor"
+ reference="White"/>
<color
- name="HTMLLinkColor"
- reference="EmphasisColor" />
+ name="GroupNotifyDimmedTextColor"
+ reference="LtGray" />
<color
- name="HealthTextColor"
- reference="White" />
+ name="GroupOverTierColor"
+ value="0.43 0.06 0.06 1" />
<color
- name="HelpBgColor"
- reference="Unused?" />
+ name="HTMLLinkColor"
+ reference="EmphasisColor" />
<color
- name="HelpFgColor"
- reference="Unused?" />
+ name="HealthTextColor"
+ reference="White" />
<color
- name="HelpScrollHighlightColor"
- reference="Unused?" />
+ name="HelpBgColor"
+ reference="Unused?" />
<color
- name="HelpScrollShadowColor"
- reference="Unused?" />
+ name="HelpFgColor"
+ reference="Unused?" />
<color
- name="HelpScrollThumbColor"
- reference="Unused?" />
+ name="HelpScrollHighlightColor"
+ reference="Unused?" />
<color
- name="HelpScrollTrackColor"
- reference="Unused?" />
+ name="HelpScrollShadowColor"
+ reference="Unused?" />
<color
- name="HighlightChildColor"
- reference="Yellow" />
+ name="HelpScrollThumbColor"
+ reference="Unused?" />
<color
- name="HighlightInspectColor"
- value="1 0 1 1" />
+ name="HelpScrollTrackColor"
+ reference="Unused?" />
<color
- name="HighlightParentColor"
- value="0.5 0.65 0.8 1" />
+ name="HighlightChildColor"
+ reference="Yellow" />
<color
- name="IMHistoryBgColor"
- reference="Unused?" />
+ name="HighlightInspectColor"
+ value="1 0 1 1" />
<color
- name="IMHistoryTextColor"
- reference="Unused?" />
+ name="HighlightParentColor"
+ value="0.5 0.65 0.8 1" />
<color
- name="IconDisabledColor"
- reference="White_25" />
+ name="IMHistoryBgColor"
+ reference="Unused?" />
<color
- name="IconEnabledColor"
- reference="White" />
+ name="IMHistoryTextColor"
+ reference="Unused?" />
<color
- name="InventoryBackgroundColor"
- reference="DkGray2" />
+ name="IconDisabledColor"
+ reference="White_25" />
<color
- name="InventoryFavoriteColor"
- reference="Yellow" />
+ name="IconEnabledColor"
+ reference="White" />
<color
- name="InventoryFocusOutlineColor"
- reference="White_25" />
+ name="InventoryBackgroundColor"
+ reference="DkGray2" />
<color
- name="InventoryItemSuffixColor"
- reference="White_25" />
+ name="InventoryFavoriteColor"
+ reference="Yellow" />
<color
- name="InventoryItemLibraryColor"
- reference="EmphasisColor" />
+ name="InventoryFocusOutlineColor"
+ reference="White_25" />
<color
- name="InventoryItemLinkColor"
- reference="LtGray_50" />
+ name="InventoryItemSuffixColor"
+ reference="White_25" />
<color
- name="InventoryMouseOverColor"
- reference="LtGray_35" />
+ name="InventoryItemLibraryColor"
+ reference="EmphasisColor" />
<color
- name="InventorySearchStatusColor"
- reference="EmphasisColor" />
+ name="InventoryItemLinkColor"
+ reference="LtGray_50" />
<color
- name="LabelDisabledColor"
- reference="White_25" />
+ name="InventoryMouseOverColor"
+ reference="LtGray_35" />
<color
- name="LabelSelectedColor"
- reference="White" />
+ name="InventorySearchStatusColor"
+ reference="EmphasisColor" />
<color
- name="LabelSelectedDisabledColor"
- reference="White_25" />
+ name="LabelDisabledColor"
+ reference="White_25" />
<color
- name="LabelTextColor"
- reference="LtGray" />
+ name="LabelSelectedColor"
+ reference="White" />
<color
- name="LoginProgressBarBgColor"
- reference="Unused?" />
+ name="LabelSelectedDisabledColor"
+ reference="White_25" />
<color
- name="LoginProgressBarFgColor"
- reference="Unused?" />
+ name="LabelTextColor"
+ reference="LtGray" />
<color
- name="LoginProgressBoxBorderColor"
- value="0 0.12 0.24 0" />
+ name="LoginProgressBarBgColor"
+ reference="Unused?" />
<color
- name="LoginProgressBoxCenterColor"
- value="0 0 0 0.78" />
+ name="LoginProgressBarFgColor"
+ reference="Unused?" />
<color
- name="LoginProgressBoxShadowColor"
- value="0 0 0 0.78" />
+ name="LoginProgressBoxBorderColor"
+ value="0 0.12 0.24 0" />
<color
- name="LoginProgressBoxTextColor"
- reference="White" />
+ name="LoginProgressBoxCenterColor"
+ value="0 0 0 0.78" />
<color
- name="MapAvatarColor"
- reference="White" />
+ name="LoginProgressBoxShadowColor"
+ value="0 0 0 0.78" />
<color
- name="MapAvatarFriendColor"
- value="0.5 0.7 0.85 1" />
+ name="LoginProgressBoxTextColor"
+ reference="White" />
<color
- name="MapAvatarSelfColor"
- value="0.53125 0 0.498047 1" />
+ name="MapAvatarColor"
+ reference="White" />
<color
- name="MapFrustumColor"
- reference="White_10" />
+ name="MapAvatarFriendColor"
+ value="0.5 0.7 0.85 1" />
<color
- name="MapParcelOutlineColor"
- value="1 1 1 0.5" />
+ name="MapAvatarSelfColor"
+ value="0.53125 0 0.498047 1" />
<color
- name="MapTrackColor"
- reference="Red" />
+ name="MapFrustumColor"
+ reference="White_10" />
<color
- name="MapTrackColorUnder"
- reference="Blue" />
+ name="MapParcelOutlineColor"
+ value="1 1 1 0.5" />
<color
- name="MapTrackDisabledColor"
- value="0.5 0 0 1" />
+ name="MapTrackColor"
+ reference="Red" />
<color
- name="MenuBarBgColor"
- reference="MouseGray" />
+ name="MapTrackColorUnder"
+ reference="Blue" />
<color
- name="MenuBarGodBgColor"
- reference="FrogGreen" />
+ name="MapTrackDisabledColor"
+ value="0.5 0 0 1" />
<color
- name="MenuDefaultBgColor"
- reference="DkGray2" />
+ name="MenuBarBgColor"
+ reference="MouseGray" />
<color
- name="MenuItemDisabledColor"
- reference="LtGray_50" />
+ name="MenuBarGodBgColor"
+ reference="FrogGreen" />
<color
- name="MenuItemEnabledColor"
- reference="LtGray" />
+ name="MenuDefaultBgColor"
+ reference="DkGray2" />
<color
- name="MenuItemHighlightBgColor"
- reference="EmphasisColor_35" />
+ name="MenuItemDisabledColor"
+ reference="LtGray_50" />
<color
- name="MenuItemFlashBgColor"
- reference="BeaconColor" />
+ name="MenuItemEnabledColor"
+ reference="LtGray" />
<color
- name="MenuItemHighlightFgColor"
- reference="White" />
+ name="MenuItemHighlightBgColor"
+ reference="EmphasisColor_35" />
<color
- name="MenuNonProductionBgColor"
- reference="Black" />
+ name="MenuItemFlashBgColor"
+ reference="BeaconColor" />
<color
- name="MenuNonProductionGodBgColor"
- value="0.263 0.325 0.345 1" />
+ name="MenuItemHighlightFgColor"
+ reference="White" />
<color
- name="MenuPopupBgColor"
- reference="DkGray2" />
+ name="MenuNonProductionBgColor"
+ reference="Black" />
<color
- name="ModelUploaderLabels"
- value="1 0.6 0 1" />
+ name="MenuNonProductionGodBgColor"
+ value="0.263 0.325 0.345 1" />
<color
- name="MultiSliderDisabledThumbColor"
- reference="Black" />
+ name="MenuPopupBgColor"
+ reference="DkGray2" />
<color
- name="MultiSliderThumbCenterColor"
- reference="White" />
+ name="ModelUploaderLabels"
+ value="1 0.6 0 1" />
<color
- name="MultiSliderThumbCenterSelectedColor"
- reference="Green" />
+ name="MultiSliderDisabledThumbColor"
+ reference="Black" />
<color
- name="MultiSliderThumbOutlineColor"
- reference="Unused?" />
+ name="MultiSliderThumbCenterColor"
+ reference="White" />
<color
- name="MultiSliderTrackColor"
- reference="LtGray" />
+ name="MultiSliderThumbCenterSelectedColor"
+ reference="Green" />
<color
- name="MultiSliderTriangleColor"
- reference="Yellow" />
- <!--
+ name="MultiSliderThumbOutlineColor"
+ reference="Unused?" />
<color
- name="NameTagBackground"
- value="0.85 0.85 0.85 0.80" />
- -->
+ name="MultiSliderTrackColor"
+ reference="LtGray" />
<color
- name="NameTagBackground"
- value="0.101 0.101 0.101 0.6" />
+ name="MultiSliderTriangleColor"
+ reference="Yellow" />
+ <!--
<color
- name="NameTagChat"
- reference="White" />
+ name="NameTagBackground"
+ value="0.85 0.85 0.85 0.80" />
+ -->
<color
- name="NameTagFriend"
- value="0.5 0.7 0.85 1" />
+ name="NameTagBackground"
+ value="0.101 0.101 0.101 0.6" />
<color
- name="NameTagLegacy"
- reference="White" />
+ name="NameTagChat"
+ reference="White" />
<color
- name="NameTagMatch"
- reference="White" />
+ name="NameTagFriend"
+ reference="SelectionColor" />
<color
- name="NameTagMismatch"
- reference="White" />
+ name="NameTagLegacy"
+ reference="White" />
<color
- name="NetMapBackgroundColor"
- value="0 0 0 1" />
+ name="NameTagMatch"
+ reference="White" />
<color
- name="NetMapGroupOwnAboveWater"
- value="0.85 0 0.85 1" />
+ name="NameTagMismatch"
+ reference="White" />
<color
- name="NetMapGroupOwnBelowWater"
- value="0.63 0 0.63 1" />
+ name="NetMapBackgroundColor"
+ value="0 0 0 1" />
<color
- name="NetMapOtherOwnAboveWater"
- value="0.24 0.24 0.24 1" />
+ name="NetMapGroupOwnAboveWater"
+ value="0.85 0 0.85 1" />
<color
- name="NetMapOtherOwnBelowWater"
- value="0.12 0.12 0.12 1" />
+ name="NetMapGroupOwnBelowWater"
+ value="0.63 0 0.63 1" />
<color
- name="NetMapYouOwnAboveWater"
- value="0 0.85 0.85 1" />
+ name="NetMapOtherOwnAboveWater"
+ value="0.24 0.24 0.24 1" />
<color
- name="NetMapYouOwnBelowWater"
- value="0 0.63 0.63 1" />
+ name="NetMapOtherOwnBelowWater"
+ value="0.12 0.12 0.12 1" />
<color
- name="NotifyBoxColor"
- value="LtGray" />
+ name="NetMapYouOwnAboveWater"
+ value="0 0.85 0.85 1" />
<color
- name="NotifyCautionBoxColor"
- value="1 0.82 0.46 1" />
+ name="NetMapYouOwnBelowWater"
+ value="0 0.63 0.63 1" />
<color
- name="NotifyCautionWarnColor"
- reference="White" />
+ name="NotifyBoxColor"
+ value="LtGray" />
<color
- name="NotifyTextColor"
- reference="White" />
+ name="NotifyCautionBoxColor"
+ value="1 0.82 0.46 1" />
<color
- name="ObjectBubbleColor"
- reference="DkGray_66" />
+ name="NotifyCautionWarnColor"
+ reference="White" />
<color
- name="ObjectChatColor"
- reference="LtYellow" />
+ name="NotifyTextColor"
+ reference="White" />
<color
- name="OverdrivenColor"
- reference="Red" />
+ name="ObjectBubbleColor"
+ reference="DkGray_66" />
<color
- name="PanelDefaultBackgroundColor"
- reference="DkGray" />
+ name="ObjectChatColor"
+ reference="LtYellow" />
<color
- name="PanelDefaultHighlightLight"
- reference="White_50" />
+ name="OverdrivenColor"
+ reference="Red" />
<color
- name="PanelFocusBackgroundColor"
- reference="DkGray2" />
+ name="PanelDefaultBackgroundColor"
+ reference="DkGray" />
<color
- name="PanelNotificationBackground"
- value="1 0.3 0.3 0" />
+ name="PanelDefaultHighlightLight"
+ reference="White_50" />
<color
- name="ParcelHoverColor"
- reference="White" />
+ name="PanelFocusBackgroundColor"
+ reference="DkGray2" />
<color
- name="PathfindingErrorColor"
- reference="LtRed" />
- <color
- name="PathfindingWarningColor"
- reference="DrYellow" />
- <color
- name="PathfindingGoodColor"
- reference="LtGreen" />
- <color
- name="MaterialErrorColor"
- reference="LtRed" />
- <color
- name="MaterialWarningColor"
- reference="DrYellow" />
- <color
- name="MaterialGoodColor"
- reference="LtGreen" />
- <color
- name="PathfindingDefaultBeaconColor"
- reference="Red_80" />
- <color
- name="PathfindingDefaultBeaconTextColor"
- reference="White" />
- <color
- name="PathfindingLinksetBeaconColor"
- reference="Blue_80" />
- <color
- name="PathfindingCharacterBeaconColor"
- reference="Red_80" />
- <color
- name="PieMenuBgColor"
- value="0.24 0.24 0.24 0.59" />
+ name="PanelNotificationBackground"
+ value="1 0.3 0.3 0" />
<color
- name="PieMenuLineColor"
- value="0 0 0 0.5" />
+ name="ParcelHoverColor"
+ reference="White" />
<color
- name="PieMenuSelectedColor"
- value="0.72 0.72 0.74 0.3" />
+ name="PathfindingErrorColor"
+ reference="LtRed" />
<color
- name="PropertyColorAuction"
- value="0.5 0 1 0.4" />
+ name="PathfindingWarningColor"
+ reference="DrYellow" />
<color
- name="PropertyColorAvail"
- reference="Transparent" />
+ name="PathfindingGoodColor"
+ reference="LtGreen" />
<color
- name="PropertyColorForSale"
- value="1 0.5 0 0.4" />
+ name="MaterialErrorColor"
+ reference="LtRed" />
<color
- name="PropertyColorGroup"
- value="0 0.72 0.72 0.4" />
+ name="MaterialWarningColor"
+ reference="DrYellow" />
<color
- name="PropertyColorOther"
- value="1 0 0 0.4" />
+ name="MaterialGoodColor"
+ reference="LtGreen" />
<color
- name="PropertyColorSelf"
- value="0 1 0 0.4" />
+ name="PathfindingDefaultBeaconColor"
+ reference="Red_80" />
<color
- name="ScriptBgReadOnlyColor"
- value="0.39 0.39 0.39 1" />
+ name="PathfindingDefaultBeaconTextColor"
+ reference="White" />
<color
- name="ScriptErrorColor"
- reference="Red" />
+ name="PathfindingLinksetBeaconColor"
+ reference="Blue_80" />
<color
- name="ScrollBGStripeColor"
- reference="Transparent" />
+ name="PathfindingCharacterBeaconColor"
+ reference="Red_80" />
<color
- name="ScrollBgReadOnlyColor"
- reference="Transparent" />
+ name="PieMenuBgColor"
+ value="0.24 0.24 0.24 0.59" />
<color
- name="ScrollBgWriteableColor"
- reference="White_05" />
+ name="PieMenuLineColor"
+ value="0 0 0 0.5" />
<color
- name="ScrollDisabledColor"
- reference="White_25" />
+ name="PieMenuSelectedColor"
+ value="0.72 0.72 0.74 0.3" />
<color
- name="ScrollHighlightedColor"
- reference="Unused?" />
+ name="PropertyColorAuction"
+ value="0.5 0 1 0.4" />
<color
- name="ScrollHoveredColor"
- reference="EmphasisColor_13" />
+ name="PropertyColorAvail"
+ reference="Transparent" />
<color
- name="ScrollSelectedBGColor"
- reference="EmphasisColor_35" />
+ name="PropertyColorForSale"
+ value="1 0.5 0 0.4" />
<color
- name="ScrollSelectedFGColor"
- reference="White" />
+ name="PropertyColorGroup"
+ value="0 0.72 0.72 0.4" />
<color
- name="ScrollUnselectedColor"
- reference="LtGray" />
+ name="PropertyColorOther"
+ value="1 0 0 0.4" />
<color
- name="ScrollbarThumbColor"
- reference="White" />
+ name="PropertyColorSelf"
+ value="0 1 0 0.4" />
<color
- name="ScrollbarTrackColor"
- reference="Black" />
+ name="ScriptBgReadOnlyColor"
+ value="0.39 0.39 0.39 1" />
<color
- name="SelectedOutfitTextColor"
- reference="EmphasisColor" />
+ name="ScriptErrorColor"
+ reference="Red" />
<color
- name="SearchableControlHighlightFontColor"
- value="1 0 0 1" />
+ name="ScrollBGStripeColor"
+ reference="Transparent" />
<color
- name="SearchableControlHighlightBgColor"
- value="0.5 0.1 0.1 1" />
+ name="ScrollBgReadOnlyColor"
+ reference="Transparent" />
<color
- name="SilhouetteChildColor"
- value="0.13 0.42 0.77 1" />
+ name="ScrollBgWriteableColor"
+ reference="White_05" />
<color
- name="SilhouetteParentColor"
- reference="Yellow" />
+ name="ScrollDisabledColor"
+ reference="White_25" />
<color
- name="SliderDisabledThumbColor"
- reference="White_25" />
+ name="ScrollHighlightedColor"
+ reference="Unused?" />
<color
- name="SliderThumbCenterColor"
- reference="White" />
+ name="ScrollSelectedBGColor"
+ reference="EmphasisColor_35" />
<color
- name="SliderThumbOutlineColor"
- reference="White" />
+ name="ScrollSelectedFGColor"
+ reference="White" />
<color
- name="SliderTrackColor"
- reference="Unused?" />
+ name="ScrollUnselectedColor"
+ reference="LtGray" />
<color
- name="SpeakingColor"
- reference="FrogGreen" />
+ name="ScrollbarThumbColor"
+ reference="White" />
<color
- name="SystemChatColor"
- reference="LtGray" />
+ name="ScrollbarTrackColor"
+ reference="Black" />
<color
- name="TextBgFocusColor"
- reference="White" />
+ name="SelectedOutfitTextColor"
+ reference="EmphasisColor" />
<color
- name="TextBgReadOnlyColor"
- reference="White_05" />
+ name="WornOutfitTextColor"
+ value="0.54 0.73 0.87 1" />
<color
- name="TextBgWriteableColor"
- reference="LtGray" />
+ name="SearchableControlHighlightFontColor"
+ value="1 0 0 1" />
<color
- name="TextCursorColor"
- reference="Black" />
+ name="SearchableControlHighlightBgColor"
+ value="0.5 0.1 0.1 1" />
<color
- name="TextDefaultColor"
- reference="Black" />
+ name="SilhouetteChildColor"
+ value="0.13 0.42 0.77 1" />
<color
- name="TextEmbeddedItemColor"
- value="0 0 0.5 1" />
+ name="SilhouetteParentColor"
+ reference="Yellow" />
<color
- name="TextEmbeddedItemReadOnlyColor"
- reference="Unused?" />
+ name="SliderDisabledThumbColor"
+ reference="White_25" />
<color
- name="TextFgColor"
- value="0.102 0.102 0.102 1" />
+ name="SliderThumbCenterColor"
+ reference="White" />
+ <color
+ name="SliderThumbOutlineColor"
+ reference="White" />
+ <color
+ name="SliderTrackColor"
+ reference="Unused?" />
<color
- name="TextFgReadOnlyColor"
- reference="LtGray" />
+ name="SpeakingColor"
+ reference="FrogGreen" />
+ <color
+ name="SystemChatColor"
+ reference="LtGray" />
+ <color
+ name="SelectedBgReadOnlyColor"
+ value="0.15 0.21 0.27 1" />
+ <color
+ name="TextBgFocusColor"
+ reference="White" />
<color
- name="TextFgTentativeColor"
- value="0.4 0.4 0.4 1" />
+ name="TextBgReadOnlyColor"
+ reference="White_05" />
<color
- name="TimeTextColor"
- reference="LtGray" />
+ name="TextBgWriteableColor"
+ reference="LtGray" />
<color
- name="TitleBarFocusColor"
- reference="White_10" />
+ name="TextCursorColor"
+ reference="Black" />
<color
- name="ToastBackground"
- value="0.3 0.3 0.3 0" />
+ name="TextDefaultColor"
+ reference="Black" />
<color
- name="ToolTipBgColor"
- value="0.937 0.89 0.655 1" />
+ name="TextEmbeddedItemColor"
+ value="0 0 0.5 1" />
<color
- name="ToolTipBorderColor"
- value="0.812 0.753 0.451 1" />
+ name="TextEmbeddedItemReadOnlyColor"
+ reference="Unused?" />
<color
- name="ToolTipTextColor"
- reference="DkGray2" />
+ name="TextFgColor"
+ value="0.102 0.102 0.102 1" />
<color
- name="InspectorTipTextColor"
- reference="LtGray" />
+ name="TextFgReadOnlyColor"
+ reference="LtGray" />
<color
- name="UserChatColor"
- reference="White" />
+ name="TextFgTentativeColor"
+ value="0.4 0.4 0.4 1" />
<color
- name="llOwnerSayChatColor"
- reference="LtOrange" />
+ name="TimeTextColor"
+ reference="LtGray" />
+ <color
+ name="TitleBarFocusColor"
+ reference="White_10" />
+ <color
+ name="ToastBackground"
+ value="0.3 0.3 0.3 0" />
+ <color
+ name="ToolTipBgColor"
+ value="0.937 0.89 0.655 1" />
+ <color
+ name="ToolTipBorderColor"
+ value="0.812 0.753 0.451 1" />
+ <color
+ name="ToolTipTextColor"
+ reference="DkGray2" />
+ <color
+ name="InspectorTipTextColor"
+ reference="LtGray" />
+ <color
+ name="UserChatColor"
+ reference="White" />
+ <color
+ name="llOwnerSayChatColor"
+ reference="LtOrange" />
<!-- New Colors -->
<color
- name="OutputMonitorMutedColor"
- reference="DkGray2" />
+ name="OutputMonitorMutedColor"
+ reference="DkGray2" />
+ <color
+ name="SysWellItemUnselected"
+ value="0 0 0 0" />
+ <color
+ name="SysWellItemSelected"
+ value="0.3 0.3 0.3 1.0" />
+ <color
+ name="ColorSwatchBorderColor"
+ value="0.45098 0.517647 0.607843 1"/>
<color
- name="SysWellItemUnselected"
- value="0 0 0 0" />
+ name="ColorSwatchBorderColorGray"
+ value="0.329 0.329 0.329 1"/>
<color
- name="SysWellItemSelected"
- value="0.3 0.3 0.3 1.0" />
+ name="ChatTeleportSeparatorColor"
+ reference="Black" />
<color
- name="ColorSwatchBorderColor"
- value="0.45098 0.517647 0.607843 1"/>
+ name="ChatTimestampColor"
+ reference="White" />
+ <color
+ name="MenuBarStreamingBgColor"
+ reference="DkGray" />
<color
- name="ChatTeleportSeparatorColor"
- reference="Black" />
+ name="MenuBarBetaBgColor"
+ reference="DkBlue" />
<color
- name="ChatTimestampColor"
- reference="White" />
+ name="MenuBarProjectBgColor"
+ reference="MdBlue" />
<color
- name="MenuBarBetaBgColor"
- reference="DkBlue" />
- <color
- name="MenuBarProjectBgColor"
- reference="MdBlue" />
- <color
- name="MenuBarTestBgColor"
- reference="DkRed" />
+ name="MenuBarTestBgColor"
+ reference="DkRed" />
<color
- name="MeshImportTableNormalColor"
- value="1 1 1 1"/>
+ name="MeshImportTableNormalColor"
+ value="1 1 1 1"/>
<color
- name="MeshImportTableHighlightColor"
- value="0.2 0.8 1 1"/>
+ name="MeshImportTableHighlightColor"
+ value="0.2 0.8 1 1"/>
<color
- name="DirectChatColor"
- reference="LtOrange" />
+ name="DirectChatColor"
+ reference="LtOrange" />
<color
- name="ToolbarDropZoneColor"
- value=".48 .69 1 .5" />
+ name="ToolbarDropZoneColor"
+ value=".48 .69 1 .5" />
<color
- name="PanelNotificationListItem"
- value="0.3 0.3 0.3 .3" />
+ name="PanelNotificationListItem"
+ value="0.3 0.3 0.3 .3" />
- <!-- profiles -->
+ <!-- profiles -->
<color
name="StatusUserOnline"
reference="White" />
@@ -913,110 +928,113 @@
<color
name="GroupHiddenInProfile"
reference="Gray" />
-
- <!-- 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"/>
- <!--Resize bar colors -->
+ <!-- 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"/>
+
+ <!--Resize bar colors -->
- <color
- name="ResizebarBorderLight"
- value="0.231 0.231 0.231 1"/>
+ <color
+ name="ResizebarBorderLight"
+ value="0.231 0.231 0.231 1"/>
- <color
- name="ResizebarBorderDark"
- value="0.133 0.133 0.133 1"/>
+ <color
+ name="ResizebarBorderDark"
+ value="0.133 0.133 0.133 1"/>
- <color
- name="ResizebarBody"
- value="0.208 0.208 0.208 1"/>
+ <color
+ name="ResizebarBody"
+ value="0.208 0.208 0.208 1"/>
- <!-- syntax highlighting (LSL Scripts) -->
- <color
- name="ScriptText"
- reference="Black" />
- <color
- name="ScriptBackground"
- reference="White" />
- <color
- name="ScriptCursorColor"
- reference="Black" />
- <color
- name="SyntaxLslComment"
- value="0 0.5 0 1" />
- <color
- name="SyntaxLslConstant"
- value="0 0.6 0.6 1" />
- <color
- name="SyntaxLslControlFlow"
- value="0.4 0 0.8 1" />
- <color
- name="SyntaxLslControlLabel"
- value="0 0 0.8 1" />
- <color
- name="SyntaxLslDataType"
- value="0.8 0.4 0 1" />
- <color
- name="SyntaxLslDeprecated"
- value="0.9 0.0 0.66, 1" />
- <color
- name="SyntaxLslEvent"
- value="0 0.3 0.5 1" />
- <color
- name="SyntaxLslFunction"
- value="0.3 0 0.5 1" />
- <color
- name="SyntaxLslGodMode"
- value="0.7 .2 .35 1" />
- <color
- name="SyntaxLslStringLiteral"
- value="1 0.14 0 1" />
- <color
- name="OutfitGalleryItemSelected"
- reference="EmphasisColor_35" />
- <color
- name="OutfitGalleryItemWorn"
- reference="EmphasisColor_13" />
- <color
- name="OutfitGalleryItemUnselected"
- value="0.4 0.4 0.4 1" />
- <color
- name="PanelGray"
- value="0.27 0.27 0.27 1" />
- <color
- name="PerformanceMid"
- value="1 0.8 0 1" />
- <color
- name="OutfitSnapshotMacMask"
- value="0.115 0.115 0.115 1"/>
- <color
- name="OutfitSnapshotMacMask2"
- value="0.1 0.1 0.1 1"/>
- <color
- name="ChatMentionFont"
- value="0.3 0.82 1 1" />
- <color
- name="ChatMentionHighlight"
- value="0.82 0.91 0.98 0.15" />
- <color
- name="ChatSelfMentionHighlight"
- value="1 1 0 0.35" />
- <color
- name="MentionFlashBgColor"
- value="1 1 0 0.5" />
-</colors>
+ <!-- syntax highlighting (LSL Scripts) -->
+ <color
+ name="ScriptText"
+ reference="Black" />
+ <color
+ name="ScriptBackground"
+ reference="White" />
+ <color
+ name="ScriptCursorColor"
+ reference="Black" />
+ <color
+ name="SyntaxLslComment"
+ value="0 0.5 0 1" />
+ <color
+ name="SyntaxLslConstant"
+ value="0 0.6 0.6 1" />
+ <color
+ name="SyntaxLslControlFlow"
+ value="0.4 0 0.8 1" />
+ <color
+ name="SyntaxLslControlLabel"
+ value="0 0 0.8 1" />
+ <color
+ name="SyntaxLslDataType"
+ value="0.8 0.4 0 1" />
+ <color
+ name="SyntaxLslDeprecated"
+ value="0.9 0.0 0.66, 1" />
+ <color
+ name="SyntaxLslEvent"
+ value="0 0.3 0.5 1" />
+ <color
+ name="SyntaxLslFunction"
+ value="0.3 0 0.5 1" />
+ <color
+ name="SyntaxLslGodMode"
+ value="0.7 .2 .35 1" />
+ <color
+ name="SyntaxLslStringLiteral"
+ value="1 0.14 0 1" />
+ <color
+ name="OutfitGalleryItemSelected"
+ value="0.26 0.36 0.47 1"/>
+ <color
+ name="OutfitGalleryItemWorn"
+ reference="EmphasisColor_13" />
+ <color
+ name="OutfitGalleryItemUnselected"
+ value="0.4 0.4 0.4 1" />
+ <color
+ name="PanelGray"
+ value="0.27 0.27 0.27 1" />
+ <color
+ name="PanelDark"
+ value="0.078 0.078 0.078 1" />
+ <color
+ name="PerformanceMid"
+ value="1 0.8 0 1" />
+ <color
+ name="OutfitSnapshotMacMask"
+ value="0.115 0.115 0.115 1"/>
+ <color
+ name="OutfitSnapshotMacMask2"
+ value="0.1 0.1 0.1 1"/>
+ <color
+ name="ChatMentionFont"
+ reference="EmphasisColor" />
+ <color
+ name="ChatMentionHighlight"
+ value="0.82 0.91 0.98 0.10" />
+ <color
+ name="ChatSelfMentionHighlight"
+ value="0.82 0.91 0.98 0.10" />
+ <color
+ name="MentionFlashBgColor"
+ value="1 1 0 0.5" />
+ </colors>
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
index 3b7f83fbab..512bd3b64e 100644
--- a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png
index 438b4912f8..b1012e505e 100644
--- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png
index 693adc4781..49cdadded7 100644
--- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png
index 818b34d40f..9afe58dcd1 100644
--- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png
index 84711ddc29..01f187b372 100644
--- a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png
+++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png
index 9b9468c574..40a1d8faf4 100644
--- a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png
+++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cone_Selected.png b/indra/newview/skins/default/textures/build/Object_Cone_Selected.png
index 0f04cb2f28..051c85d05d 100644
--- a/indra/newview/skins/default/textures/build/Object_Cone_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Cone_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cube_Selected.png b/indra/newview/skins/default/textures/build/Object_Cube_Selected.png
index 2a10237771..3560b36ec6 100644
--- a/indra/newview/skins/default/textures/build/Object_Cube_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Cube_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png b/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png
index ee6db5d64e..8f752aaf4c 100644
--- a/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Grass_Selected.png b/indra/newview/skins/default/textures/build/Object_Grass_Selected.png
index 37f35f9339..90844abe94 100644
--- a/indra/newview/skins/default/textures/build/Object_Grass_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Grass_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png
index ad6ba66bed..66e1c45567 100644
--- a/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png
index 03a47494f5..48ae5969a1 100644
--- a/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png
index daefae7389..eff8a231d6 100644
--- a/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Prism_Selected.png b/indra/newview/skins/default/textures/build/Object_Prism_Selected.png
index 73470c7af9..ab7921b97d 100644
--- a/indra/newview/skins/default/textures/build/Object_Prism_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Prism_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png b/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png
index 361c915231..446951d992 100644
--- a/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Ring_Selected.png b/indra/newview/skins/default/textures/build/Object_Ring_Selected.png
index 49b76d137e..a23e6dba50 100644
--- a/indra/newview/skins/default/textures/build/Object_Ring_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Ring_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png b/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png
index 473b90e867..daf39a658c 100644
--- a/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png b/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png
index 20278c8f6d..28175f107e 100644
--- a/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Torus_Selected.png b/indra/newview/skins/default/textures/build/Object_Torus_Selected.png
index e6cad859fd..049ca64f05 100644
--- a/indra/newview/skins/default/textures/build/Object_Torus_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Torus_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tree_Selected.png b/indra/newview/skins/default/textures/build/Object_Tree_Selected.png
index 52b4f535f8..8b45d668aa 100644
--- a/indra/newview/skins/default/textures/build/Object_Tree_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Tree_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tube_Selected.png b/indra/newview/skins/default/textures/build/Object_Tube_Selected.png
index 4469814e1a..c94a984c41 100644
--- a/indra/newview/skins/default/textures/build/Object_Tube_Selected.png
+++ b/indra/newview/skins/default/textures/build/Object_Tube_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Selected.png b/indra/newview/skins/default/textures/containers/Accordion_Selected.png
index 2222954332..ab852007ab 100644
--- a/indra/newview/skins/default/textures/containers/Accordion_Selected.png
+++ b/indra/newview/skins/default/textures/containers/Accordion_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabLeft_Flat_Off.png b/indra/newview/skins/default/textures/containers/TabLeft_Flat_Off.png
new file mode 100644
index 0000000000..d6c6bc41ec
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabLeft_Flat_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabLeft_Flat_Selected.png b/indra/newview/skins/default/textures/containers/TabLeft_Flat_Selected.png
new file mode 100644
index 0000000000..91e44a4ffe
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabLeft_Flat_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Off.png b/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Off.png
new file mode 100644
index 0000000000..826d939954
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Selected.png
new file mode 100644
index 0000000000..c023486e3e
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_First_Flat_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Off.png
new file mode 100644
index 0000000000..6996c3e065
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Selected.png
new file mode 100644
index 0000000000..c96a80b9eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Last_Flat_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Off.png
new file mode 100644
index 0000000000..6e5e6ba15d
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Selected.png
new file mode 100644
index 0000000000..a6944e1952
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Flat_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Flash.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Flash.png
index 9f1e2a469d..e979bd9417 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Flash.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Flash.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png
index f347505772..3111cbc338 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png
index fd24e5b430..f450347bc4 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png
index dccf543a9a..0c65883e7f 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Flash.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Flash.png
index dd73d655e9..48f6615c30 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Flash.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Flash.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png
index cf30330f1c..cd6d11c5a6 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png
index 6ac1ce3ffb..f72cb1d20b 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png
index 8b40051c0b..62f82879cf 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Flash.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Flash.png
index f6b775c2a0..20c6caf05b 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Flash.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Flash.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png
index d4881e21d3..0c8e9f1a36 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png
index bf2a72d6f4..1b0fcc944d 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png
index c3833ad7fa..afd846735f 100644
--- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Info_Over.png b/indra/newview/skins/default/textures/icons/Info_Over.png
index 6399cd6715..1d00c2c175 100644
--- a/indra/newview/skins/default/textures/icons/Info_Over.png
+++ b/indra/newview/skins/default/textures/icons/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_SysClosed.png b/indra/newview/skins/default/textures/icons/Inv_SysClosed.png
index 2550cae0d4..19afa94cc4 100644
--- a/indra/newview/skins/default/textures/icons/Inv_SysClosed.png
+++ b/indra/newview/skins/default/textures/icons/Inv_SysClosed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_SysOpen.png b/indra/newview/skins/default/textures/icons/Inv_SysOpen.png
index 5b56d86184..7ca0f5a849 100644
--- a/indra/newview/skins/default/textures/icons/Inv_SysOpen.png
+++ b/indra/newview/skins/default/textures/icons/Inv_SysOpen.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/SL_Logo.png b/indra/newview/skins/default/textures/icons/SL_Logo.png
index 5e376c72f9..7b147df369 100644
--- a/indra/newview/skins/default/textures/icons/SL_Logo.png
+++ b/indra/newview/skins/default/textures/icons/SL_Logo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/back_arrow_off.png b/indra/newview/skins/default/textures/icons/back_arrow_off.png
index c9c7bf5fec..de4b89c28b 100644
--- a/indra/newview/skins/default/textures/icons/back_arrow_off.png
+++ b/indra/newview/skins/default/textures/icons/back_arrow_off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/back_arrow_over.png b/indra/newview/skins/default/textures/icons/back_arrow_over.png
index ee6acc2653..21cc3c2781 100644
--- a/indra/newview/skins/default/textures/icons/back_arrow_over.png
+++ b/indra/newview/skins/default/textures/icons/back_arrow_over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/back_arrow_press.png b/indra/newview/skins/default/textures/icons/back_arrow_press.png
index 9876b4eeb7..de4b89c28b 100644
--- a/indra/newview/skins/default/textures/icons/back_arrow_press.png
+++ b/indra/newview/skins/default/textures/icons/back_arrow_press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/check_mark.png b/indra/newview/skins/default/textures/icons/check_mark.png
index 95ca9dbd6c..00ec32964d 100644
--- a/indra/newview/skins/default/textures/icons/check_mark.png
+++ b/indra/newview/skins/default/textures/icons/check_mark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/hand.png b/indra/newview/skins/default/textures/icons/hand.png
index 5fbdb70c2b..6effb7c77d 100644
--- a/indra/newview/skins/default/textures/icons/hand.png
+++ b/indra/newview/skins/default/textures/icons/hand.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/see_me_online.png b/indra/newview/skins/default/textures/icons/see_me_online.png
index adc37f5528..51d369003c 100644
--- a/indra/newview/skins/default/textures/icons/see_me_online.png
+++ b/indra/newview/skins/default/textures/icons/see_me_online.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/locked_image_dark.png b/indra/newview/skins/default/textures/locked_image_dark.png
new file mode 100644
index 0000000000..b952f2cfb0
--- /dev/null
+++ b/indra/newview/skins/default/textures/locked_image_dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png
index fce54942d3..cbb78cd514 100644
--- a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png
index 8cc3f02c5a..6b4092bf49 100644
--- a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Off.png b/indra/newview/skins/default/textures/navbar/Info_Off.png
index 6399cd6715..ff26c7f55d 100644
--- a/indra/newview/skins/default/textures/navbar/Info_Off.png
+++ b/indra/newview/skins/default/textures/navbar/Info_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Over.png b/indra/newview/skins/default/textures/navbar/Info_Over.png
index a296d2014f..a45a3849f7 100644
--- a/indra/newview/skins/default/textures/navbar/Info_Over.png
+++ b/indra/newview/skins/default/textures/navbar/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Press.png b/indra/newview/skins/default/textures/navbar/Info_Press.png
index 2afc4a9143..8e1f64609e 100644
--- a/indra/newview/skins/default/textures/navbar/Info_Press.png
+++ b/indra/newview/skins/default/textures/navbar/Info_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png
index c61dcde58c..19a73beef7 100644
--- a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png
+++ b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Row_Selection.png b/indra/newview/skins/default/textures/navbar/Row_Selection.png
index cfc31f8d32..0eeb4f494c 100644
--- a/indra/newview/skins/default/textures/navbar/Row_Selection.png
+++ b/indra/newview/skins/default/textures/navbar/Row_Selection.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/square_selection.png b/indra/newview/skins/default/textures/square_selection.png
new file mode 100644
index 0000000000..9f344c4842
--- /dev/null
+++ b/indra/newview/skins/default/textures/square_selection.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index a8fc8faa44..b84d9cf780 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -124,7 +124,9 @@ with the same filename but different name
<texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
<texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />
<texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" />
+ <texture name="Checkbox_Slim_Off" file_name="widgets/Checkbox_Slim_Off.png" preload="true" />
<texture name="Checkbox_On" file_name="widgets/Checkbox_On.png" preload="true" />
+ <texture name="Checkbox_Slim_On" file_name="widgets/Checkbox_Slim_On.png" preload="true" />
<texture name="Checkbox_On_Press" file_name="widgets/Checkbox_On_Press.png" preload="true" />
<texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" />
<texture name="Check_Mark" file_name="icons/check_mark.png" preload="true" />
@@ -174,6 +176,8 @@ with the same filename but different name
<texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Arrow" file_name="widgets/ComboButton_Arrow.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Transparent" file_name="widgets/ComboButton_Transparent.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="Container" file_name="containers/Container.png" preload="false" />
@@ -561,15 +565,16 @@ with the same filename but different name
<texture name="PushButton_On" file_name="widgets/PushButton_On.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_On_Selected" file_name="widgets/PushButton_On_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Over" file_name="widgets/PushButton_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
- <texture name="PushButton_Press" file_name="widgets/PushButton_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
- <texture name="PushButton_Selected" file_name="widgets/PushButton_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected" file_name="widgets/PushButton_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Selected_Press" file_name="widgets/PushButton_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Selected_Disabled" file_name="widgets/PushButton_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Login" file_name="widgets/PushButton_Login.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Login_Over" file_name="widgets/PushButton_Login_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="PushButton_Login_Pressed" file_name="widgets/PushButton_Login_Pressed.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
-
+ <texture name="PushButton_Sign" file_name="widgets/PushButton_Sign.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Sign_Over" file_name="widgets/PushButton_Sign_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Sign_Pressed" file_name="widgets/PushButton_Sign_Pressed.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="RadioButton_Press" file_name="widgets/RadioButton_Press.png" preload="true" />
<texture name="RadioButton_On_Press" file_name="widgets/RadioButton_On_Press.png" preload="true" />
@@ -650,6 +655,8 @@ with the same filename but different name
<texture name="OBJECT_Icon" file_name="icons/object_icon.png" preload="true" />
<texture name="Unknown_Icon" file_name="icons/unknown_icon.png" preload="true" />
+ <texture name="Square_Selection" file_name="square_selection.png" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
+
<texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
<texture name="Snapshot_Download" file_name="snapshot_download.png" preload="false" />
<texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" />
@@ -658,6 +665,7 @@ with the same filename but different name
<texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" />
<texture name="login_mp_logo" file_name="windows/login_mp_logo.png" preload="true" />
+ <texture name="login_mp_logo_horizontal" file_name="windows/login_mp_logo_horizontal.png" preload="true" />
<texture name="login_mp_logo_small" file_name="windows/login_mp_logo_small.png" preload="true" />
<texture name="first_login_image" file_name="windows/first_login_image.jpg" preload="true" />
@@ -687,6 +695,15 @@ with the same filename but different name
<texture name="TabIcon_Places_Off" file_name="taskpanel/TabIcon_Places_Off.png" preload="false" />
<texture name="TabIcon_Things_Off" file_name="taskpanel/TabIcon_Things_Off.png" preload="false" />
+ <texture name="TabLeft_Flat_Off" file_name="containers/TabLeft_Flat_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="TabLeft_Flat_Selected" file_name="containers/TabLeft_Flat_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="TabTop_First_Flat_Off" file_name="containers/TabTop_First_Flat_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Last_Flat_Off" file_name="containers/TabTop_Last_Flat_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Middle_Flat_Off" file_name="containers/TabTop_Middle_Flat_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_First_Flat_Selected" file_name="containers/TabTop_First_Flat_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Last_Flat_Selected" file_name="containers/TabTop_Last_Flat_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Middle_Flat_Selected" file_name="containers/TabTop_Middle_Flat_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+
<texture name="TabTop_Right_Off" file_name="containers/TabTop_Right_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
<texture name="TabTop_Right_Selected" file_name="containers/TabTop_Right_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
<texture name="TabTop_Right_Flashing" file_name="containers/TabTop_Right_Flashing.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
@@ -704,7 +721,9 @@ with the same filename but different name
<texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
<texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
<texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Highlight" file_name="widgets/TextField_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
<texture name="TextField_Search_Highlight" file_name="widgets/TextField_Search_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Transparent" file_name="widgets/TextField_Transparent.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="Thumbnail_Fallback" file_name="icons/thumbnail_fallback_icon.png" preload="true" />
@@ -780,13 +799,13 @@ with the same filename but different name
<texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
- <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true"
+ <texture name="Window_Background" file_name="windows/Window_NoTitle_Background.png" preload="true"
scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
- <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+ <texture name="Window_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true"
scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
- <texture name="Window_NoTitle_Background" file_name="windows/Window_Background.png" preload="true"
+ <texture name="Window_NoTitle_Background" file_name="windows/Window_NoTitle_Background.png" preload="true"
scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
- <texture name="Window_NoTitle_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+ <texture name="Window_NoTitle_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true"
scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
<texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" />
@@ -872,6 +891,7 @@ with the same filename but different name
<texture name="badge_warn.j2c" />
<texture name="badge_ok.j2c" />
<texture name="materials_ui_x_24.png" />
+ <texture name="locked_image" file_name="locked_image_dark.png" preload="true"/>
<texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" />
<texture name="Progress_2" file_name="icons/Progress_2.png" preload="true" />
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png b/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png
index 8439f82e29..6852706a80 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Off.png b/indra/newview/skins/default/textures/widgets/Checkbox_Off.png
index cb9a04d84f..6c237f973a 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_Off.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On.png b/indra/newview/skins/default/textures/widgets/Checkbox_On.png
index 0ec090504a..de87071c05 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_On.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png b/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png
index 5759f7de69..702351e03b 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png b/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png
index ba46e91c55..7be2cac5e1 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Press.png b/indra/newview/skins/default/textures/widgets/Checkbox_Press.png
index 5f5a33d878..a533debf1e 100644
--- a/indra/newview/skins/default/textures/widgets/Checkbox_Press.png
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Slim_Off.png b/indra/newview/skins/default/textures/widgets/Checkbox_Slim_Off.png
new file mode 100644
index 0000000000..99af0397d5
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Slim_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Slim_On.png b/indra/newview/skins/default/textures/widgets/Checkbox_Slim_On.png
new file mode 100644
index 0000000000..cabecf1467
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Slim_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Arrow.png b/indra/newview/skins/default/textures/widgets/ComboButton_Arrow.png
new file mode 100644
index 0000000000..7961967458
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Arrow.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png b/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png
index ebeb813349..5b2bc7b163 100644
--- a/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Off.png b/indra/newview/skins/default/textures/widgets/ComboButton_Off.png
index 8c315a9d25..71c16e8414 100644
--- a/indra/newview/skins/default/textures/widgets/ComboButton_Off.png
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png
index 15afcb04a1..715b401ce5 100644
--- a/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Transparent.png b/indra/newview/skins/default/textures/widgets/ComboButton_Transparent.png
new file mode 100644
index 0000000000..4b978877e1
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Transparent.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png
index 34edea9421..9e74524be4 100644
--- a/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png
index 9583f05507..aa8865c33d 100644
--- a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png b/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png
index 9a69f7e0d9..fff0cfaff2 100644
--- a/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Off.png b/indra/newview/skins/default/textures/widgets/DropDown_Off.png
index b118e7a7d4..9f6a2313b9 100644
--- a/indra/newview/skins/default/textures/widgets/DropDown_Off.png
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_On.png b/indra/newview/skins/default/textures/widgets/DropDown_On.png
index 3613e42a3f..be40e7104c 100644
--- a/indra/newview/skins/default/textures/widgets/DropDown_On.png
+++ b/indra/newview/skins/default/textures/widgets/DropDown_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Press.png b/indra/newview/skins/default/textures/widgets/DropDown_Press.png
index ec0ffc2e88..b6bf4d1c22 100644
--- a/indra/newview/skins/default/textures/widgets/DropDown_Press.png
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Over.png b/indra/newview/skins/default/textures/widgets/ListItem_Over.png
index 8c80522232..9316567e7b 100644
--- a/indra/newview/skins/default/textures/widgets/ListItem_Over.png
+++ b/indra/newview/skins/default/textures/widgets/ListItem_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Select.png b/indra/newview/skins/default/textures/widgets/ListItem_Select.png
index b27e0ee787..cd65d347d6 100644
--- a/indra/newview/skins/default/textures/widgets/ListItem_Select.png
+++ b/indra/newview/skins/default/textures/widgets/ListItem_Select.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
index de71f763d3..ea45cfe3b7 100644
--- a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
index 6020fadc5a..0e1fd747fc 100644
--- a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ProgressBar.png b/indra/newview/skins/default/textures/widgets/ProgressBar.png
index 492d9b6fc4..4d0d123987 100644
--- a/indra/newview/skins/default/textures/widgets/ProgressBar.png
+++ b/indra/newview/skins/default/textures/widgets/ProgressBar.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png b/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png
index e99ec4b14b..157b404c08 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Login.png b/indra/newview/skins/default/textures/widgets/PushButton_Login.png
index 8e7d932ab1..d6ba983674 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Login.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Login.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Login_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Login_Over.png
index 038ba23be2..e3161b1a26 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Login_Over.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Login_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Login_Pressed.png b/indra/newview/skins/default/textures/widgets/PushButton_Login_Pressed.png
index 828aa1a139..bd4174c3d4 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Login_Pressed.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Login_Pressed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Off.png b/indra/newview/skins/default/textures/widgets/PushButton_Off.png
index c74cea62d3..daf448a6e1 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Off.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On.png b/indra/newview/skins/default/textures/widgets/PushButton_On.png
index e387c7e313..5bfb126ea8 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_On.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Over.png
index 34a64a3ade..c27178f061 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Over.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Press.png
index 79fc601f27..45b55fa518 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Press.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png
index e2818da352..062fcf9246 100644
--- a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Sign.png b/indra/newview/skins/default/textures/widgets/PushButton_Sign.png
new file mode 100644
index 0000000000..f1c27f8c9b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Sign.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Sign_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Sign_Over.png
new file mode 100644
index 0000000000..efef8bebad
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Sign_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Sign_Pressed.png b/indra/newview/skins/default/textures/widgets/PushButton_Sign_Pressed.png
new file mode 100644
index 0000000000..ec3409e8b8
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Sign_Pressed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png b/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png
index 32ec25fe0e..d2a26f2bca 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Off.png b/indra/newview/skins/default/textures/widgets/RadioButton_Off.png
index 5d267af5dc..68c26b65b3 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_Off.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On.png b/indra/newview/skins/default/textures/widgets/RadioButton_On.png
index e6bf0db157..01bd9ba3be 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_On.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png b/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png
index 72aae43618..d22ac0ec41 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png b/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png
index f3883b82b3..11a0704aa8 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Press.png b/indra/newview/skins/default/textures/widgets/RadioButton_Press.png
index 0025256045..df29db100d 100644
--- a/indra/newview/skins/default/textures/widgets/RadioButton_Press.png
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png
index 9afc907c1c..eb9563e0ee 100644
--- a/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png
index ede643e528..144a7cba25 100644
--- a/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png
index ef50fb5d51..26e2fe53aa 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png
index 191dbf08fc..e9f15dbad4 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png
index d5882bce85..d66d020587 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png
index ddaab1cfcd..1104f6879d 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png
index c8634b1294..753c38bdad 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png
index 65d082b993..8ad008ba51 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png
index 12f55c599e..ca5f84a088 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
index 6a023156c5..9b1531a11e 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
index 457644e69a..28f5bf37f7 100644
--- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
index 5cfa3ae4e1..d2a26f2bca 100644
--- a/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png
index 66cdcbeb94..68c26b65b3 100644
--- a/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png
index 0bf8e43e81..df29db100d 100644
--- a/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png b/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png
index 720830f83f..65cfaf4c62 100644
--- a/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png
+++ b/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png
index ff21034095..2421b687f7 100644
--- a/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png
index e888e1e045..cbbacb6a5b 100644
--- a/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png
index 133845bdbc..691a8ff13f 100644
--- a/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png
index dffd557bbd..daea2b21f8 100644
--- a/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Active.png b/indra/newview/skins/default/textures/widgets/TextField_Active.png
index 66c3867b81..c3d9a645c6 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Active.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Disabled.png b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png
index baf747f581..5355fa3223 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Highlight.png b/indra/newview/skins/default/textures/widgets/TextField_Highlight.png
new file mode 100644
index 0000000000..f1658b9a87
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Highlight.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Off.png b/indra/newview/skins/default/textures/widgets/TextField_Off.png
index a35562f950..b830e6efeb 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Off.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png
index 572535f1ab..270dd72823 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png
index 94b4b158f7..ca531b2abc 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
index 7768da04e8..3869ccb7f2 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png
index fccd38c807..958cea5c5f 100644
--- a/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Transparent.png b/indra/newview/skins/default/textures/widgets/TextField_Transparent.png
new file mode 100644
index 0000000000..1735184387
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Transparent.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_back.png b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png
index 03d1e805e1..1e2ce7bc83 100644
--- a/indra/newview/skins/default/textures/widgets/track_control_moon_back.png
+++ b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_front.png b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png
index cdc52fe08a..25f2914ecc 100644
--- a/indra/newview/skins/default/textures/widgets/track_control_moon_front.png
+++ b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sphere.png b/indra/newview/skins/default/textures/widgets/track_control_sphere.png
index b6592b5992..adfb51edd2 100644
--- a/indra/newview/skins/default/textures/widgets/track_control_sphere.png
+++ b/indra/newview/skins/default/textures/widgets/track_control_sphere.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sun_back.png b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png
index b3191ccc5d..98bae90332 100644
--- a/indra/newview/skins/default/textures/widgets/track_control_sun_back.png
+++ b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_I.png b/indra/newview/skins/default/textures/windows/Inspector_I.png
index 0d1719c66f..d51cf43051 100644
--- a/indra/newview/skins/default/textures/windows/Inspector_I.png
+++ b/indra/newview/skins/default/textures/windows/Inspector_I.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png
index f19fb0300b..5606af74b4 100644
--- a/indra/newview/skins/default/textures/windows/Window_Background.png
+++ b/indra/newview/skins/default/textures/windows/Window_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Foreground.png b/indra/newview/skins/default/textures/windows/Window_Foreground.png
index 15d2ff72b6..28bab49869 100644
--- a/indra/newview/skins/default/textures/windows/Window_Foreground.png
+++ b/indra/newview/skins/default/textures/windows/Window_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png
new file mode 100644
index 0000000000..6880008fff
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png
new file mode 100644
index 0000000000..978b51f5a7
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/login_mp_logo.png b/indra/newview/skins/default/textures/windows/login_mp_logo.png
index 7526374ba2..e2b472565b 100644
--- a/indra/newview/skins/default/textures/windows/login_mp_logo.png
+++ b/indra/newview/skins/default/textures/windows/login_mp_logo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/login_mp_logo_horizontal.png b/indra/newview/skins/default/textures/windows/login_mp_logo_horizontal.png
new file mode 100644
index 0000000000..5bc7d77d15
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/login_mp_logo_horizontal.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/login_mp_logo_small.png b/indra/newview/skins/default/textures/windows/login_mp_logo_small.png
index 779d8ff649..36c84f478a 100644
--- a/indra/newview/skins/default/textures/windows/login_mp_logo_small.png
+++ b/indra/newview/skins/default/textures/windows/login_mp_logo_small.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/da/floater_joystick.xml b/indra/newview/skins/default/xui/da/floater_joystick.xml
index 49e1397e9f..c756bc6969 100644
--- a/indra/newview/skins/default/xui/da/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/da/floater_joystick.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Joystick" title="JOYSTICK OPSÆTNING">
<check_box label="Aktiver Joystick:" name="enable_joystick"/>
- <spinner label="X akse mapping" name="JoystickAxis1"/>
- <spinner label="Y akse mapping" name="JoystickAxis2"/>
- <spinner label="Z akse mapping" name="JoystickAxis0"/>
- <spinner label="Hældning mapping" name="JoystickAxis4"/>
- <spinner label="Drejning mapping" name="JoystickAxis5"/>
- <spinner label="Rulning mapping" name="JoystickAxis3"/>
- <spinner label="Zoom mapping" name="JoystickAxis6"/>
+ <spinner label="X akse mapping" name="JoystickAxis1" label_width="115" width="155"/>
+ <spinner label="Y akse mapping" name="JoystickAxis2" label_width="115" width="155"/>
+ <spinner label="Z akse mapping" name="JoystickAxis0" label_width="115" width="155"/>
+ <spinner label="Hældning mapping" name="JoystickAxis4" label_width="115" width="155"/>
+ <spinner label="Drejning mapping" name="JoystickAxis5" label_width="115" width="155"/>
+ <spinner label="Rulning mapping" name="JoystickAxis3" label_width="115" width="155"/>
+ <spinner label="Zoom mapping" name="JoystickAxis6" label_width="115" width="155"/>
<check_box label="Direkte zoom" name="ZoomDirect"/>
<check_box label="3D Cursor" name="Cursor3D"/>
<check_box label="Auto opret" name="AutoLeveling"/>
diff --git a/indra/newview/skins/default/xui/da/floater_sound_devices.xml b/indra/newview/skins/default/xui/da/floater_sound_devices.xml
deleted file mode 100644
index cb4cbba570..0000000000
--- a/indra/newview/skins/default/xui/da/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="Lyd enheder">
- <text name="voice_label">
- Stemme chat
- </text>
- <check_box label="Aktiveret" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_voice_effect.xml b/indra/newview/skins/default/xui/da/floater_voice_effect.xml
deleted file mode 100644
index 86ad251103..0000000000
--- a/indra/newview/skins/default/xui/da/floater_voice_effect.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Steder" name="voice_effects" title="STEMME MORPH">
- <string name="no_voice_effect">
- (Ingen stemme &quot;morph&quot;)
- </string>
- <string name="active_voice_effect">
- (Aktiv)
- </string>
- <string name="unsubscribed_voice_effect">
- (Ikke aktiveret)
- </string>
- <string name="new_voice_effect">
- (Ny!)
- </string>
- <text name="preview_text">
- For at se
- </text>
- <text name="status_text">
- Optag en prøve, klik derefter på en stemme for at høre hvordan det vil lyde.
- </text>
- <button label="Optag" name="record_btn" tool_tip="Optag en stemmeprøve."/>
- <button label="Stop" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Abonnér nu]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Optag en prøve med din stemme og klik på en effekt for at teste.">
- <scroll_list.columns label="Stemme navn" name="name"/>
- <scroll_list.columns label="Udløber" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/da/floater_whitelist_entry.xml
index 443e84b64a..e05be4e310 100644
--- a/indra/newview/skins/default/xui/da/floater_whitelist_entry.xml
+++ b/indra/newview/skins/default/xui/da/floater_whitelist_entry.xml
@@ -3,7 +3,7 @@
<text name="media_label">
Indtast en URL eller et URL mønster for at tilføje til listen med godkendte domæner
</text>
- <line_editor name="whitelist_entry" tool_tip="Indtast en URL eller et URL mønster for at godkende side(r)"/>
+ <line_editor name="whitelist_entry" tool_tip="Indtast en URL eller et URL mønster for at godkende side(r)" bottom_delta="25"/>
<button label="OK" name="ok_btn"/>
<button label="Annullér" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
index 7caa17d514..fa245416cf 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
@@ -4,6 +4,7 @@
Vis mig når:
</text>
<check_box label="Når jeg bruger eller får L$" name="notify_money_change_checkbox"/>
+ <check_box name="notify_money_spend_checkbox" left_delta="70"/>
<check_box label="Når mine venner logger på eller af" name="friends_online_notify_checkbox"/>
<text name="show_label">
Vis altid:
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_sound.xml b/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
index 26d2ae4abd..acae39061b 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
@@ -30,7 +30,7 @@
<radio_item label="Avatar position" name="1"/>
</radio_group>
<check_box label="Bevæg avatar-læber når der snakkes" name="enable_lip_sync"/>
- <check_box label="Skift tale tænd/sluk når jeg trykker:" name="push_to_talk_toggle_check" tool_tip="Når du er i skift-modus, vil hvert tryk tænde eller slukke din mikrofon. Når du ikke er i skift-modus, vil din mikrofon kun være tændt når knappen/tasten holdes nede (som en Walkie Talkie)"/>
+ <check_box label="Skift tale tænd/sluk når jeg trykker" name="push_to_talk_toggle_check" tool_tip="Når du er i skift-modus, vil hvert tryk tænde eller slukke din mikrofon. Når du ikke er i skift-modus, vil din mikrofon kun være tændt når knappen/tasten holdes nede (som en Walkie Talkie)"/>
<line_editor label="Tryk-for-tale udløser" name="modifier_combo"/>
<button label="Angiv taste" name="set_voice_hotkey_button"/>
<button name="set_voice_middlemouse_button" tool_tip="Nulstil til midterste muse-knap"/>
diff --git a/indra/newview/skins/default/xui/da/panel_voice_effect.xml b/indra/newview/skins/default/xui/da/panel_voice_effect.xml
deleted file mode 100644
index 50f561ec7f..0000000000
--- a/indra/newview/skins/default/xui/da/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Voice Morphing Off
- </string>
- <string name="preview_voice_effects">
- Se stemme &quot;morph&quot; ▶
- </string>
- <string name="get_voice_effects">
- Hente stemme &quot;morph&quot; ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Vælg en stemme &quot;morph&quot; for at ændre din stemme">
- <combo_box.item label="Stemme morph slukket" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/de/floater_big_preview.xml b/indra/newview/skins/default/xui/de/floater_big_preview.xml
deleted file mode 100644
index c5ce56d1d9..0000000000
--- a/indra/newview/skins/default/xui/de/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="VORSCHAU"/>
diff --git a/indra/newview/skins/default/xui/de/floater_post_process.xml b/indra/newview/skins/default/xui/de/floater_post_process.xml
deleted file mode 100644
index a6ed8cc3df..0000000000
--- a/indra/newview/skins/default/xui/de/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="POST-PROCESSING-EINSTELLUNGEN">
- <tab_container name="Post-Process Tabs">
- <panel label="Farbfilter" name="wmiColorFilterPanel">
- <check_box label="Ein" name="wmiColorFilterToggle" />
- <text name="wmiColorFilterBrightnessText">
- Helligkeit
- </text>
- <text name="wmiColorFilterSaturationText">
- Sättigung
- </text>
- <text name="wmiColorFilterContrastText">
- Kontrast
- </text>
- <text name="wmiColorFilterBaseText">
- Kontrast-Grundfarbe
- </text>
- <slider label="R" name="wmiColorFilterBaseR" />
- <slider label="G" name="wmiColorFilterBaseG" />
- <slider label="B" name="wmiColorFilterBaseB" />
- <slider label="I" name="wmiColorFilterBaseI" />
- </panel>
- <panel label="Nachtsicht" name="wmiNightVisionPanel">
- <check_box label="Ein" name="wmiNightVisionToggle" />
- <text name="wmiNightVisionBrightMultText">
- Lichtverstärkungsmultiplikator
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Rauschen-Größe
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Rauschen-Stärke
- </text>
- </panel>
- <panel label="Bloom" name="wmiBloomPanel">
- <check_box label="Ein" name="wmiBloomToggle" />
- <text name="wmiBloomExtractText">
- Luminanz-Extraktion
- </text>
- <text name="wmiBloomSizeText">
- Bloom-Größe
- </text>
- <text name="wmiBloomStrengthText">
- Bloom-Stärke
- </text>
- </panel>
- <panel label="Extras" name="Extras">
- <button label="Effekt laden" label_selected="Effekt laden" name="PPLoadEffect" />
- <button label="Effekt speichern" label_selected="Effekt speichern" name="PPSaveEffect" />
- <line_editor label="Effektname" name="PPEffectNameEditor" />
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_sound_devices.xml b/indra/newview/skins/default/xui/de/floater_sound_devices.xml
deleted file mode 100644
index 22ccb2c1a2..0000000000
--- a/indra/newview/skins/default/xui/de/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="SOUNDGERÄTE">
- <text name="voice_label">
- Voice-Chat
- </text>
- <check_box label="Aktiviert" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_voice_effect.xml b/indra/newview/skins/default/xui/de/floater_voice_effect.xml
deleted file mode 100644
index 8d37950480..0000000000
--- a/indra/newview/skins/default/xui/de/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Orte" name="voice_effects" title="VOICE-MORPHING-VORSCHAU">
- <string name="no_voice_effect">
- (Kein Voice-Morphing)
- </string>
- <string name="active_voice_effect">
- (Aktiv)
- </string>
- <string name="unsubscribed_voice_effect">
- (nicht abonniert)
- </string>
- <string name="new_voice_effect">
- (Neu!)
- </string>
- <string name="effect_Arena">
- Arena
- </string>
- <string name="effect_Beast">
- Bestie
- </string>
- <string name="effect_Buff">
- Muskulös
- </string>
- <string name="effect_Buzz">
- Buzz
- </string>
- <string name="effect_Camille">
- Camille
- </string>
- <string name="effect_Creepy">
- Unheimlich
- </string>
- <string name="effect_CreepyBot">
- UnheimlicherBot
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- TieferBot
- </string>
- <string name="effect_Demon">
- Dämon
- </string>
- <string name="effect_Female Elf">
- Weibliche Elfe
- </string>
- <string name="effect_Flirty">
- Kokett
- </string>
- <string name="effect_Foxy">
- Attraktiv
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Bonus_Halloween_2010
- </string>
- <string name="effect_Helium">
- Helium
- </string>
- <string name="effect_Husky">
- Rauchig
- </string>
- <string name="effect_Husky Whisper">
- Rauchiges Flüstern
- </string>
- <string name="effect_Intercom">
- Intercom
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Leises Trällern
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Modell
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Alptraum
- </string>
- <string name="effect_PopBot">
- PopBot
- </string>
- <string name="effect_Rachel">
- Rachel
- </string>
- <string name="effect_Radio">
- Radio
- </string>
- <string name="effect_Robot">
- Roboter
- </string>
- <string name="effect_Roxanne">
- Roxanne
- </string>
- <string name="effect_Rumble">
- Rumpeln
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samantha
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Shorty
- </string>
- <string name="effect_Smaller">
- Kleiner
- </string>
- <string name="effect_Sneaky">
- Hinterhältig
- </string>
- <string name="effect_Stallion">
- Hengst
- </string>
- <string name="effect_Sultry">
- Feurig
- </string>
- <string name="effect_Thunder">
- Donner
- </string>
- <string name="effect_Vixen">
- Erotisch
- </string>
- <string name="effect_WhinyBot">
- JammernderBot
- </string>
- <text name="preview_text">
- Zur Vorschau
- </text>
- <text name="status_text">
- Stimme aufnehmen und auf einen Effekt klicken, um diesen auf Ihre Stimme anzuwenden.
- </text>
- <button label="Aufnehmen" name="record_btn" tool_tip="Nehmen Sie Ihre Stimme auf."/>
- <button label="Stopp" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Jetzt abonnieren]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Nehmen Sie Ihre Stimme auf und klicken Sie dann auf einen Effekt, um diesen auszuprobieren.">
- <scroll_list.columns label="Bezeichnung" name="name"/>
- <scroll_list.columns label="Gültig bis" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/de/panel_login_first.xml b/indra/newview/skins/default/xui/de/panel_login_first.xml
deleted file mode 100644
index 038001157e..0000000000
--- a/indra/newview/skins/default/xui/de/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=de
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Benutzername" name="username_combo" tool_tip="Bei der Registrierung gewählter Benutzername wie „berndschmidt12“ oder „Liebe Sonne“"/>
- <line_editor label="Kennwort" name="password_edit"/>
- <button label="Anmelden" name="connect_btn"/>
- <check_box label="Details speichern" name="remember_check"/>
- <text name="forgot_password_text">
- Kennwort vergessen
- </text>
- <text name="sign_up_text">
- Registrieren
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Ihr erster Schritt ist Learning Island. Suchen Sie die Pforte!
- </text>
- <text name="image_caption_right">
- Erkunden Sie dann Social Island und lernen Sie andere Einwohner kennen!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_voice_effect.xml b/indra/newview/skins/default/xui/de/panel_voice_effect.xml
deleted file mode 100644
index 533deb8597..0000000000
--- a/indra/newview/skins/default/xui/de/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Voice-Morphing Aus
- </string>
- <string name="preview_voice_effects">
- Voice-Morphing ausprobieren ▶
- </string>
- <string name="get_voice_effects">
- Voice-Morphing abonnieren ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Wählen Sie einen Voice-Morph-Effekt aus, um Ihre Stimme zu verändern.">
- <combo_box.item label="Voice-Morphing Aus" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 9c932ac034..bfe1477fa0 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -87,7 +87,7 @@ Megapahit is brought to you by:
enabled="false"
font="Monospace"
follows="top|left"
- height="200"
+ height="180"
bg_readonly_color="Transparent"
left="5"
text_color="LtGray"
@@ -99,12 +99,10 @@ Erik Kundiman LinneNoir
milo (observeur) Fritigern Gothly
Kou Ayashi Hadet Sonnenkern
Remmy (Secret Foxtail) Eris Ravenwood
-gwigz (nya) EmilyAmiee
-Bavid Dailey Aria (Tashia Redrose)
-Cate (32a) Hiroo Ono
-Melodey Keysin (scoutkeysin)
-Padoria Teuden ~ ( ^-^ ) ~ (cutie_qu)
-Markus Teuden
+EmilyAmiee Bavid Dailey
+Aria (Tashia Redrose) Cate (32a)
+Hiroo Ono Melodey
+Keysin ~ ( ^-^ ) ~ (cutie_qu)
</text_editor>
<text
follows="top|left"
@@ -120,7 +118,7 @@ with special thanks to:
<text_editor
enabled="false"
follows="top|left"
- height="130"
+ height="150"
bg_readonly_color="Transparent"
left="5"
text_color="LtGray"
@@ -135,6 +133,7 @@ Vir Linden - Making it possible for the project to have a place in SL
nutsobvious - Early testing and video proof
Soft Linden - Security testing
Kyle Linden - Giving TPV parcel 2 to Erik Kundiman
+gwigz (nya) - Feature contributions
Signal Linden - Opening opportunities for Megapahit to contribute more
</text_editor>
</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index c5b42b6dae..ffb9c0f78e 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -974,7 +974,7 @@
layout="topleft"
left="28"
name="Set to group:"
- top_pad="5"
+ top_pad="9"
width="176">
Set to group:
</text>
@@ -1022,7 +1022,7 @@
layout="topleft"
left="28"
name="Owned by others:"
- top_pad="5"
+ top_pad="9"
width="176">
Owned by others:
</text>
@@ -1593,7 +1593,7 @@ Only large parcels can be listed in search.
left="10"
name="with media:"
top="10"
- width="100">
+ width="110">
Type:
</text>
<combo_box
@@ -1620,7 +1620,7 @@ Only large parcels can be listed in search.
layout="topleft"
left="10"
name="at URL:"
- width="100"
+ width="110"
top_pad="10">
Home Page:
</text>
@@ -1632,7 +1632,7 @@ Only large parcels can be listed in search.
max_length_bytes="255"
name="media_url"
select_on_focus="true"
- width="300"
+ width="290"
top_delta="0"/>
<button
follows="left|top"
@@ -1659,13 +1659,13 @@ Only large parcels can be listed in search.
follows="left|top"
height="20"
layout="topleft"
- left="110"
+ left="120"
max_length_bytes="255"
name="url_description"
select_on_focus="true"
tool_tip="Text displayed next to play/load button"
top_delta="0"
- width="300" />
+ width="290" />
<text
type="string"
length="1"
@@ -1685,7 +1685,7 @@ Only large parcels can be listed in search.
follows="left|top"
height="80"
layout="topleft"
- left="110"
+ left="120"
name="media texture"
tool_tip="Click to choose a picture"
top_delta="0"
@@ -1698,7 +1698,7 @@ Only large parcels can be listed in search.
layout="topleft"
left_pad="8"
name="replace_texture_help"
- width="300"
+ width="290"
word_wrap="true"
top_delta="0">
Objects using this texture will show the movie or web page after you click the play arrow. Select the thumbnail to choose a different texture.
@@ -1707,7 +1707,7 @@ Only large parcels can be listed in search.
height="16"
label="Auto scale"
layout="topleft"
- left="107"
+ left="117"
name="media_auto_scale"
top_pad="-10"
tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required."
@@ -1721,7 +1721,7 @@ Only large parcels can be listed in search.
left="10"
name="media_size"
tool_tip="Size to render Web media, leave 0 for default."
- width="100"
+ width="110"
top_pad="10">
Size:
</text>
@@ -1776,7 +1776,7 @@ Only large parcels can be listed in search.
left="10"
name="Options:"
top_pad="10"
- width="100">
+ width="110">
Options:
</text>
<check_box
@@ -1786,7 +1786,7 @@ Only large parcels can be listed in search.
left_pad="-3"
name="media_loop"
tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning."
- top_delta="-1"
+ top_delta="1"
width="200" />
</panel>
<panel
diff --git a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
index 870ddee554..308f4feb5a 100644
--- a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
+++ b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
@@ -50,7 +50,6 @@
follows="top|left|right"
height="24"
label="Get started"
- font="SansSerifMedium"
layout="topleft"
left="320"
name="continue_btn"
@@ -59,6 +58,7 @@
image_hover_unselected="PushButton_Login_Over"
label_color="White"
top_pad ="15"
+ pad_bottom="1"
width="140"/>
<button
follows="top|left|right"
@@ -66,6 +66,7 @@
label="Later"
layout="topleft"
left_pad="9"
+ pad_bottom="1"
name="close_btn"
width="90"/>
<icon
@@ -97,7 +98,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
text_color="White"
height="75"
width="260"
@@ -112,7 +112,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
text_color="White"
height="75"
width="260"
@@ -126,7 +125,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
text_color="White"
height="75"
width="260"
diff --git a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
index 889eeb5369..d6dc112dce 100644
--- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -47,15 +47,15 @@
name="ambient_lbl"
height="10"
layout="topleft"
- left="10"
+ left="7"
top="5"
- width="80">Ambient:</text>
+ width="80">Ambient</text>
<color_swatch can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
- left_delta="0"
+ left_delta="3"
name="ambient_light"
top_pad="5"
width="60"/>
@@ -63,15 +63,15 @@
name="blue_horizon_lbl"
height="10"
layout="topleft"
- left_delta="0"
+ left="7"
top_pad="10"
- width="80">Blue Horizon:</text>
+ width="80">Blue Horizon</text>
<color_swatch can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
- left_delta="0"
+ left_delta="3"
name="blue_horizon"
top_pad="5"
width="60"/>
@@ -79,15 +79,15 @@
name="blue_density_lbl"
height="10"
layout="topleft"
- left_delta="0"
+ left="7"
top_pad="10"
- width="80">Blue Density:</text>
+ width="80">Blue Density</text>
<color_swatch can_apply_immediately="true"
follows="left|top"
height="40"
label_height="0"
layout="topleft"
- left_delta="0"
+ left_delta="3"
name="blue_density"
top_pad="5"
width="60"/>
@@ -107,7 +107,7 @@
layout="topleft"
right="-12"
top="5"
- width="60">Sun Color:</text>
+ width="60">Sun Color</text>
<color_swatch can_apply_immediately="true"
follows="left|top"
height="10"
@@ -123,7 +123,7 @@
layout="topleft"
left_delta="0"
top_pad="5"
- width="80">Cloud Color:</text>
+ width="80">Cloud Color</text>
<color_swatch can_apply_immediately="true"
follows="left|top"
height="10"
@@ -139,7 +139,7 @@
left_delta="0"
top_pad="10"
name="cloud_map_label"
- width="80">Cloud Image:</text>
+ width="80">Cloud Image</text>
<texture_picker height="63"
layout="topleft"
left_delta="0"
@@ -152,7 +152,7 @@
left_delta="0"
top_pad="-13"
name="water_map_label"
- width="80">Water Image:</text>
+ width="80">Water Image</text>
<texture_picker height="63"
layout="topleft"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index adbce0d982..0c82cbb00c 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -63,7 +63,7 @@
layout="topleft"
left="10"
name="InstructSearchResidentName"
- top="8"
+ top="7"
width="220">
Type part of a person&apos;s name:
</text>
@@ -76,7 +76,7 @@
height="23"
left_delta="0"
name="Edit"
- top_pad="0"
+ top_pad="3"
width="65" />
<button
follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml
deleted file mode 100644
index 362853d06f..0000000000
--- a/indra/newview/skins/default/xui/en/floater_big_preview.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
- positioning="cascading"
- can_close="true"
- can_resize="true"
- can_minimize="false"
- help_topic="floater_big_preview"
- layout="topleft"
- name="floater_big_preview"
- save_rect="true"
- single_instance="true"
- reuse_instance="true"
- title="PREVIEW"
- height="465"
- width="770">
- <panel
- height="450"
- width="750"
- visible="true"
- name="big_preview_placeholder"
- top="5"
- follows="all"
- left="10">
- </panel>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
index 7636284b4b..17631ad30c 100644
--- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -29,7 +29,7 @@
control_name="BulkChangeIncludeAnimations"
height="16"
name="check_animation"
- top="24"
+ top="30"
left="10"
width="16" />
<icon
@@ -73,7 +73,7 @@
name="check_gesture"
left="95"
width="16"
- top="25" />
+ top="30" />
<icon
height="16"
image_name="Inv_Gesture"
@@ -116,7 +116,7 @@
control_name="BulkChangeIncludeScripts"
height="16"
name="check_script"
- top="25"
+ top="30"
left="180"
width="16"
/>
@@ -161,7 +161,7 @@
height="16"
name="check_settings"
left="245"
- top="25"
+ top="30"
width="16" />
<icon
height="16"
@@ -291,7 +291,7 @@
height="16"
label="Copy"
layout="topleft"
- top_pad="0"
+ top_pad="3"
name="next_owner_copy"
tool_tip="Next owner can make unlimited copies of this object. Copies maintain creator information, and can never be more permissive than the item being copied."
width="92">
@@ -302,7 +302,7 @@
control_name="BulkChangeNextOwnerTransfer"
enabled_control="BulkChangeNextOwnerCopy"
height="16"
- top_pad="0"
+ top_pad="3"
initial_value="true"
label="Transfer"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index e8e83301be..5e0903a40f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -93,7 +93,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
height="16"
layout="topleft"
left="20"
@@ -105,7 +104,6 @@
<text
type="string"
length="1"
- font="SansSerifMedium"
follows="top|left"
halign="right"
height="16"
@@ -128,7 +126,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
height="16"
layout="topleft"
left="20"
@@ -140,7 +137,6 @@
<text
type="string"
length="1"
- font="SansSerifMedium"
follows="top|left"
halign="right"
height="16"
@@ -163,7 +159,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
font.style="BOLD"
height="16"
layout="topleft"
@@ -176,7 +171,6 @@
<text
type="string"
length="1"
- font="SansSerifMedium"
follows="top|left"
halign="right"
height="16"
@@ -207,7 +201,6 @@
type="string"
length="1"
follows="top|left"
- font="SansSerifMedium"
height="16"
top_pad="15"
layout="topleft"
@@ -217,7 +210,6 @@
Choose amount to buy
</text>
<text
- font="SansSerifMedium"
type="string"
length="1"
follows="left|top"
@@ -233,7 +225,6 @@
type="string"
max_length_bytes="10"
halign="right"
- font="SansSerifMedium"
select_on_focus="true"
follows="top|left"
top_delta="-4"
@@ -247,7 +238,6 @@
<text
type="string"
length="1"
- font="SansSerifMedium"
text_color="EmphasisColor"
follows="top|left"
halign="right"
@@ -276,7 +266,6 @@
</text>
<text
type="string"
- font="SansSerifMedium"
length="1"
follows="top|left"
height="16"
@@ -290,7 +279,6 @@
<text
type="string"
length="1"
- font="SansSerifMedium"
follows="top|left"
top_delta="0"
height="16"
@@ -350,7 +338,6 @@ Re-enter amount to see the latest exchange rate.
length="1"
follows="top|left"
layout="topleft"
- font="SansSerifMedium"
top="10"
left="20"
width="310"
diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
index abe8344097..6d3da72962 100644
--- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml
+++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
@@ -87,7 +87,7 @@
name="notes_editor"
spellcheck="true"
text_readonly_color="white"
- prevalidator="ascii_with_newline"
+ prevalidator="ascii"
commit_on_focus_lost="true"
top_pad="5"
width="290"
diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
index 787b2f8be4..b911e9b6f5 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
@@ -290,7 +290,7 @@
<button
follows="top|left"
height="23"
- width="110"
+ width="113"
label="Clone Track From"
left="10"
top_pad="10"
@@ -298,7 +298,7 @@
<button
follows="top|left"
height="23"
- width="110"
+ width="113"
label="Load Track From"
top_pad="0"
left_delta="0"
@@ -306,7 +306,7 @@
<button
follows="top|left"
height="23"
- width="110"
+ width="113"
label="Clear Track"
top_pad="0"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
index c831684594..41e8d3dc8a 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -5,7 +5,7 @@
can_minimize="true"
can_close="true"
can_resize="false"
- height="80"
+ height="84"
width="515"
layout="topleft"
name="HoverHeight"
@@ -39,6 +39,6 @@
label="Bind Camera view"
layout="topleft"
name="BindCameraCheck"
- top_pad="7"
+ top_pad="14"
width="237"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
index 61cb91e2f3..8070ed55e6 100644
--- a/indra/newview/skins/default/xui/en/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -5,7 +5,7 @@
height="800"
layout="topleft"
min_height="175"
- min_width="154"
+ min_width="390"
name="contents"
help_topic="contents"
title="FONT TEST"
diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml
index f8ec696af9..e94669bba4 100644
--- a/indra/newview/skins/default/xui/en/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml
@@ -6,7 +6,7 @@
name="godtools floater"
help_topic="godtools_floater"
title="GOD TOOLS"
- width="400">
+ width="410">
<tab_container
follows="left|top"
height="364"
@@ -15,7 +15,7 @@
name="GodTools Tabs"
tab_position="top"
top="20"
- width="400">
+ width="410">
<panel
border="true"
follows="left|top|right|bottom"
@@ -72,11 +72,11 @@
follows="left|top|right"
height="20"
layout="topleft"
- left_pad="0"
+ left_pad="5"
max_length_bytes="63"
name="region name"
top_delta="0"
- width="250">
+ width="294">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -233,13 +233,13 @@
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
- left_delta="108"
+ left_delta="90"
max_length_bytes="10"
name="estate"
top_delta="0"
- width="50" />
+ width="100" />
<text
type="string"
length="1"
@@ -249,7 +249,7 @@
layout="topleft"
left="200"
name="parent id"
- top_pad="4"
+ top_pad="7"
width="190">
Parent ID:
</text>
@@ -257,14 +257,14 @@
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
- left_delta="108"
+ left_delta="90"
max_length_bytes="10"
name="parentestate"
tool_tip="This is the parent estate for this region"
top_delta="0"
- width="50">
+ width="100">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -276,22 +276,22 @@
layout="topleft"
left="200"
name="Grid Pos: "
- top_pad="4"
- width="190">
+ top_pad="7"
+ width="90">
Grid Pos:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
- left_delta="88"
+ left_pad="0"
max_length_bytes="10"
name="gridposx"
tool_tip="This is the grid x position for this region"
top_delta="0"
- width="50">
+ width="46">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -299,14 +299,14 @@
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
- left_pad="10"
+ left_pad="8"
max_length_bytes="10"
name="gridposy"
tool_tip="This is the grid y position for this region"
top_delta="0"
- width="40">
+ width="46">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -318,20 +318,20 @@
layout="topleft"
left="200"
name="Redirect to Grid: "
- top_pad="4"
- width="88">
+ top_pad="7"
+ width="90">
Redirect to Grid:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
left_pad="0"
max_length_bytes="10"
name="redirectx"
- width="50">
+ width="46">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -339,13 +339,13 @@
border_style="line"
border_thickness="1"
follows="top|right"
- height="16"
+ height="18"
layout="topleft"
- left_pad="10"
+ left_pad="8"
max_length_bytes="10"
name="redirecty"
top_delta="0"
- width="40">
+ width="46">
<line_editor.commit_callback
function="RegionTools.ChangeAnything" />
</line_editor>
@@ -407,10 +407,10 @@
label="Refresh"
label_selected="Refresh"
layout="topleft"
- left="278"
+ left="280"
name="Refresh"
tool_tip="Click here to refresh the above information"
- top_pad="10"
+ top_pad="14"
width="110">
<button.commit_callback
function="RegionTools.Refresh" />
@@ -526,7 +526,7 @@
height="16"
label="Disable Physics"
layout="topleft"
- left_delta="120"
+ left_delta="136"
name="disable physics"
tool_tip="Set this to disable all physics in this region"
top_delta="0"
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_settings.xml b/indra/newview/skins/default/xui/en/floater_inventory_settings.xml
index a51e7a844a..5dd3dfa2bf 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_settings.xml
@@ -27,7 +27,6 @@
left_pad="12"
top_delta="2"
name="multi_folder_txt"
- font="SansSerifMedium"
text_color="White"
width="300">
Double-click on folder in multi-folder view:
@@ -37,7 +36,6 @@
follows="left|top"
top_pad="8"
layout="topleft"
- font="SansSerifMedium"
left="60"
width="300"
height="66"
@@ -90,7 +88,6 @@
left_pad="12"
top_delta="2"
name="single_folder_txt"
- font="SansSerifMedium"
text_color="White"
width="300">
Double-click on folder in single-folder view:
@@ -100,7 +97,6 @@
follows="left|top"
top_pad="8"
layout="topleft"
- font="SansSerifMedium"
left="60"
width="300"
height="44"
@@ -142,10 +138,9 @@
layout="topleft"
left_pad="13"
name="find_original_txt"
- font="SansSerifMedium"
text_color="White"
top_delta="1"
- width="300">
+ width="310">
Clicking on "Show in inventory" or "Find original"
</text>
<radio_group
@@ -153,7 +148,6 @@
follows="left|top"
top_pad="8"
layout="topleft"
- font="SansSerifMedium"
left="60"
width="300"
height="44"
@@ -196,7 +190,6 @@
left_pad="12"
top_delta="2"
name="favorites_txt"
- font="SansSerifMedium"
text_color="White"
width="300">
Favorites
@@ -206,7 +199,6 @@
layout="topleft"
follows="left|top"
top_pad="8"
- font="SansSerifMedium"
left="60"
width="300"
height="18"
@@ -219,7 +211,6 @@
follows="left|top"
top_pad="5"
layout="topleft"
- font="SansSerifMedium"
left="60"
width="150"
height="18"
@@ -232,7 +223,6 @@
follows="left|top"
top_pad="5"
layout="topleft"
- font="SansSerifMedium"
left="60"
width="150"
height="18"
@@ -276,7 +266,6 @@
left_pad="12"
top_delta="2"
name="single_folder_txt"
- font="SansSerifMedium"
text_color="White"
width="300">
Pressing enter on an avatar attachment
diff --git a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
index fbd3c81bad..67831c2449 100644
--- a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
@@ -4,9 +4,9 @@
can_resize="true"
default_tab_group="1"
height="790"
- width="256"
+ width="267"
min_height="500"
- min_width="256"
+ min_width="267"
layout="topleft"
name="material editor"
help_topic="material_editor"
@@ -17,7 +17,7 @@
top="18"
left="4"
height="768"
- width="250"
+ width="261"
follows="all"
layout="topleft"
color="Transparent"
diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml
index 21ceeafeea..f894e94622 100644
--- a/indra/newview/skins/default/xui/en/floater_material_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -4,9 +4,9 @@
can_resize="true"
default_tab_group="1"
height="891"
- width="256"
+ width="267"
min_height="500"
- min_width="256"
+ min_width="267"
layout="topleft"
name="material editor"
help_topic="material_editor"
@@ -20,7 +20,7 @@
top="18"
left="4"
height="768"
- width="250"
+ width="261"
follows="all"
layout="topleft"
color="DkGray2"
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index 39e9de0980..fb828b804a 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -1407,7 +1407,7 @@
follows="top|left"
height="15"
layout="topleft"
- left="220"
+ left="240"
name="pelvis_offset_label"
text_color="White"
top="8"
@@ -1421,12 +1421,13 @@
max_val="3.0"
name="pelvis_offset"
top_pad="10"
+ left="340"
value="0.0"
width="80"/>
<text
follows="top|left"
height="17"
- left="425"
+ left="435"
name="skin_too_many_joints"
text_color="Orange"
top="7"
@@ -1437,7 +1438,7 @@
<text
follows="top|left"
height="32"
- left="425"
+ left="435"
name="skin_unknown_joint"
text_color="Orange"
top="8"
@@ -1879,7 +1880,7 @@ Analysed:
top="5"
left_pad="20"
name="label_display"
- width="50">
+ width="53">
Display...
</text>
<check_box
@@ -1889,7 +1890,7 @@ Analysed:
layout="topleft"
left_delta="0"
name="show_edges"
- top_pad="8">
+ top_pad="10">
</check_box>
<check_box
follows="top|left"
@@ -1897,7 +1898,7 @@ Analysed:
label_text.text_color="White"
layout="topleft"
name="show_physics"
- top_pad="8">
+ top_pad="10">
</check_box>
<check_box
follows="top|left"
@@ -1905,7 +1906,7 @@ Analysed:
label_text.text_color="White"
layout="topleft"
name="show_textures"
- top_pad="8">
+ top_pad="10">
</check_box>
<check_box
follows="top|left"
@@ -1913,7 +1914,7 @@ Analysed:
label_text.text_color="White"
layout="topleft"
name="show_skin_weight"
- top_pad="8">
+ top_pad="10">
</check_box>
<check_box
follows="top|left"
@@ -1923,7 +1924,7 @@ Analysed:
width="130"
layout="topleft"
name="show_joint_overrides"
- top_pad="8">
+ top_pad="10">
</check_box>
<check_box
follows="top|left"
@@ -1931,7 +1932,7 @@ Analysed:
label_text.text_color="White"
layout="topleft"
name="show_joint_positions"
- top_pad="17">
+ top_pad="21">
</check_box>
<text
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml
index dd0795305e..10e74e9a31 100644
--- a/indra/newview/skins/default/xui/en/floater_my_environments.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml
@@ -41,6 +41,7 @@
mouse_opaque="true"
name="icon_settingsdays"
left="4"
+ top="9"
width="16" />
<check_box
height="16"
@@ -48,7 +49,7 @@
layout="topleft"
left_pad="2"
name="chk_days"
- top_delta="0"
+ top_delta="2"
width="60" />
<icon
height="16"
@@ -57,6 +58,7 @@
mouse_opaque="true"
name="icon_settingsskies"
left_pad="10"
+ top="9"
width="16" />
<check_box
height="16"
@@ -64,7 +66,7 @@
layout="topleft"
left_pad="2"
name="chk_skies"
- top_delta="0"
+ top_delta="2"
width="60" />
<icon
height="16"
@@ -73,6 +75,7 @@
mouse_opaque="true"
name="icon_settingswater"
left_pad="10"
+ top="9"
width="16" />
<check_box
height="16"
@@ -80,7 +83,7 @@
layout="topleft"
left_pad="2"
name="chk_water"
- top_delta="0"
+ top_delta="2"
width="60" />
<filter_editor
follows="left|top|right"
@@ -89,7 +92,7 @@
layout="topleft"
left="4"
name="flt_search"
- top_pad="6"
+ top_pad="4"
right="-4" />
</layout_panel>
<layout_panel
diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml
index 881c1f7469..def57abfe4 100644
--- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml
@@ -12,7 +12,7 @@
save_visibility="true"
reuse_instance="true"
title="INVENTORY"
- width="418" >
+ width="424" >
<panel
class="sidepanel_inventory"
name="main_panel"
diff --git a/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
index 9981e5d893..66c229e698 100644
--- a/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
+++ b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater
- height="130"
+ height="140"
width="300"
layout="topleft"
name="floater_new_feature_notification"
@@ -40,7 +40,7 @@ New feature
text_color="White"
layout="topleft"
left="10"
- height="40"
+ height="50"
top_pad="14"
right="-10"
word_wrap="true"
diff --git a/indra/newview/skins/default/xui/en/floater_performance.xml b/indra/newview/skins/default/xui/en/floater_performance.xml
index dac8a71b2d..5fb9eeb2de 100644
--- a/indra/newview/skins/default/xui/en/floater_performance.xml
+++ b/indra/newview/skins/default/xui/en/floater_performance.xml
@@ -65,10 +65,10 @@
text_color="White"
height="20"
layout="topleft"
- left="395"
+ left="392"
top="7"
name="fps_desc1_lbl"
- width="150">
+ width="153">
Allow 5-10 seconds for
</text>
<text
@@ -78,7 +78,7 @@
layout="topleft"
top_pad="-3"
name="fps_desc2_lbl"
- width="150">
+ width="153">
changes to take full effect.
</text>
</panel>
@@ -265,7 +265,7 @@
left="10"
name="complexity_info"
top_pad="0"
- width="455">
+ width="490">
Reduce the complexity of your avatar if you aren't satisfied with current FPS.
</text>
<icon
diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml
deleted file mode 100644
index 37339f79c8..0000000000
--- a/indra/newview/skins/default/xui/en/floater_post_process.xml
+++ /dev/null
@@ -1,426 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
- legacy_header_height="18"
- height="400"
- layout="topleft"
- name="Post-Process Floater"
- help_topic="post_process_floater"
- title="POST-PROCESS SETTINGS"
- width="400">
- <tab_container
- follows="left|top"
- height="400"
- layout="topleft"
- left="0"
- name="Post-Process Tabs"
- tab_position="top"
- top="0"
- width="400">
- <panel
- border="true"
- follows="left|top|right|bottom"
- height="400"
- label="Color Filter"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- help_topic="post_process_color_filter_tab"
- name="wmiColorFilterPanel"
- top="0"
- width="398">
- <check_box
- control_name="wmiColorFilterToggle"
- height="16"
- label="Enable"
- layout="topleft"
- left="14"
- name="wmiColorFilterToggle"
- top="4"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiColorFilterBrightnessText"
- top_pad="4"
- width="355">
- Brightness
- </text>
- <slider
- control_name="wmiColorFilterBrightness"
- decimal_digits="2"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- layout="topleft"
- left_delta="4"
- max_val="4"
- name="wmiColorFilterBrightness"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiColorFilterSaturationText"
- top_pad="4"
- width="355">
- Saturation
- </text>
- <slider
- control_name="wmiColorFilterSaturation"
- decimal_digits="2"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- layout="topleft"
- left_delta="4"
- max_val="2"
- min_val="-1"
- name="wmiColorFilterSaturation"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiColorFilterContrastText"
- top_pad="4"
- width="355">
- Contrast
- </text>
- <slider
- control_name="wmiColorFilterContrast"
- decimal_digits="2"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- layout="topleft"
- left_delta="4"
- max_val="4"
- name="wmiColorFilterContrast"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiColorFilterBaseText"
- top_pad="4"
- width="355">
- Contrast Base Color
- </text>
- <slider
- control_name="wmiColorFilterBaseR"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- label="R"
- layout="topleft"
- left_delta="4"
- name="wmiColorFilterBaseR"
- top_pad="20"
- width="200" />
- <slider
- control_name="wmiColorFilterBaseG"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- label="G"
- layout="topleft"
- left_delta="0"
- name="wmiColorFilterBaseG"
- top_pad="10"
- width="200" />
- <slider
- control_name="wmiColorFilterBaseB"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.0"
- label="B"
- layout="topleft"
- left_delta="0"
- name="wmiColorFilterBaseB"
- top_pad="10"
- width="200" />
- <slider
- control_name="wmiColorFilterBaseI"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="0.5"
- label="I"
- layout="topleft"
- left_delta="0"
- name="wmiColorFilterBaseI"
- top_pad="10"
- width="200" />
- </panel>
- <panel
- border="true"
- follows="left|top|right|bottom"
- height="400"
- label="Night Vision"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- help_topic="post_process_night_vision_tab"
- name="wmiNightVisionPanel"
- top_delta="-236"
- width="398">
- <check_box
- control_name="wmiNightVisionToggle"
- height="16"
- label="Enable"
- layout="topleft"
- left="14"
- name="wmiNightVisionToggle"
- top="4"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiNightVisionBrightMultText"
- top_pad="5"
- width="355">
- Light Amplification Multiple
- </text>
- <slider
- control_name="wmiNightVisionBrightMult"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="3.0"
- layout="topleft"
- left_delta="4"
- max_val="10"
- min_val="1"
- name="wmiNightVisionBrightMult"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiNightVisionNoiseSizeText"
- top_pad="4"
- width="355">
- Noise Size
- </text>
- <slider
- control_name="wmiNightVisionNoiseSize"
- follows="left"
- height="10"
- initial_value="1"
- layout="topleft"
- left_delta="4"
- max_val="100"
- min_val="1"
- name="wmiNightVisionNoiseSize"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiNightVisionNoiseStrengthText"
- top_pad="4"
- width="355">
- Noise Strength
- </text>
- <slider
- control_name="wmiNightVisionNoiseStrength"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="0.3"
- layout="topleft"
- left_delta="4"
- name="wmiNightVisionNoiseStrength"
- top_pad="20"
- width="200" />
- </panel>
- <panel
- border="true"
- follows="left|top|right|bottom"
- height="400"
- label="Bloom"
- layout="topleft"
- left_delta="0"
- help_topic="post_process_bloom_tab"
- name="wmiBloomPanel"
- top_delta="-236"
- width="398">
- <check_box
- control_name="wmiBloomToggle"
- height="16"
- label="Enable"
- layout="topleft"
- left="14"
- name="wmiBloomToggle"
- top="4"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiBloomExtractText"
- top_pad="5"
- width="355">
- Luminosity Extraction
- </text>
- <slider
- control_name="wmiBloomExtract"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="0.9"
- layout="topleft"
- left_delta="4"
- name="wmiBloomExtract"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiBloomSizeText"
- top_pad="4"
- width="355">
- Bloom Size
- </text>
- <slider
- control_name="wmiBloomSize"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="3.0"
- layout="topleft"
- left_delta="4"
- max_val="20"
- name="wmiBloomSize"
- top_pad="20"
- width="200" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_delta="-4"
- name="wmiBloomStrengthText"
- top_pad="4"
- width="355">
- Bloom Strength
- </text>
- <slider
- control_name="wmiBloomStrength"
- follows="left"
- height="10"
- increment="0.01"
- initial_value="1.2"
- layout="topleft"
- left_delta="4"
- max_val="10"
- name="wmiBloomStrength"
- top_pad="20"
- width="200" />
- </panel>
- <panel
- border="true"
- follows="left|top|right|bottom"
- height="400"
- label="Extras"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- help_topic="post_process_extras_tab"
- name="Extras"
- top_delta="-236"
- width="398">
- <button
- height="20"
- label="LoadEffect"
- label_selected="LoadEffect"
- layout="topleft"
- left="15"
- name="PPLoadEffect"
- top="13"
- width="100" />
- <button
- height="20"
- label="SaveEffect"
- label_selected="SaveEffect"
- layout="topleft"
- left_delta="0"
- name="PPSaveEffect"
- top_pad="7"
- width="100" />
- <combo_box
- height="18"
- layout="topleft"
- left_delta="120"
- name="PPEffectsCombo"
- top="15"
- width="150" />
- <line_editor
- border_style="line"
- border_thickness="1"
- follows="left|right|bottom"
- font="SansSerif"
- height="20"
- label="Effect Name"
- layout="topleft"
- left_delta="0"
- max_length_bytes="40"
- name="PPEffectNameEditor"
- tab_group="1"
- top_pad="22"
- width="150" />
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 97ff1fd5a2..af3403d034 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -82,8 +82,8 @@
name="pref core"
tab_group="1"
tab_position="left"
- tab_width="140"
- tab_padding_right="0"
+ tab_width="136"
+ tab_padding_right="4"
top="40"
width="658">
<panel
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 0e37472990..672db51ff6 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -141,14 +141,6 @@
tool_tip="Maximum resolution for 'level of detail' textures"
width="90">
<combo_box.item
- label="128"
- name="128"
- value="128"/>
- <combo_box.item
- label="256"
- name="256"
- value="256"/>
- <combo_box.item
label="512"
name="512"
value="512"/>
@@ -672,7 +664,7 @@
increment="8"
initial_value="160"
label="Sky:"
- label_width="145"
+ label_width="164"
layout="topleft"
left="420"
min_val="16"
@@ -758,7 +750,7 @@
control_name="RenderShadowDetail"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="ShadowDetail"
width="150">
@@ -812,7 +804,7 @@
control_name="RenderReflectionProbeDetail"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="ReflectionDetail"
width="150">
@@ -848,7 +840,7 @@
control_name="RenderReflectionProbeLevel"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="ReflectionLevel"
width="150">
@@ -880,7 +872,7 @@
name="ReflectionProbeCount"
text_readonly_color="LabelDisabledColor"
top_delta="22"
- width="128">
+ width="130">
Max Reflection Probes:
</text>
@@ -889,7 +881,7 @@
height="18"
layout="topleft"
label="Max. Reflection Probes:"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="ProbeCount"
width="150">
@@ -923,7 +915,7 @@
increment="0.1"
initial_value="160"
label="Exposure:"
- label_width="145"
+ label_width="164"
layout="topleft"
left="420"
min_val="0.5"
@@ -967,7 +959,7 @@
control_name="RenderHeroProbeResolution"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="MirrorResolution"
width="150">
@@ -1007,7 +999,7 @@
control_name="RenderHeroProbeUpdateRate"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="HeroProbeUpdateRate"
width="150">
@@ -1038,7 +1030,7 @@
increment="0.1"
initial_value="160"
label="Sharpening:"
- label_width="145"
+ label_width="164"
layout="topleft"
left="420"
min_val="0.0"
@@ -1067,7 +1059,7 @@
control_name="RenderTonemapType"
height="18"
layout="topleft"
- left_delta="130"
+ left_delta="175"
top_delta="0"
name="TonemapType"
width="150">
@@ -1089,7 +1081,7 @@
initial_value="1"
label="Tone Mapping Mix:"
tool_tip="Mix between linear and tone mapped colors"
- label_width="145"
+ label_width="164"
layout="topleft"
left="420"
min_val="0.0"
diff --git a/indra/newview/skins/default/xui/en/floater_profile.xml b/indra/newview/skins/default/xui/en/floater_profile.xml
index 32ab811a6e..3a33572785 100644
--- a/indra/newview/skins/default/xui/en/floater_profile.xml
+++ b/indra/newview/skins/default/xui/en/floater_profile.xml
@@ -31,7 +31,7 @@
follows="all"
layout="topleft"
halign="center"
- tab_min_width="81"
+ tab_min_width="80"
tab_height="30"
tab_position="top"
>
diff --git a/indra/newview/skins/default/xui/en/floater_quick_prefs.xml b/indra/newview/skins/default/xui/en/floater_quick_prefs.xml
new file mode 100644
index 0000000000..f5bdcf2156
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_quick_prefs.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ floater_quick_prefs.xml
+ Quick Preferences panel – ported from Firestorm Viewer.
+ Provides on-the-fly access to avatar hover height and max bandwidth.
+-->
+<floater
+ positioning="cascading"
+ can_minimize="true"
+ can_close="true"
+ can_resize="false"
+ height="240"
+ width="320"
+ layout="topleft"
+ name="quick_prefs"
+ single_instance="true"
+ help_topic="quick_prefs"
+ save_rect="true"
+ save_visibility="false"
+ title="QUICK PREFERENCES">
+
+ <!-- ── Hover Height ─────────────────────────────────────────────────── -->
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="28"
+ width="100"
+ name="HoverHeightLabel"
+ tool_tip="Adjust your avatar's hover height above the ground">
+ Hover Height:
+ </text>
+
+ <slider
+ control_name="HoverHeightSlider"
+ decimal_digits="3"
+ enabled="false"
+ can_edit_text="true"
+ follows="left|right|top"
+ height="16"
+ increment="0.001"
+ initial_value="0.0"
+ label_width="0"
+ layout="topleft"
+ left="110"
+ right="-10"
+ top="30"
+ name="HoverHeightSlider"
+ tool_tip="Drag to set your avatar hover height (-3.0 to +3.0 m)" />
+
+ <!-- ── Max Bandwidth ────────────────────────────────────────────────── -->
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top_pad="12"
+ width="100"
+ name="MaxBandwidthLabel"
+ tool_tip="Set the maximum network bandwidth in Kbps">
+ Max Bandwidth:
+ </text>
+
+ <slider
+ control_name="ThrottleBandwidthKBPS"
+ decimal_digits="0"
+ can_edit_text="true"
+ follows="left|right|top"
+ height="16"
+ increment="50"
+ initial_value="500"
+ max_val="3000"
+ min_val="50"
+ label_width="0"
+ layout="topleft"
+ left="110"
+ right="-10"
+ top_delta="-2"
+ name="max_bandwidth"
+ tool_tip="Network bandwidth in Kbps (50 – 3000)" />
+
+ <view_border
+ follows="left|right"
+ layout="topleft"
+ left="2"
+ right="-2"
+ top_pad="10"
+ height="2"
+ name="ots_divider" />
+
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="5"
+ top_pad="6"
+ width="290"
+ text_color="EmphasisColor"
+ name="OTSLabel">
+ Over-the-Shoulder Cam:
+ </text>
+
+ <check_box
+ control_name="OTSEnabled"
+ follows="left|top"
+ height="16"
+ label="Use Over-The-Shoulder Cam"
+ layout="topleft"
+ left="10"
+ top_pad="4"
+ width="290"
+ name="ots_enabled"
+ tool_tip="When checked, M enters shoulder cam instead of first-person mouselook" />
+
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top_pad="6"
+ width="100"
+ name="OTSDistLabel">
+ Distance:
+ </text>
+
+ <slider
+ control_name="OTSCameraDistance"
+ decimal_digits="1"
+ can_edit_text="true"
+ follows="left|right|top"
+ height="16"
+ increment="0.1"
+ initial_value="3.0"
+ max_val="10.0"
+ min_val="1.0"
+ label_width="0"
+ layout="topleft"
+ left="110"
+ right="-10"
+ top_delta="-2"
+ name="ots_distance"
+ tool_tip="Camera distance behind avatar (1 – 10 m)" />
+
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top_pad="4"
+ width="100"
+ name="OTSSideLabel">
+ Side offset:
+ </text>
+
+ <slider
+ control_name="OTSCameraSide"
+ decimal_digits="2"
+ can_edit_text="true"
+ follows="left|right|top"
+ height="16"
+ increment="0.05"
+ initial_value="-0.5"
+ max_val="1.0"
+ min_val="-1.0"
+ label_width="0"
+ layout="topleft"
+ left="110"
+ right="-10"
+ top_delta="-2"
+ name="ots_side"
+ tool_tip="Side offset: negative = right shoulder, positive = left shoulder" />
+
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top_pad="4"
+ width="100"
+ name="OTSHeightLabel">
+ Height:
+ </text>
+
+ <slider
+ control_name="OTSCameraHeight"
+ decimal_digits="2"
+ can_edit_text="true"
+ follows="left|right|top"
+ height="16"
+ increment="0.05"
+ initial_value="0.5"
+ max_val="2.0"
+ min_val="0.0"
+ label_width="0"
+ layout="topleft"
+ left="110"
+ right="-10"
+ top_delta="-2"
+ name="ots_height"
+ tool_tip="Camera height above avatar root (0 – 2 m)" />
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script.xml b/indra/newview/skins/default/xui/en/floater_script.xml
index 900319620d..aca661a6d2 100644
--- a/indra/newview/skins/default/xui/en/floater_script.xml
+++ b/indra/newview/skins/default/xui/en/floater_script.xml
@@ -8,9 +8,9 @@
can_dock="true"
can_minimize="true"
save_rect="true"
- visible="false"
- width="350"
+ visible="false"
+ width="402"
can_resize="false"
- min_width="350"
+ min_width="402"
min_height="200">
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sound_devices.xml b/indra/newview/skins/default/xui/en/floater_sound_devices.xml
deleted file mode 100644
index dec0e9b6c6..0000000000
--- a/indra/newview/skins/default/xui/en/floater_sound_devices.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
- border_visible="false"
- border="false"
- legacy_header_height="18"
- can_minimize="true"
- can_resize="false"
- can_close="false"
- chrome="true"
- save_dock_state="true"
- save_visibility="true"
- save_rect="true"
- single_instance="true"
- bevel_style="in"
- height="164"
- layout="topleft"
- name="floater_sound_devices"
- title="SOUND DEVICES"
- width="490">
- <panel
- layout="topleft"
- follows="all"
- filename="panel_sound_devices.xml"
- name="device_settings_panel"
- width="400"
- left="10"
- top="26"
- class="panel_voice_device_settings"/>
- <text
- name="voice_label"
- top="136"
- left="12"
- height="14"
- width="80"
- layout="topleft"
- >Voice Chat</text>
- <check_box
- layout="topleft"
- control_name="EnableVoiceChat"
- follows="bottom|left"
- top="138"
- left="80"
- name="enable_voice"
- width="100"
- height="14"
- label="Enabled"
- />
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index 1600c422c3..191db4f854 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -418,6 +418,64 @@
</stat_view>
</stat_view>
</stat_view>
+ <stat_view name="voice"
+ label="Voice"
+ setting="OpenDebugStatVoice">
+ <stat_bar
+ name="webrtc_latency"
+ label="Latency"
+ stat="webrtc_latency"
+ unit_label="ms"
+ decimal_digits="1"/>
+ <stat_bar
+ name="webrtc_upload_bandwidth"
+ label="Upload bandwidth"
+ stat="webrtc_upload_bandwidth"
+ unit_label="kbps"
+ decimal_digits="0"/>
+ <stat_view name="incoming_audio"
+ label="Incoming audio"
+ setting="OpenDebugStatVoiceIncoming">
+ <stat_bar
+ name="incoming_packet_recv"
+ label="Packets received"
+ stat="webrtc_packets_in_recv"/>
+ <stat_bar
+ name="packets_in_lost"
+ label="Packets lost"
+ stat="webrtc_packets_in_lost"/>
+ <stat_bar
+ name="jitter_in"
+ label="Jitter"
+ stat="webrtc_jitter_in"
+ unit_label="ms"
+ decimal_digits="1"/>
+ <stat_bar
+ name="jitter_buffer"
+ label="Jitter buffer"
+ stat="webrtc_jitter_buffer"
+ unit_label="ms"
+ decimal_digits="1"/>
+ </stat_view>
+ <stat_view name="outgoing_audio"
+ label="Outgoing audio"
+ setting="OpenDebugStatVoiceOutgoing">
+ <stat_bar
+ name="packets_out_sent"
+ label="Packets sent"
+ stat="webrtc_packets_out_sent"/>
+ <stat_bar
+ name="packets_out_lost"
+ label="Packets lost"
+ stat="webrtc_packets_out_lost"/>
+ <stat_bar
+ name="jitter_out"
+ label="Jitter"
+ stat="webrtc_jitter_out"
+ unit_label="ms"
+ decimal_digits="1"/>
+ </stat_view>
+ </stat_view>
</container_view>
</scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml
index 9d4fb82ec6..7108005f00 100644
--- a/indra/newview/skins/default/xui/en/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/en/floater_telehub.xml
@@ -2,7 +2,7 @@
<!-- Explicit left edge to avoid overlapping build tools -->
<floater
legacy_header_height="18"
- height="250"
+ height="260"
layout="topleft"
name="telehub"
help_topic="telehub"
diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
index 4211d624ac..0d75685223 100644
--- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
@@ -155,4 +155,36 @@
name="item3"
value="tx" />
</combo_box>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="24"
+ width="200">
+ Multiple columns:
+ </text>
+ <combo_box
+ name="multi_column_combo"
+ layout="topleft"
+ height="20"
+ width="150"
+ left_delta="0"
+ top_pad="4">
+ <combo_item name="combo_item1" value="0">
+ <column width="40" name="label" label="|Abc|" />
+ <column name="longtext" label="Match full text" />
+ </combo_item>
+
+ <combo_item name="combo_item2" value="1">
+ <column name="label" label="*Abc*" />
+ <column name="longtext" label="Match substring" />
+ </combo_item>
+
+ <combo_item name="combo_item3" value="2">
+ <column name="label" label="/ *. /" />
+ <column name="longtext" label="Match regular expression" />
+ </combo_item>
+ </combo_box>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_slapp.xml b/indra/newview/skins/default/xui/en/floater_test_slapp.xml
index 5a13a0147e..35f5961285 100644
--- a/indra/newview/skins/default/xui/en/floater_test_slapp.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_slapp.xml
@@ -17,7 +17,6 @@
follows="left|top|right"
height="16"
name="trusted_txt"
- font="SansSerifMedium"
text_color="white"
layout="topleft"
left="16">
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 023df69f0f..e736fc58b2 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -99,7 +99,7 @@
font.name="SansSerifSmall"
name="test_text10"
tool_tip="text">
- SansSerifSmall
+ SansSerif
The 华文细黑 brown fox ヒラキjumped over the lazy dog.
</text>
<text
@@ -111,7 +111,7 @@
font.name="SansSerifMedium"
name="test_text11"
tool_tip="text">
- SansSerif
+ SansSerifMedium
The 华文细黑 brown fox ヒラキjumped over the lazy dog.
</text>
<text
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index dba323a9e1..e4dab5b7ac 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -84,11 +84,14 @@
left="10"
name="button focus"
tool_tip="Focus"
- width="35">
- <button.commit_callback
- function="BuildTool.setTool"
- parameter="Focus" />
- </button>
+ width="35"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Focus" />
+ </button>
<button
follows="left|top"
height="25"
@@ -99,7 +102,10 @@
left_pad="10"
name="button move"
tool_tip="Move"
- width="35">
+ width="35"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.setTool"
parameter="Move" />
@@ -114,7 +120,10 @@
left_pad="10"
name="button edit"
tool_tip="Edit"
- width="35">
+ width="35"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.setTool"
parameter="Edit" />
@@ -129,7 +138,10 @@
left_pad="10"
name="button create"
tool_tip="Create"
- width="35">
+ width="35"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.setTool"
parameter="Create" />
@@ -144,7 +156,10 @@
left_pad="10"
name="button land"
tool_tip="Land"
- width="35">
+ width="35"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.setTool"
parameter="Land" />
@@ -161,15 +176,19 @@
left="8"
name="text status"
top_pad="3"
- width="285">
+ width="285"
+ font="DejaVu"
+ font.size="LSmall">
Drag to move, shift-drag to copy
</text>
<radio_group
layout="topleft"
left="10"
- height="70"
- top="59"
- name="focus_radio_group">
+ height="70"
+ top="59"
+ name="focus_radio_group"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
top_pad="6"
label="Zoom"
@@ -198,16 +217,20 @@
top_delta="-2"
left_delta="100"
name="slider zoom"
- width="134">
+ width="134"
+ font="DejaVu"
+ font.size="LSmall">
<slider_bar.commit_callback
function="BuildTool.commitZoom"/>
</slider_bar>
<radio_group
- left="10"
- height="70"
- top="59"
+ left="10"
+ height="70"
+ top="59"
layout="topleft"
- name="move_radio_group">
+ name="move_radio_group"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
top_pad="6"
label="Move"
@@ -232,7 +255,9 @@
top="55"
height="70"
layout="topleft"
- name="edit_radio_group">
+ name="edit_radio_group"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
label="Move"
layout="topleft"
@@ -263,7 +288,9 @@
label="Edit linked"
layout="topleft"
name="checkbox edit linked parts"
- top_pad="-18">
+ top_pad="-18"
+ font="DejaVu"
+ font.size="LSmall">
<check_box.commit_callback
function="BuildTool.selectComponent"/>
</check_box>
@@ -276,7 +303,10 @@
layout="topleft"
left="143"
name="link_btn"
- width="50">
+ width="50"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.LinkObjects"/>
</button>
@@ -287,7 +317,10 @@
layout="topleft"
left_pad="2"
name="unlink_btn"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1">
<button.commit_callback
function="BuildTool.UnlinkObjects"/>
</button>
@@ -298,10 +331,12 @@
layout="topleft"
left="143"
name="checkbox uniform"
- top="48"
+ top="47"
label_text.wrap="true"
label_text.width="100"
- width="134" />
+ width="134"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
control_name="ScaleStretchTextures"
height="19"
@@ -310,18 +345,22 @@
layout="topleft"
left="143"
name="checkbox stretch textures"
- top_pad="-4"
+ top_pad="-2"
follows="left|top"
- width="134" />
+ width="134"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
control_name="SnapEnabled"
height="18"
initial_value="true"
label="Snap"
layout="topleft"
- top_pad="0"
+ top_pad="-1"
name="checkbox snap to grid"
- width="134" />
+ width="134"
+ font="DejaVu"
+ font.size="LSmall"/>
<combo_box
height="20"
layout="topleft"
@@ -331,7 +370,9 @@
top="83"
left="195"
top_pad="0"
- width="60">
+ width="60"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall">
<combo_box.item
label="World"
name="World"
@@ -577,7 +618,7 @@
layout="topleft"
left_delta="0"
name="checkbox copy selection"
- top_delta="15"
+ top_delta="17"
width="134" />
<check_box
control_name="CreateToolCopyCenters"
@@ -587,7 +628,7 @@
layout="topleft"
left_delta="18"
name="checkbox copy centers"
- top="85"
+ top="92"
width="134" />
<check_box
control_name="CreateToolCopyRotates"
@@ -596,7 +637,7 @@
layout="topleft"
left_delta="0"
name="checkbox copy rotates"
- top_delta="16"
+ top_delta="17"
width="134" />
<radio_group
height="105"
@@ -604,7 +645,9 @@
left="4"
name="land_radio_group"
top="54"
- width="114">
+ width="114"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
height="19"
label="Select Land"
@@ -746,7 +789,8 @@
length="1"
height="16"
follows="left|top"
- font="SansSerifSmall"
+ font="DejaVu"
+ font.size="LSmall"
layout="topleft"
left="10"
name="selection_empty"
@@ -760,7 +804,8 @@
length="1"
height="16"
follows="left|top"
- font="SansSerifSmall"
+ font="DejaVu"
+ font.size="LSmall"
layout="topleft"
left="10"
name="selection_faces"
@@ -775,7 +820,8 @@
length="1"
height="16"
follows="left|top"
- font="SansSerifSmall"
+ font="DejaVu"
+ font.size="LSmall"
layout="topleft"
left="10"
name="selection_count"
@@ -830,7 +876,9 @@
tab_height="25"
open_tabs_on_drag_and_drop="true"
top="173"
- width="295">
+ width="295"
+ font="DejaVu"
+ font.size="LSmall">
<panel
border="false"
@@ -904,7 +952,9 @@
left="10"
name="Name:"
top="5"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall">
Name:
</text>
<line_editor
@@ -923,7 +973,9 @@
left="10"
name="Description:"
top_pad="3"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall">
Description:
</text>
<line_editor
@@ -945,7 +997,9 @@
layout="topleft"
name="Creator:"
top_pad="7"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall">
Creator:
</text>
<avatar_icon
@@ -967,7 +1021,6 @@
height="29"
layout="topleft"
name="Creator Name"
- font="SansSerifSmall"
top_delta="-1"
translate="false"
width="170"
@@ -984,7 +1037,9 @@
layout="topleft"
name="Owner:"
top_pad="3"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall">
Owner:
</text>
<avatar_icon
@@ -1015,7 +1070,8 @@
height="29"
layout="topleft"
name="Owner Name"
- font="SansSerifSmall"
+ font="DejaVu"
+ font.size="LSmall"
left_pad="1"
top_delta="-1"
translate="false"
@@ -1033,7 +1089,9 @@
height="18"
name="Group:"
top_pad="3"
- width="75">
+ width="75"
+ font="DejaVu"
+ font.size="LSmall">
Group:
</text>
<name_box
@@ -1053,7 +1111,10 @@
name="button set group"
tab_stop="false"
tool_tip="Choose a group to share this object's permissions"
- width="23" />
+ width="23"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<check_box
height="19"
follows="left|top"
@@ -1063,7 +1124,9 @@
tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
top_pad="5"
left="100"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<button
follows="top|left"
height="23"
@@ -1073,7 +1136,10 @@
name="button deed"
left_pad="19"
tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."
- width="80" />
+ width="80"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<text
type="string"
length="1"
@@ -1083,7 +1149,9 @@
top_pad="10"
left="10"
name="label click action"
- width="82">
+ width="82"
+ font="DejaVu"
+ font.size="LSmall" >
Click to:
</text>
<combo_box
@@ -1093,7 +1161,9 @@
name="clickaction"
width="130"
left_pad="10"
- tool_tip="A click action enables you to interact with an object with a single left click. Each click action has a special cursor indicating what it does. Some click actions have requirements to function. For example Touch and Pay require scripts" >
+ tool_tip="A click action enables you to interact with an object with a single left click. Each click action has a special cursor indicating what it does. Some click actions have requirements to function. For example Touch and Pay require scripts"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Touch (default)"
name="Touch/grab(default)"
@@ -1134,7 +1204,9 @@
name="checkbox for sale"
left="7"
width="97"
- tool_tip="Lets people buy this object, its content or it copy inworld for specified price." />
+ tool_tip="Lets people buy this object, its content or it copy inworld for specified price."
+ font="DejaVu"
+ font.size="LSmall" />
<!-- NEW PRICE SPINNER
Objects are allowed to be for sale for L$0 to invoke buy UI behavior
even though the user gets a free copy.
@@ -1152,7 +1224,9 @@ even though the user gets a free copy.
min_val="0"
height="20"
max_val="999999999"
- tool_tip="Object cost." />
+ tool_tip="Object cost."
+ font="DejaVu"
+ font.size="LSmall" />
<!-- NEW SALE TYPE COMBO BOX -->
<combo_box
left_pad="8"
@@ -1166,7 +1240,9 @@ even though the user gets a free copy.
mouse_opaque="true"
name="sale type"
width="89"
- tool_tip="Select whether purchaser will receive a copy, copy of the content or item itself." >
+ tool_tip="Select whether purchaser will receive a copy, copy of the content or item itself."
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
name="Copy"
label="Copy"
@@ -1188,7 +1264,9 @@ even though the user gets a free copy.
layout="topleft"
left="7"
name="search_check"
- tool_tip="Let people see this object in search results" />
+ tool_tip="Let people see this object in search results"
+ font="DejaVu"
+ font.size="LSmall" />
<panel
border="false"
follows="left|top"
@@ -1212,7 +1290,9 @@ even though the user gets a free copy.
follows="left|top|right"
layout="topleft"
name="perm_modify"
- width="264">
+ width="264"
+ font="DejaVu"
+ font.size="LSmall" >
You can modify this object
</text>
<text
@@ -1220,7 +1300,9 @@ even though the user gets a free copy.
follows="left|top"
name="Anyone can:"
width="250"
- left="10">
+ left="10"
+ font="DejaVu"
+ font.size="LSmall" >
Anyone:
</text>
<check_box
@@ -1230,7 +1312,9 @@ even though the user gets a free copy.
name="checkbox allow everyone move"
tool_tip="Anyone can move the object."
left="10"
- width="85" />
+ width="85"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Copy"
@@ -1238,14 +1322,18 @@ even though the user gets a free copy.
left_pad="0"
name="checkbox allow everyone copy"
tool_tip="Anyone can take a copy of the object. Object and all of its contents must be copy and transfer permissive."
- width="90" />
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
follows="left|top"
height="19"
name="Next owner can:"
width="250"
- left="10">
+ left="10"
+ font="DejaVu"
+ font.size="LSmall" >
Next owner:
</text>
<check_box
@@ -1256,7 +1344,9 @@ even though the user gets a free copy.
height="10"
name="checkbox next owner can modify"
tool_tip="Next owner can edit properties like item name or scale of this object."
- width="85" />
+ width="85"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
follows="left|top|right"
height="19"
@@ -1265,7 +1355,9 @@ even though the user gets a free copy.
left_pad="0"
name="checkbox next owner can copy"
tool_tip="Next owner can make unlimited copies of this object. Copies maintain creator information, and can never be more permissive than the item being copied."
- width="80" />
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
follows="left|top|right"
height="19"
@@ -1275,7 +1367,9 @@ even though the user gets a free copy.
left_pad="0"
top_delta="0"
tool_tip="Next owner can give away or resell this object."
- width="100" />
+ width="100"
+ font="DejaVu"
+ font.size="LSmall" />
<!-- *NOTE: These "B/O/G/E/N/F fields may overlap "perm_modify" above,
but that's OK, this is used only for debugging. -->
<text
@@ -1288,7 +1382,9 @@ even though the user gets a free copy.
left="230"
name="B:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
B:
</text>
<text
@@ -1301,7 +1397,9 @@ even though the user gets a free copy.
top_pad="2"
name="O:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
O:
</text>
<text
@@ -1314,7 +1412,9 @@ even though the user gets a free copy.
top_pad="2"
name="G:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
G:
</text>
<text
@@ -1327,7 +1427,9 @@ even though the user gets a free copy.
layout="topleft"
name="E:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
E:
</text>
<text
@@ -1340,7 +1442,9 @@ even though the user gets a free copy.
top_pad="2"
name="N:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
N:
</text>
<text
@@ -1353,7 +1457,9 @@ even though the user gets a free copy.
top_pad="2"
name="F:"
height="10"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
F:
</text>
</panel>
@@ -1373,7 +1479,9 @@ even though the user gets a free copy.
name="pathfinding_attributes_label"
top_pad="4"
width="150"
- left="10">
+ left="10"
+ font="DejaVu"
+ font.size="LSmall" >
Pathfinding attributes:
</text>
<text
@@ -1383,7 +1491,9 @@ even though the user gets a free copy.
name="pathfinding_attributes_value"
width="130"
word_wrap="false"
- left_pad="0">
+ left_pad="0"
+ font="DejaVu"
+ font.size="LSmall" >
</text>
</panel>
</panel>
@@ -1408,7 +1518,9 @@ even though the user gets a free copy.
tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits."
top_pad="5"
left="10"
- width="123" />
+ width="123"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Physical"
@@ -1416,7 +1528,9 @@ even though the user gets a free copy.
name="Physical Checkbox Ctrl"
tool_tip="Allows object to be pushed and affected by gravity"
top_pad="0"
- width="123" />
+ width="123"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Temporary"
@@ -1424,7 +1538,9 @@ even though the user gets a free copy.
name="Temporary Checkbox Ctrl"
tool_tip="Causes object to be deleted 1 minute after creation"
top_pad="0"
- width="123" />
+ width="123"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Phantom"
@@ -1432,7 +1548,9 @@ even though the user gets a free copy.
name="Phantom Checkbox Ctrl"
tool_tip="Causes object to not collide with other objects or avatars"
top_pad="0"
- width="123" />
+ width="123"
+ font="DejaVu"
+ font.size="LSmall" />
<view_border
bevel_style="none"
follows="top|left"
@@ -1441,7 +1559,9 @@ even though the user gets a free copy.
left_delta="0"
name="object_horizontal"
top_pad="10"
- width="95" />
+ width="95"
+ font="DejaVu"
+ font.size="LSmall" />
<menu_button
menu_filename="menu_copy_paste_pos.xml"
follows="top|left"
@@ -1465,7 +1585,9 @@ even though the user gets a free copy.
tool_tip="Position (meters)"
left_pad="8"
top_delta="0"
- width="121">
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" >
Position (m)
</text>
<spinner
@@ -1482,7 +1604,9 @@ even though the user gets a free copy.
name="Pos X"
text_enabled_color="1 0 0.3 .7"
top_pad="8"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1497,7 +1621,9 @@ even though the user gets a free copy.
name="Pos Y"
text_enabled_color="EmphasisColor"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1512,7 +1638,9 @@ even though the user gets a free copy.
name="Pos Z"
text_enabled_color="0 0.8 1 .65"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<menu_button
menu_filename="menu_copy_paste_size.xml"
follows="top|left"
@@ -1525,7 +1653,7 @@ even though the user gets a free copy.
top_pad="13"
name="clipboard_size_btn"
tool_tip="Paste options"
- width="19"/>
+ width="19" />
<text
type="string"
length="1"
@@ -1536,7 +1664,9 @@ even though the user gets a free copy.
top_delta="0"
name="label size"
tool_tip="Size (meters)"
- width="121">
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" >
Size (m)
</text>
<spinner
@@ -1553,7 +1683,9 @@ even though the user gets a free copy.
name="Scale X"
text_enabled_color="1 1 1 1"
top_pad="8"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1568,7 +1700,9 @@ even though the user gets a free copy.
name="Scale Y"
text_enabled_color="1 1 1 1"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1583,7 +1717,9 @@ even though the user gets a free copy.
name="Scale Z"
text_enabled_color="1 1 1 1"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<menu_button
menu_filename="menu_copy_paste_rot.xml"
follows="top|left"
@@ -1607,7 +1743,9 @@ even though the user gets a free copy.
top_delta="0"
name="label rotation"
tool_tip="Rotation (degrees)"
- width="121">
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" >
Rotation (°)
</text>
<spinner
@@ -1625,7 +1763,9 @@ even though the user gets a free copy.
name="Rot X"
text_enabled_color="1 1 1 1"
top_pad="8"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -1641,7 +1781,9 @@ even though the user gets a free copy.
name="Rot Y"
text_enabled_color="1 1 1 1"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -1657,7 +1799,9 @@ even though the user gets a free copy.
name="Rot Z"
text_enabled_color="1 1 1 1"
top_pad="3"
- width="87" />
+ width="87"
+ font="DejaVu"
+ font.size="LSmall" />
<!-- <text
type="string"
length="1"
@@ -1686,7 +1830,9 @@ even though the user gets a free copy.
name="comboBaseType"
top="6"
left="125"
- width="125">
+ width="125"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Box"
name="Box"
@@ -1742,7 +1888,9 @@ even though the user gets a free copy.
left="125"
name="text cut"
top_pad="5"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Path Cut (begin/end)
</text>
<spinner
@@ -1757,7 +1905,9 @@ even though the user gets a free copy.
max_val="0.98"
name="cut begin"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="16"
@@ -1770,7 +1920,9 @@ even though the user gets a free copy.
min_val="0.02"
name="cut end"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -1780,7 +1932,9 @@ even though the user gets a free copy.
left="125"
name="text hollow"
top_pad="7"
- width="68">
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" >
Hollow
</text>
<text
@@ -1791,7 +1945,9 @@ even though the user gets a free copy.
layout="topleft"
left_pad="10"
name="text skew"
- width="63">
+ width="63"
+ font="DejaVu"
+ font.size="LSmall" >
Skew
</text>
<spinner
@@ -1805,7 +1961,9 @@ even though the user gets a free copy.
max_val="95"
name="Scale 1"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -1818,7 +1976,9 @@ even though the user gets a free copy.
min_val="-0.95"
name="Skew"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -1828,7 +1988,9 @@ even though the user gets a free copy.
left="125"
name="Hollow Shape"
top_pad="7"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Hollow Shape
</text>
<combo_box
@@ -1837,7 +1999,9 @@ even though the user gets a free copy.
left_delta="0"
name="hole"
top_pad="-2"
- width="150">
+ width="150"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Default"
name="Default"
@@ -1864,7 +2028,9 @@ even though the user gets a free copy.
left_delta="0"
name="text twist"
top_pad="7"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Twist (begin/end)
</text>
<spinner
@@ -1881,7 +2047,9 @@ even though the user gets a free copy.
min_val="-180"
name="Twist Begin"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="0"
follows="left|top"
@@ -1896,7 +2064,9 @@ even though the user gets a free copy.
min_val="-180"
name="Twist End"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -1906,7 +2076,9 @@ even though the user gets a free copy.
left="125"
name="scale_taper"
top_pad="7"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Taper
</text>
<text
@@ -1919,7 +2091,9 @@ even though the user gets a free copy.
left_delta="0"
name="scale_hole"
top_delta="0"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Hole Size
</text>
<spinner
@@ -1935,7 +2109,9 @@ even though the user gets a free copy.
min_val="-1"
name="Taper Scale X"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -1949,7 +2125,9 @@ even though the user gets a free copy.
min_val="-1"
name="Taper Scale Y"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -1959,7 +2137,9 @@ even though the user gets a free copy.
left="125"
name="text topshear"
top_pad="5"
- width="141">
+ width="141"
+ font="DejaVu"
+ font.size="LSmall" >
Top Shear
</text>
<spinner
@@ -1976,7 +2156,9 @@ even though the user gets a free copy.
min_val="-0.5"
name="Shear X"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -1991,7 +2173,9 @@ even though the user gets a free copy.
min_val="-0.5"
name="Shear Y"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
visible="false"
type="string"
@@ -2002,7 +2186,9 @@ even though the user gets a free copy.
left="125"
name="advanced_cut"
top_pad="7"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Profile Cut (begin/end)
</text>
<text
@@ -2015,7 +2201,9 @@ even though the user gets a free copy.
left_delta="0"
name="advanced_dimple"
top_delta="0"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Dimple (begin/end)
</text>
<text
@@ -2027,7 +2215,9 @@ even though the user gets a free copy.
left_delta="0"
name="advanced_slice"
top_delta="0"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Slice (begin/end)
</text>
<spinner
@@ -2042,7 +2232,9 @@ even though the user gets a free copy.
max_val="0.98"
name="Path Limit Begin"
top_pad="3"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2055,7 +2247,9 @@ even though the user gets a free copy.
min_val="0.02"
name="Path Limit End"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
visible="false"
type="string"
@@ -2066,7 +2260,9 @@ even though the user gets a free copy.
left="125"
name="text taper2"
top_pad="7"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Taper
</text>
<spinner
@@ -2083,7 +2279,9 @@ even though the user gets a free copy.
min_val="-1"
name="Taper X"
top_pad="3"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
visible="false"
decimal_digits="2"
@@ -2098,7 +2296,9 @@ even though the user gets a free copy.
min_val="-1"
name="Taper Y"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<text
visible="false"
type="string"
@@ -2109,7 +2309,9 @@ even though the user gets a free copy.
left="125"
name="text radius delta"
top_pad="7"
- width="78">
+ width="78"
+ font="DejaVu"
+ font.size="LSmall" >
Radius
</text>
<text
@@ -2121,7 +2323,9 @@ even though the user gets a free copy.
layout="topleft"
left_delta="78"
name="text revolutions"
- width="68">
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" >
Revolutions
</text>
<spinner
@@ -2135,7 +2339,9 @@ even though the user gets a free copy.
min_val="-1"
name="Radius Offset"
top_pad="4"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
visible="false"
decimal_digits="2"
@@ -2148,7 +2354,9 @@ even though the user gets a free copy.
min_val="1"
name="Revolutions"
top_delta="0"
- width="68" />
+ width="68"
+ font="DejaVu"
+ font.size="LSmall" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
@@ -2161,7 +2369,9 @@ even though the user gets a free copy.
tool_tip="Click to choose a picture"
top="70"
visible="false"
- width="145" />
+ width="145"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<check_box
height="19"
label="Mirror"
@@ -2171,7 +2381,9 @@ even though the user gets a free copy.
tool_tip="Flips sculpted prim along the X axis"
top_pad="8"
visible="false"
- width="130" />
+ width="130"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Inside-out"
@@ -2181,7 +2393,9 @@ even though the user gets a free copy.
tool_tip="Inverts the sculpted prims normals, making it appear inside-out"
top_pad="4"
visible="false"
- width="121" />
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -2192,7 +2406,9 @@ even though the user gets a free copy.
name="label sculpt type"
top_pad="10"
visible="false"
- width="130">
+ width="130"
+ font="DejaVu"
+ font.size="LSmall" >
Stitching type
</text>
<combo_box
@@ -2202,7 +2418,9 @@ even though the user gets a free copy.
name="sculpt type control"
top_pad="4"
visible="false"
- width="150">
+ width="150"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Sphere"
name="Sphere"
@@ -2259,7 +2477,9 @@ even though the user gets a free copy.
name="select_single"
top="5"
width="252"
- word_wrap="true">
+ word_wrap="true"
+ font="DejaVu"
+ font.size="LSmall" >
Select only one primitive to edit features.
</text>
<text
@@ -2271,7 +2491,9 @@ even though the user gets a free copy.
left="10"
name="edit_object"
top="5"
- width="252">
+ width="252"
+ font="DejaVu"
+ font.size="LSmall" >
Edit object features:
</text>
<check_box
@@ -2282,7 +2504,9 @@ even though the user gets a free copy.
name="Animated Mesh Checkbox Ctrl"
tool_tip="Allows rigged mesh objects to be animated independently"
top_pad="10"
- width="121" />
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="10"
label="Flexible Path"
@@ -2292,7 +2516,9 @@ even though the user gets a free copy.
name="Flexible1D Checkbox Ctrl"
tool_tip="Allows object to flex about the Z axis (Client-side only)"
top_pad="15"
- width="121" />
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2305,7 +2531,9 @@ even though the user gets a free copy.
max_val="3"
name="FlexNumSections"
top_pad="10"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2319,7 +2547,9 @@ even though the user gets a free copy.
min_val="-10"
name="FlexGravity"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2332,7 +2562,9 @@ even though the user gets a free copy.
max_val="10"
name="FlexFriction"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2345,7 +2577,9 @@ even though the user gets a free copy.
max_val="10"
name="FlexWind"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2358,7 +2592,9 @@ even though the user gets a free copy.
max_val="10"
name="FlexTension"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2372,7 +2608,9 @@ even though the user gets a free copy.
min_val="-10"
name="FlexForceX"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2386,7 +2624,9 @@ even though the user gets a free copy.
min_val="-10"
name="FlexForceY"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -2400,7 +2640,9 @@ even though the user gets a free copy.
min_val="-10"
name="FlexForceZ"
top_pad="4"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<view_border
bevel_style="none"
follows="top|left"
@@ -2409,7 +2651,9 @@ even though the user gets a free copy.
left="8"
name="object_horizontal"
top_pad="10"
- width="278" />
+ width="278"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="16"
label="Light"
@@ -2418,7 +2662,9 @@ even though the user gets a free copy.
name="Light Checkbox Ctrl"
tool_tip="Causes object to emit light"
top_pad="8"
- width="60" />
+ width="60"
+ font="DejaVu"
+ font.size="LSmall" />
<color_swatch
can_apply_immediately="true"
color="0.5 0.5 0.5 1"
@@ -2430,7 +2676,9 @@ even though the user gets a free copy.
top_pad="-17"
name="colorswatch"
tool_tip="Click to open color picker"
- width="40" />
+ width="40"
+ font="DejaVu"
+ font.size="LSmall" />
<texture_picker
allow_no_texture="true"
top_delta="0"
@@ -2443,7 +2691,9 @@ even though the user gets a free copy.
mouse_opaque="true"
name="light texture control"
tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)"
- width="32" />
+ width="32"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<menu_button
menu_filename="menu_copy_paste_light.xml"
follows="top|left"
@@ -2467,7 +2717,9 @@ even though the user gets a free copy.
left="10"
name="Light Intensity"
top_pad="26"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner bottom_delta="0"
decimal_digits="3"
follows="left|top"
@@ -2481,7 +2733,9 @@ even though the user gets a free copy.
min_val="0"
mouse_opaque="true"
name="Light FOV"
- width="120" />
+ width="120"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner follows="left|top"
height="19"
initial_value="5"
@@ -2492,7 +2746,9 @@ even though the user gets a free copy.
max_val="20"
name="Light Radius"
top_pad="3"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner bottom_delta="0"
decimal_digits="3"
follows="left|top"
@@ -2506,7 +2762,9 @@ even though the user gets a free copy.
min_val="-20"
mouse_opaque="true"
name="Light Focus"
- width="120" />
+ width="120"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner follows="left|top"
height="19"
increment="0.25"
@@ -2518,7 +2776,9 @@ even though the user gets a free copy.
max_val="2"
name="Light Falloff"
top_pad="3"
- width="128" />
+ width="128"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner bottom_delta="0"
decimal_digits="3"
follows="left|top"
@@ -2532,7 +2792,9 @@ even though the user gets a free copy.
min_val="0"
mouse_opaque="true"
name="Light Ambiance"
- width="120" />
+ width="120"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="16"
label="Reflection Probe"
@@ -2541,15 +2803,19 @@ even though the user gets a free copy.
name="Reflection Probe"
tool_tip="Adjusts how objects within this volume receive reflections when PBR is enabled"
top_pad="10"
- width="60" />
+ width="60"
+ font="DejaVu"
+ font.size="LSmall" />
<combo_box
height="19"
top_delta="0"
- left="144"
+ left="144"
follows="left|top"
name="Probe Volume Type"
tool_tip="Choose the probe influence volume"
- width="140">
+ width="140"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Sphere"
name="Sphere"
@@ -2568,7 +2834,9 @@ even though the user gets a free copy.
name="Probe Dynamic"
tool_tip="When enabled, Avatars will appear in reflections within this probe's influence volume."
bottom_delta="19"
- width="60" />
+ width="60"
+ font="DejaVu"
+ font.size="LSmall" />
<text
bottom_delta="-8"
@@ -2580,7 +2848,9 @@ even though the user gets a free copy.
left="10"
name="Probe Update Label"
text_readonly_color="LabelDisabledColor"
- width="100">
+ width="100"
+ font="DejaVu"
+ font.size="LSmall" >
Probe Update
</text>
<combo_box
@@ -2590,7 +2860,9 @@ even though the user gets a free copy.
follows="left|top"
name="Probe Update Type"
tool_tip="Determines how the probe updates. Static updates the slowest and without avatars. Dynamic updates more frequently, with avatars visible in the probes. Mirror (Environment) turns this probe into a realtime planar projected probe that only reflects the environment, but does not calculate ambiance. Mirror (Everything) is similar to Mirror (Environment), but it reflects particles and avatars."
- width="140">
+ width="140"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Static"
name="Static"
@@ -2621,7 +2893,9 @@ even though the user gets a free copy.
min_val="0"
mouse_opaque="true"
name="Probe Ambiance"
- width="120" />
+ width="120"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner bottom_delta="0"
decimal_digits="3"
follows="left|top"
@@ -2635,7 +2909,9 @@ even though the user gets a free copy.
min_val="0"
mouse_opaque="true"
name="Probe Near Clip"
- width="120" />
+ width="120"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -2644,7 +2920,9 @@ even though the user gets a free copy.
layout="topleft"
name="label physicsshapetype"
top="38"
- width="121">
+ width="121"
+ font="DejaVu"
+ font.size="LSmall" >
Physics Shape Type:
</text>
<combo_box
@@ -2654,13 +2932,17 @@ even though the user gets a free copy.
follows="left|top"
name="Physics Shape Type Combo Ctrl"
tool_tip="Choose the physics shape type"
- width="108"/>
+ width="108"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" />
<combo_box
height="19"
layout="topleft"
name="material"
top_pad="5"
- width="150">
+ width="150"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Stone"
name="Stone"
@@ -2703,7 +2985,9 @@ even though the user gets a free copy.
max_val="28"
name="Physics Gravity"
top_pad="10"
- width="132" />
+ width="132"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
@@ -2718,7 +3002,9 @@ even though the user gets a free copy.
min_val="0"
name="Physics Friction"
top_pad="4"
- width="132" />
+ width="132"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
@@ -2734,7 +3020,9 @@ even though the user gets a free copy.
min_val="1"
name="Physics Density"
top_pad="4"
- width="132" />
+ width="132"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
@@ -2749,7 +3037,9 @@ even though the user gets a free copy.
min_val="0"
name="Physics Restitution"
top_pad="8"
- width="132" />
+ width="132"
+ font="DejaVu"
+ font.size="LSmall" />
</panel>
<panel
label="Texture"
@@ -2777,7 +3067,10 @@ even though the user gets a free copy.
left="8"
name="button new script"
top="10"
- width="134" />
+ width="134"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<button
follows="left|top"
height="23"
@@ -2785,7 +3078,10 @@ even though the user gets a free copy.
layout="topleft"
left_pad="8"
name="button permissions"
- width="134" />
+ width="134"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<filter_editor
follows="left|top|right"
label="Enter filter text"
@@ -2822,7 +3118,8 @@ even though the user gets a free copy.
<text
type="string"
length="1"
- font="SansSerifBig"
+ font="DejaVu"
+ font.size="Small"
follows="left|top"
height="19"
layout="topleft"
@@ -2841,7 +3138,9 @@ even though the user gets a free copy.
left="30"
name="label_area_price"
top="48"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Price: L$[PRICE] for [AREA] m²
</text>
<text
@@ -2853,7 +3152,9 @@ even though the user gets a free copy.
left_delta="0"
name="label_area"
top_delta="0"
- width="150">
+ width="150"
+ font="DejaVu"
+ font.size="LSmall" >
Area: [AREA] m²
</text>
<button
@@ -2865,7 +3166,10 @@ even though the user gets a free copy.
left_delta="0"
name="button about land"
top_pad="4"
- width="125" />
+ width="125"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<check_box
control_name="ShowParcelOwners"
height="19"
@@ -2875,11 +3179,14 @@ even though the user gets a free copy.
name="checkbox show owners"
tool_tip="Colorize the parcels according to the type of owner: &#10;&#10;Green = Your land &#10;Aqua = Your group&apos;s land &#10;Red = Owned by others &#10;Yellow = For sale &#10;Purple = For auction &#10;Grey = Public"
top_pad="8"
- width="205" />
+ width="205"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
- font="SansSerifBig"
+ font="DejaVu"
+ font.size="Small"
follows="left|top"
height="19"
layout="topleft"
@@ -2898,7 +3205,10 @@ even though the user gets a free copy.
left="30"
name="button subdivide land"
top="172"
- width="125" />
+ width="125"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<button
follows="left|top"
height="23"
@@ -2908,11 +3218,15 @@ even though the user gets a free copy.
left_delta="0"
name="button join land"
top_pad="4"
- width="125" />
+ width="125"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<text
type="string"
length="1"
- font="SansSerifBig"
+ font="DejaVu"
+ font.size="Small"
follows="left|top"
height="19"
layout="topleft"
@@ -2931,7 +3245,10 @@ even though the user gets a free copy.
left="30"
name="button buy land"
top="276"
- width="125" />
+ width="125"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
<button
follows="left|top"
height="23"
@@ -2941,7 +3258,10 @@ even though the user gets a free copy.
left_delta="0"
name="button abandon land"
top_pad="4"
- width="125" />
+ width="125"
+ font="DejaVu"
+ font.size="LSmall"
+ pad_bottom="1" />
</panel>
<!-- end of tabs -->
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml
index 7fe9830d23..d75d2e0db7 100644
--- a/indra/newview/skins/default/xui/en/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/en/floater_toybox.xml
@@ -16,7 +16,6 @@
width="650">
<text
follows="left|top"
- font="SansSerifMedium"
valign="top"
halign="left"
height="20"
@@ -31,7 +30,6 @@
</text>
<text
follows="left|top"
- font="SansSerifMedium"
valign="top"
halign="left"
height="20"
@@ -49,7 +47,7 @@
button_display_mode="icons_with_text"
follows="all"
left="20"
- button_icon_and_text.button_width.max="140"
+ button_icon_and_text.button_width.max="172"
button_icon_and_text.button_width.min="70"
name="toybox_toolbar"
pad_left="5"
diff --git a/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml
index c0d260ef59..279a05748d 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml
@@ -22,7 +22,7 @@
increment="0.025"
initial_value="0.5"
label="Voice Chat"
- label_width="60"
+ label_width="62"
layout="topleft"
left="15"
top="50"
diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml
deleted file mode 100644
index d037bdb813..0000000000
--- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
- legacy_header_height="27"
- can_resize="true"
- height="500"
- name="voice_effects"
- help_topic="voice_effects"
- title="VOICE MORPHING PREVIEW"
- background_visible="true"
- label="Places"
- layout="topleft"
- min_height="360"
- min_width="200"
- save_rect="true"
- width="300">
- <string name="no_voice_effect">
- (No Voice Morph)
- </string>
- <string name="active_voice_effect">
- (Active)
- </string>
- <string name="unsubscribed_voice_effect">
- (Unsubscribed)
- </string>
- <string name="new_voice_effect">
- (New!)
- </string>
-
- <!-- effect names begin -->
- <string name="effect_Arena">Arena</string>
- <string name="effect_Beast">Beast</string>
- <string name="effect_Buff">Buff</string>
- <string name="effect_Buzz">Buzz</string>
- <string name="effect_Camille">Camille</string>
- <string name="effect_Creepy">Creepy</string>
- <string name="effect_CreepyBot">CreepyBot</string>
- <string name="effect_Cyber">Cyber</string>
- <string name="effect_DeepBot">DeepBot</string>
- <string name="effect_Demon">Demon</string>
- <string name="effect_Female Elf">Female Elf</string>
- <string name="effect_Flirty">Flirty</string>
- <string name="effect_Foxy">Foxy</string>
- <string name="effect_Halloween 2010 Bonus">Halloween_2010_Bonus</string>
- <string name="effect_Helium">Helium</string>
- <string name="effect_Husky">Husky</string>
- <string name="effect_Husky Whisper">Husky Whisper</string>
- <string name="effect_Intercom">Intercom</string>
- <string name="effect_Julia">Julia</string>
- <string name="effect_Lo Lilt">Lo Lilt</string>
- <string name="effect_Macho">Macho</string>
- <string name="effect_Micro">Micro</string>
- <string name="effect_Mini">Mini</string>
- <string name="effect_Model">Model</string>
- <string name="effect_Nano">Nano</string>
- <string name="effect_Nightmare">Nightmare</string>
- <string name="effect_PopBot">PopBot</string>
- <string name="effect_Rachel">Rachel</string>
- <string name="effect_Radio">Radio</string>
- <string name="effect_Robot">Robot</string>
- <string name="effect_Roxanne">Roxanne</string>
- <string name="effect_Rumble">Rumble</string>
- <string name="effect_Sabrina">Sabrina</string>
- <string name="effect_Samantha">Samantha</string>
- <string name="effect_Sexy">Sexy</string>
- <string name="effect_Shorty">Shorty</string>
- <string name="effect_Smaller">Smaller</string>
- <string name="effect_Sneaky">Sneaky</string>
- <string name="effect_Stallion">Stallion</string>
- <string name="effect_Sultry">Sultry</string>
- <string name="effect_Thunder">Thunder</string>
- <string name="effect_Vixen">Vixen</string>
- <string name="effect_WhinyBot">WhinyBot</string>
- <!-- effect names end -->
-
- <text
- height="16"
- word_wrap="true"
- use_ellipses="true"
- type="string"
- follows="left|top|right"
- layout="topleft"
- font="SansSerifBold"
- color="White"
- left="10"
- name="preview_text"
- right="-10"
- top="27">To Preview
- </text>
- <text
- height="23"
- word_wrap="true"
- use_ellipses="true"
- type="string"
- follows="left|top|right"
- layout="topleft"
- left="10"
- name="status_text"
- right="-5"
- top_pad="0">
-Record a sample, then click on a voice to hear how it will sound.
- </text>
- <button
- follows="left|top"
- height="23"
- label="Record"
- layout="topleft"
- left="10"
- name="record_btn"
- tool_tip="Record a sample of your voice."
- top_pad="5"
- width="100">
- <button.commit_callback
- function="VoiceEffect.Record" />
- </button>
- <button
- follows="left|top"
- height="23"
- label="Stop"
- layout="topleft"
- left_delta="0"
- name="record_stop_btn"
- top_delta="0"
- width="100">
- <button.commit_callback
- function="VoiceEffect.Stop" />
- </button>
- <text
- height="23"
- halign="right"
- use_ellipses="true"
- type="string"
- follows="left|top|right"
- layout="topleft"
- left_pad="10"
- top_delta="10"
- name="voice_morphing_link"
- right="-10">
- [[URL] Subscribe Now]
- </text>
- <scroll_list
- bottom="-10"
- draw_heading="true"
- follows="all"
- layout="topleft"
- left="10"
- multi_select="false"
- name="voice_effect_list"
- right="-10"
- tool_tip="Record a sample of your voice, then click an effect to preview."
- top="95">
- <scroll_list.columns
- label="Voice Name"
- name="name"
- relative_width="0.60" />
- <scroll_list.columns
- dynamic_width="true"
- label="Expires"
- name="expires"
- relative_width="0.30" />
- </scroll_list>
-
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
index 4e75b2b29c..fdc1e64e05 100644
--- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
@@ -10,12 +10,12 @@
title="WHITELIST ENTRY"
width="390">
- <text type="string" length="1" bottom="20" follows="top|left" height="15" layout="topleft"
- left="10" name="media_label" top="20">
+ <text type="string" length="1" follows="top|left|right" height="30" layout="topleft"
+ left="10" name="media_label" top="20" right="-10" word_wrap="true">
Enter a URL or URL pattern to add to the list of allowed domains
</text>
- <line_editor bottom_delta="40" enabled="true" follows="left|top" font="SansSerif"
+ <line_editor bottom_delta="15" enabled="true" follows="left|top" font="SansSerif"
height="20" left="10" name="whitelist_entry"
tool_tip="Enter a URL or URL pattern to White List"
width="350" />
diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml
index fb93d32ee4..6535a9a079 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -109,7 +109,7 @@
</panel>
<panel
follows="right|top"
- height="126"
+ height="150"
top_pad="4"
width="238"
left="1"
@@ -167,7 +167,7 @@
follows="top|right"
halign="left"
height="16"
- top_delta="-2"
+ top_delta="-5"
left_pad="7"
layout="topleft"
name="person_label"
@@ -181,9 +181,9 @@
layout="topleft"
left="3"
name="infohub_chk"
- top_pad="3"
+ top_pad="7"
width="22" />
- <icon
+ <icon
follows="top|right"
height="16"
image_name="map_infohub.tga"
@@ -191,7 +191,7 @@
left_pad="0"
mouse_opaque="true"
name="infohub"
- top_delta="0"
+ top_delta="-3"
width="16" />
<text
type="string"
@@ -199,7 +199,7 @@
follows="top|right"
halign="left"
height="16"
- top_delta="2"
+ top_delta="0"
left_pad="3"
layout="topleft"
name="infohub_label"
@@ -213,7 +213,7 @@
layout="topleft"
left="3"
name="land_for_sale_chk"
- top_pad="2"
+ top_pad="8"
width="22" />
<icon
follows="top|right"
@@ -222,16 +222,16 @@
layout="topleft"
mouse_opaque="true"
name="landforsale"
- top_delta="0"
+ top_delta="-3"
left_pad="0"
width="16" />
- <text
+ <text
type="string"
length="1"
follows="top|right"
halign="left"
height="16"
- top_delta="2"
+ top_delta="1"
left_pad="3"
layout="topleft"
name="land_sale_label"
@@ -257,7 +257,7 @@
layout="topleft"
left_pad="0"
name="auction_label"
- top_delta="3"
+ top_delta="1"
width="170">
land auction
</text>
@@ -270,7 +270,7 @@
mouse_opaque="true"
name="square2_owner"
left="20"
- top_pad="-5"
+ top_pad="-2"
width="16" />
<text
type="string"
@@ -280,11 +280,35 @@
layout="topleft"
left_pad="0"
name="by_owner_label"
- top_delta="3"
+ top_delta="0"
width="100">
by owner
</text>
+ <check_box
+ name="grid_coords_chk"
+ control_name="MapShowGridCoords"
+ layout="topleft"
+ follows="top|right"
+ top_pad="5"
+ left="3"
+ height="16"
+ width="22"
+ />
+ <text
+ name="grid_coords_label"
+ type="string"
+ layout="topleft"
+ follows="top|right"
+ top_delta="-2"
+ left_pad="2"
+ height="16"
+ width="220"
+ halign="left"
+ length="1" >
+ Show grid map coordinates
+ </text>
+
<button
follows="top|right"
height="22"
@@ -333,7 +357,7 @@
height="16"
layout="topleft"
left="135"
- top_pad="1"
+ top_pad="5"
name="event_chk"
width="22" />
<icon
@@ -343,6 +367,7 @@
layout="topleft"
mouse_opaque="true"
name="event"
+ top_delta="-2"
left_pad="0"
width="18" />
<text
@@ -351,7 +376,7 @@
follows="top|right"
halign="left"
height="16"
- top_delta="2"
+ top_delta="0"
left_pad="3"
layout="topleft"
name="pg_label"
@@ -367,7 +392,7 @@
layout="topleft"
left="135"
name="events_mature_chk"
- top_pad="3"
+ top_pad="7"
width="22" />
<icon
follows="top|right"
@@ -376,16 +401,16 @@
layout="topleft"
mouse_opaque="true"
name="events_mature_icon"
- top_delta="0"
+ top_delta="-2"
left_pad="0"
width="18" />
- <text
+ <text
type="string"
length="1"
follows="top|right"
halign="left"
height="16"
- top_delta="2"
+ top_delta="0"
left_pad="3"
layout="topleft"
name="events_mature_label"
@@ -400,7 +425,7 @@
layout="topleft"
left="135"
name="events_adult_chk"
- top_pad="3"
+ top_pad="7"
width="22" />
<icon
follows="top|right"
@@ -410,15 +435,15 @@
left_pad="0"
mouse_opaque="true"
name="events_adult_icon"
- top_delta="0"
+ top_delta="-2"
width="18" />
- <text
+ <text
type="string"
length="1"
follows="top|right"
halign="left"
height="16"
- top_delta="2"
+ top_delta="0"
left_pad="3"
layout="topleft"
name="events_adult_label"
@@ -455,7 +480,7 @@
<panel
follows="right|top|bottom"
- height="235"
+ height="220"
top_pad="0"
width="238"
name="layout_panel_4">
@@ -573,7 +598,7 @@
draw_stripes="false"
bg_writeable_color="0.75 0.75 0.75 0.15"
follows="all"
- height="145"
+ height="130"
layout="topleft"
left="28"
name="search_results"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index 45ec1e27f1..1ad01ee120 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<fonts>
- <font name="default" comment="default font files (global fallbacks)">
- <file>DejaVuSans.ttf</file>
+ <font
+ name="default"
+ comment="default font files (global fallbacks)">
+ <file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans.ttf</file>
<file functor="is_emoji">TwemojiSVG.ttf</file>
<os name="Windows">
<file>meiryo.TTC</file>
@@ -31,9 +34,11 @@
</os>
</font>
- <font name="SansSerifBold"
- comment="Name of bold sans-serif font">
- <file>DejaVuSans-Bold.ttf</file>
+ <font
+ name="SansSerifBold"
+ comment="Name of bold sans-serif font">
+ <file load_collection="true" flags="bold" font_weight="700">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
<os name="Windows">
<file>arialbd.ttf</file>
</os>
@@ -42,8 +47,11 @@
</os>
</font>
- <font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
- <file>DejaVuSans.ttf</file>
+ <font
+ name="SansSerif"
+ comment="Name of san-serif font (Truetype file name)">
+ <file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans.ttf</file>
<os name="Windows">
<file>arial.ttf</file>
</os>
@@ -52,31 +60,38 @@
</os>
</font>
- <font name="SansSerif"
- comment="Name of bold sans-serif font"
- font_style="BOLD">
- <file>DejaVuSans-Bold.ttf</file>
+ <font
+ name="SansSerif"
+ comment="Name of bold sans-serif font"
+ font_style="BOLD">
+ <file load_collection="true" flags="bold" font_weight="700">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
</font>
- <font name="SansSerif"
- comment="Name of italic sans-serif font"
- font_style="ITALIC">
- <file>DejaVuSans-Oblique.ttf</file>
+ <font
+ name="SansSerif"
+ comment="Name of italic sans-serif font"
+ font_style="ITALIC">
+ <file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
</font>
- <font name="SansSerif"
- comment="Name of bold italic sans-serif font"
- font_style="BOLD|ITALIC">
- <file>DejaVuSans-BoldOblique.ttf</file>
+ <font
+ name="SansSerif"
+ comment="Name of bold italic sans-serif font"
+ font_style="BOLD|ITALIC">
+ <file load_collection="true" flags="bold" font_weight="700">InterItalicVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
</font>
<font name="Emoji"
comment="Name of emoji font">
<file>TwemojiSVG.ttf</file>
</font>
-
- <font name="Monospace"
- comment="Name of monospace font">
+
+ <font
+ name="Monospace"
+ comment="Name of monospace font">
<file>DejaVuSansMono.ttf</file>
</font>
@@ -103,9 +118,11 @@
<file>DejaVuSans-BoldOblique.ttf</file>
</font>
- <font name="Helvetica"
- comment="Name of Helvetica font">
- <file>DejaVuSans.ttf</file>
+ <font
+ name="Helvetica"
+ comment="Name of Helvetica font">
+ <file font_weight="400">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans.ttf</file>
<os name="Windows">
<file>arial.ttf</file>
</os>
@@ -114,10 +131,12 @@
</os>
</font>
- <font name="Helvetica"
- comment="Name of Helvetica font (bold)"
- font_style="BOLD">
- <file>DejaVuSans-Bold.ttf</file>
+ <font
+ name="Helvetica"
+ comment="Name of Helvetica font (bold)"
+ font_style="BOLD">
+ <file flags="bold" font_weight="700">InterVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
<os name="Windows">
<file>arialbd.ttf</file>
</os>
@@ -126,10 +145,12 @@
</os>
</font>
- <font name="Helvetica"
- comment="Name of Helvetica font (italic)"
- font_style="ITALIC">
- <file>DejaVuSans-Oblique.ttf</file>
+ <font
+ name="Helvetica"
+ comment="Name of Helvetica font (italic)"
+ font_style="ITALIC">
+ <file font_weight="400">InterItalicVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
<os name="Windows">
<file>ariali.ttf</file>
</os>
@@ -138,10 +159,12 @@
</os>
</font>
- <font name="Helvetica"
- comment="Name of Helvetica font (bold italic)"
- font_style="BOLD|ITALIC">
- <file>DejaVuSans-BoldOblique.ttf</file>
+ <font
+ name="Helvetica"
+ comment="Name of Helvetica font (bold italic)"
+ font_style="BOLD|ITALIC">
+ <file font_weight="800">InterItalicVariableFont.ttf</file>
+ <file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
<os name="Windows">
<file>arialbi.ttf</file>
</os>
@@ -150,33 +173,38 @@
</os>
</font>
- <font name="OverrideTest"
- comment="Name of font to test overriding">
+ <font
+ name="OverrideTest"
+ comment="Name of font to test overriding">
<file>times.ttf</file>
- <file>DejaVuSans.ttf</file>
+ <file font_weight="400">InterVariableFont.ttf</file>
</font>
<font_size name="Monospace"
- comment="Size for monospaced font (points, or 1/72 of an inch)"
- size="8.0"
- />
+ comment="Size for monospaced font (points, or 1/72 of an inch)"
+ size="8.0"
+ />
<font_size name="Huge"
- comment="Size of huge font (points, or 1/72 of an inch)"
- size="16.0"
- />
+ comment="Size of huge font (points, or 1/72 of an inch)"
+ size="16.0"
+ />
<font_size name="Large"
- comment="Size of large font (points, or 1/72 of an inch)"
- size="10.6"
- />
+ comment="Size of large font (points, or 1/72 of an inch)"
+ size="11.0"
+ />
<font_size name="Medium"
- comment="Size of medium font (points, or 1/72 of an inch)"
- size="8.6"
- />
+ comment="Size of medium font (points, or 1/72 of an inch)"
+ size="10"
+ />
<font_size name="Small"
- comment="Size of small font (points, or 1/72 of an inch)"
- size="7.6"
- />
- <font_size name="SmallLSL"
+ comment="Size of small font (points, or 1/72 of an inch)"
+ size="9"
+ />
+ <font_size name="LSmall"
+ comment="Legacy size of small font (points, or 1/72 of an inch)"
+ size="7.6"
+ />
+<font_size name="SmallLSL"
comment="Size of small font for LSL editor (points, or 1/72 of an inch)"
size="7"
/>
diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml
index c190d9610f..226454df7c 100644
--- a/indra/newview/skins/default/xui/en/inspect_group.xml
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -9,7 +9,7 @@
bg_opaque_image="Inspector_Background"
can_close="false"
can_minimize="false"
- height="158"
+ height="188"
layout="topleft"
name="inspect_group"
single_instance="true"
@@ -47,7 +47,7 @@
</text>
<text
follows="all"
- height="45"
+ height="65"
left="8"
name="group_details"
use_ellipses="true"
@@ -80,7 +80,7 @@ L$123 to join
height="23"
label="Join"
left="8"
- top="125"
+ top="156"
name="join_btn"
width="103"
commit_callback.function="InspectGroup.Join"/>
@@ -89,7 +89,7 @@ L$123 to join
height="23"
label="Leave"
left="8"
- top="125"
+ top="156"
name="leave_btn"
width="103"
commit_callback.function="InspectGroup.Leave"/>
@@ -98,7 +98,7 @@ L$123 to join
height="23"
label="View Profile"
name="view_profile_btn"
- top="125"
+ top="156"
left="117"
width="103"
commit_callback.function="InspectGroup.ViewProfile" />
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index d978619355..e8f9c10858 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -48,6 +48,34 @@
<menu_item_call.on_click
function="Object.ShowOriginal" />
</menu_item_call>
+ <menu_item_call
+ label="Object profile"
+ name="Object Inspect">
+ <menu_item_call.on_click
+ function="Object.Inspect" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add to favorites"
+ layout="topleft"
+ name="Add to favorites">
+ <menu_item_call.on_click
+ function="Object.SetFavorite"
+ parameter="Add" />
+ <menu_item_call.on_visible
+ function="Object.EnableFavorites"
+ parameter="Add"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Remove from favorites"
+ layout="topleft"
+ name="Remove from favorites">
+ <menu_item_call.on_click
+ function="Object.SetFavorite"
+ parameter="Remove" />
+ <menu_item_call.on_visible
+ function="Object.EnableFavorites"
+ parameter="Remove" />
+ </menu_item_call>
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
index fc4ffde947..f86e9160ed 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -90,6 +90,22 @@
function="Avatar.EnableFreezeEject"/>
</menu_item_call>
<menu_item_call
+ label="Estate Eject"
+ name="EstateEject...">
+ <menu_item_call.on_click
+ function="Avatar.EstateKick" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableEstateEjectBan"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Estate Ban"
+ name="EstateBan...">
+ <menu_item_call.on_click
+ function="Avatar.EstateBan" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableEstateEjectBan"/>
+ </menu_item_call>
+ <menu_item_call
label="Debug Textures"
name="Debug...">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index 62cdaa5886..5a28f0dde5 100644
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -176,57 +176,60 @@
<on_click function="Group.DoToSelected" parameter="leave_group"/>
<on_enable function="Avatar.EnableItem" parameter="can_leave_group" />
</menu_item_call>
- <menu_item_separator layout="topleft" name="Moderator Options Separator"/>
- <context_menu
- label="Moderator Options"
- layout="topleft"
- name="Moderator Options">
- <menu_item_check
- label="Allow text chat"
- layout="topleft"
- name="AllowTextChat">
- <on_check function="Avatar.CheckItem" parameter="is_allowed_text_chat" />
- <on_click function="Avatar.DoToSelected" parameter="toggle_allow_text_chat" />
- <on_enable function="Avatar.EnableItem" parameter="can_allow_text_chat" />
- </menu_item_check>
- <menu_item_separator layout="topleft" name="moderate_voice_separator" />
- <menu_item_call
- label="Mute this participant"
- layout="topleft"
- name="ModerateVoiceMuteSelected">
- <on_click function="Avatar.DoToSelected" parameter="selected" />
- <on_enable function="Avatar.EnableItem" parameter="can_mute" />
- <on_visible function="Avatar.VisibleItem" parameter="show_mute" />
- </menu_item_call>
+ <menu_item_separator layout="topleft" name="Moderator Options Separator"/>
+ <context_menu
+ label="Moderator Options"
+ layout="topleft"
+ name="Moderator Options">
+ <menu_item_check
+ label="Allow text chat"
+ layout="topleft"
+ name="AllowTextChat">
+ <on_check function="Avatar.CheckItem" parameter="is_allowed_text_chat" />
+ <on_click function="Avatar.DoToSelected" parameter="toggle_allow_text_chat" />
+ <on_enable function="Avatar.EnableItem" parameter="can_allow_text_chat" />
+ <on_visible function="Avatar.VisibleItem" parameter="can_allow_text_chat" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" name="moderate_voice_separator">
+ <on_visible function="Avatar.VisibleItem" parameter="can_allow_text_chat" />
+ </menu_item_separator>
+ <menu_item_call
+ label="Mute this participant"
+ layout="topleft"
+ name="ModerateVoiceMuteSelected">
+ <on_click function="Avatar.DoToSelected" parameter="selected" />
+ <on_enable function="Avatar.EnableItem" parameter="can_mute" />
+ <on_visible function="Avatar.VisibleItem" parameter="show_mute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unmute this participant"
+ layout="topleft"
+ name="ModerateVoiceUnMuteSelected">
+ <on_click function="Avatar.DoToSelected" parameter="selected" />
+ <on_enable function="Avatar.EnableItem" parameter="can_unmute" />
+ <on_visible function="Avatar.VisibleItem" parameter="show_unmute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Mute everyone"
+ layout="topleft"
+ name="ModerateVoiceMute">
+ <on_click function="Avatar.DoToSelected" parameter="mute_all" />
+ <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unmute everyone"
+ layout="topleft"
+ name="ModerateVoiceUnmute">
+ <on_click function="Avatar.DoToSelected" parameter="unmute_all" />
+ <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
+ </menu_item_call>
+ </context_menu>
+ <menu_item_separator layout="topleft" name="Group Ban Separator"/>
<menu_item_call
- label="Unmute this participant"
- layout="topleft"
- name="ModerateVoiceUnMuteSelected">
- <on_click function="Avatar.DoToSelected" parameter="selected" />
- <on_enable function="Avatar.EnableItem" parameter="can_unmute" />
- <on_visible function="Avatar.VisibleItem" parameter="show_unmute" />
- </menu_item_call>
- <menu_item_call
- label="Mute everyone"
- layout="topleft"
- name="ModerateVoiceMute">
- <on_click function="Avatar.DoToSelected" parameter="mute_all" />
- <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
- </menu_item_call>
- <menu_item_call
- label="Unmute everyone"
- layout="topleft"
- name="ModerateVoiceUnmute">
- <on_click function="Avatar.DoToSelected" parameter="unmute_all" />
- <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
- </menu_item_call>
- </context_menu>
- <menu_item_separator layout="topleft" name="Group Ban Separator"/>
- <menu_item_call
- label="Ban member"
- layout="topleft"
- name="BanMember">
- <on_click function="Avatar.DoToSelected" parameter="ban_member" />
- <on_enable function="Avatar.EnableItem" parameter="can_ban_member" />
- </menu_item_call>
+ label="Ban member"
+ layout="topleft"
+ name="BanMember">
+ <on_click function="Avatar.DoToSelected" parameter="ban_member" />
+ <on_enable function="Avatar.EnableItem" parameter="can_ban_member" />
+ </menu_item_call>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml
index 864bec5d9a..1e10a984da 100644
--- a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml
@@ -34,6 +34,16 @@
function="CallLog.Check"
parameter="sort_friends_on_top" />
</menu_item_check>
+ <menu_item_check
+ label="Show muted"
+ name="show_muted">
+ <on_click
+ function="CallLog.Action"
+ parameter="show_blocked" />
+ <on_check
+ function="CallLog.Check"
+ parameter="show_blocked" />
+ </menu_item_check>
<menu_item_separator />
<menu_item_call
label="View Nearby chat history..."
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml
index 97f53d3a17..f85f897700 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml
@@ -53,11 +53,7 @@
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_check>
- <menu_item_separator>
- <menu_item_separator.on_visible
- function="Inventory.GearDefault.Visible"
- parameter="single_folder_view" />
- </menu_item_separator>
+ <menu_item_separator/>
<menu_item_check
label="List view"
layout="topleft"
@@ -100,4 +96,46 @@
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
+ <menu_item_check
+ label="Recent tab"
+ layout="topleft"
+ name="recent_tab">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="toggle_recent_tab" />
+ <on_check
+ function="Inventory.GearDefault.Check"
+ parameter="recent_tab" />
+ <on_visible
+ function="Inventory.GearDefault.Visible"
+ parameter="multi_folder_view" />
+ </menu_item_check>
+ <menu_item_check
+ label="Worn tab"
+ layout="topleft"
+ name="worn_tab">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="toggle_worn_tab" />
+ <on_check
+ function="Inventory.GearDefault.Check"
+ parameter="worn_tab" />
+ <on_visible
+ function="Inventory.GearDefault.Visible"
+ parameter="multi_folder_view" />
+ </menu_item_check>
+ <menu_item_check
+ label="Favorites tab"
+ layout="topleft"
+ name="favorites_tab">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="toggle_favorites_tab" />
+ <on_check
+ function="Inventory.GearDefault.Check"
+ parameter="favorites_tab" />
+ <on_visible
+ function="Inventory.GearDefault.Visible"
+ parameter="multi_folder_view" />
+ </menu_item_check>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
index b7a296bf31..8d73eee60a 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -169,4 +169,20 @@
<menu_item_call.on_visible
function="Avatar.EnableFreezeEject"/>
</menu_item_call>
+ <menu_item_call
+ label="Estate Eject"
+ name="estate_eject">
+ <menu_item_call.on_click
+ function="Avatar.EstateKick" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableEstateEjectBan"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Estate Ban"
+ name="estate_ban">
+ <menu_item_call.on_click
+ function="Avatar.EstateBan" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableEstateEjectBan"/>
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index f444275878..48ee13bf21 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -206,6 +206,14 @@
function="Edit.EnableHoverHeight" />
</menu_item_call>
<menu_item_call
+ label="Quick Preferences..."
+ layout="topleft"
+ name="Quick Preferences"
+ shortcut="alt|control|Q">
+ <menu_item_call.on_click
+ function="QuickPrefs" />
+ </menu_item_call>
+ <menu_item_call
label="Edit shape..."
layout="topleft"
name="Edit My Shape">
@@ -982,7 +990,8 @@
</menu_item_check>
<menu_item_check
label="Midday (Legacy)"
- name="legacy noon">
+ name="legacy noon"
+ shortcut="control|shift|T">
<menu_item_check.on_click
function="World.EnvSettings"
parameter="legacy noon" />
@@ -1014,8 +1023,8 @@
</menu_item_check>
<menu_item_check
label="Use Shared Environment"
- shortcut="control|shift|X"
- name="Use Shared Environment">
+ name="Use Shared Environment"
+ shortcut="control|shift|X">
<menu_item_check.on_click
function="World.EnvSettings"
parameter="region" />
@@ -2695,18 +2704,6 @@ function="World.EnvPreset"
parameter="fast timers" />
</menu_item_check>
<menu_item_check
- label="Memory"
- name="Memory"
- shortcut="control|shift|0"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="memory view" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="memory view" />
- </menu_item_check>
- <menu_item_check
label="Scene Statistics"
name="Scene Statistics">
<menu_item_check.on_check
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index dc556d4529..65f26d50e7 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4454,9 +4454,9 @@ Click OK to install.
</notification>
<notification
- icon="alertmodal.tga"
+ icon="alert.tga"
name="PromptOptionalUpdate"
- type="alertmodal">
+ type="alert">
Version [VERSION] has been downloaded and is ready to install.
Release notes: [URL]
@@ -5404,6 +5404,18 @@ Kick [EVIL_USER] from this estate?
<notification
icon="alertmodal.tga"
+ name="EstateBanUser"
+ type="alertmodal">
+Ban [AVATAR_NAME] from this estate?
+ <tag>confirm</tag>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Ban"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="EstateChangeCovenant"
type="alertmodal">
Are you sure you want to change the Estate Covenant?
@@ -8614,10 +8626,10 @@ Scripts associated with this experience will be able to do the following on regi
priority="critical"
persist="true"
type="notify">
-Warning: The object &apos;&lt;nolink&gt;[OBJECTNAME]&lt;/nolink&gt;&apos; wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings.
-
-Do not allow access if you do not fully understand why it wants access to your account.
+Warning:
+[WARNINGS]
+Do not allow access if you do not fully understand why it wants access to your account.
<tag>confirm</tag>
<form name="form">
<button
@@ -8630,9 +8642,7 @@ Do not allow access if you do not fully understand why it wants access to your a
name="Deny"
text="Deny"/>
</form>
- <footer>
-[FOOTERTEXT]
- </footer>
+ <footer>[FOOTERTEXT]</footer>
</notification>
<notification
@@ -9147,6 +9157,14 @@ Failed to save snapshot to [PATH]: Disk is full. [NEED_MEMORY]KB is required but
Failed to save snapshot to [PATH]: Directory does not exist.
</notification>
+ <notification icon="notifytip.tga"
+ name="SnapshotSavedToComputer" type="notifytip">
+Screenshot saved to:
+ [FILEPATH]
+
+Click to open folder.
+ </notification>
+
<notification
icon="notifytip.tga"
name="PresetNotSaved"
@@ -9222,6 +9240,23 @@ Your voice has been muted by moderator.
</notification>
<notification
+ icon="notifytip.tga"
+ name="NearbyVoiceMutedByModerator"
+ type="notifytip">
+ The moderator has muted your voice chat.
+People in this location will not hear you if you speak.
+ <tag>voice</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="NearbyVoiceUnmutedByModerator"
+ type="notifytip">
+ Your voice chat can now be heard by people in this location.
+ <tag>voice</tag>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="FailedToGetBenefits"
type="alertmodal">
@@ -9706,6 +9741,22 @@ Are you sure you want to leave this call?
<notification
icon="alertmodal.tga"
+ name="ConfirmLeaveAdhoc"
+ type="alertmodal">
+Are you sure you want to leave this conference chat?
+ <tag>confirm</tag>
+ <tag>voice</tag>
+ <usetemplate
+ ignoretext="Confirm before I leave conference chat"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes">
+ <unique/>
+ </usetemplate>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="ConfirmMuteAll"
type="alert">
You have selected to mute all participants in a group call.
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index 970c6ad2f5..2b5682bf06 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -61,7 +61,7 @@
left_pad="5"
name="avatar_name"
parse_urls="false"
- top="6"
+ top="5"
use_ellipses="true"
value="(loading)"
width="0" />
diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
index 6bb891db63..d907a050b6 100644
--- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
@@ -10,6 +10,18 @@
min_height="350"
min_width="240"
width="323">
+ <string
+ name="no_blocked"
+ value="No blocked residents or objects." />
+ <string
+ name="no_filtered_blocked"
+ value="No blocked residents or objects match your search." />
+ <string
+ name="loading_blocked"
+ value="Loading blocked residents and objects..." />
+ <string
+ name="failed_blocked"
+ value="Blocked list is currently unavailable." />
<panel
follows="left|top|right"
height="27"
diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml
index 5ac0bf54de..6b4312a22a 100644
--- a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml
@@ -65,7 +65,7 @@
left_pad="5"
name="item_name"
parse_urls="false"
- top="6"
+ top="4"
use_ellipses="true"
width="180" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
index 4f48911376..dde2df7128 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_header.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -23,7 +23,7 @@
<text
parse_urls="false"
allow_scroll="false"
- v_pad = "6"
+ v_pad = "4"
read_only = "true"
follows="left|right"
font.style="BOLD"
@@ -49,7 +49,7 @@
left_pad="5"
name="time_box"
right="-5"
- top="7"
+ top="5"
value="23:30"
width="110" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
index 5406497930..c43f82c0f1 100644
--- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml
@@ -109,7 +109,7 @@
image_overlay_alignment="center"
image_pressed="WellButton_Lit"
image_pressed_selected="WellButton_Lit_Selected"
- image_selected="PushButton_Press"
+ image_selected="PushButton_Selected"
label_color="Black"
left="0"
name="Unread"
diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
index 7902588598..90e367543e 100644
--- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
@@ -78,7 +78,7 @@
left="5"
name="conversation_title"
parse_urls="false"
- top="6"
+ top="4"
use_ellipses="true"
value="(loading)"
width="35" />
@@ -86,6 +86,7 @@
auto_update="true"
follows="top|right"
draw_border="false"
+ top="6"
height="16"
layout="topleft"
left_pad="5"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
index bd0335df6e..7c528c5319 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
@@ -15,7 +15,7 @@
<string name="height_value_label_color" translate="false">White</string>
<text
follows="top|left|right"
- font="SansSerifSmallBold"
+ font="SansSerifSmall"
halign="right"
height="12"
layout="topleft"
@@ -36,7 +36,7 @@
layout="topleft"
left="10"
name="accordion_panel"
- top_pad="0"
+ top_pad="5"
width="313">
<accordion
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_experience_search.xml b/indra/newview/skins/default/xui/en/panel_experience_search.xml
index bb07476ad0..7867361623 100644
--- a/indra/newview/skins/default/xui/en/panel_experience_search.xml
+++ b/indra/newview/skins/default/xui/en/panel_experience_search.xml
@@ -47,12 +47,14 @@
<text
name="lbl name part"
left="0"
+ top_pad="1"
follows="top|left|right"
right="-1">
Enter part of the name:
</text>
<line_editor
left="0"
+ top_pad="9"
follows="left|top|right"
name="edit"
height="18"
@@ -121,7 +123,7 @@
draw_heading="true"
left="0"
right="-1"
- height="239"
+ height="236"
top_pad="4"
follows="all"
column_padding="5"
diff --git a/indra/newview/skins/default/xui/en/panel_gltf_material.xml b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
index 45df40bc05..697c6e60b7 100644
--- a/indra/newview/skins/default/xui/en/panel_gltf_material.xml
+++ b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
@@ -7,7 +7,7 @@
top="0"
left="0"
height="768"
- width="247">
+ width="257">
<check_box
follows="left|top"
layout="topleft"
@@ -20,7 +20,7 @@
<panel
border="true"
follows="left|top"
- width="246"
+ width="256"
height="196"
layout="topleft"
left="1"
@@ -175,7 +175,7 @@
<panel
border="true"
follows="left|top"
- width="246"
+ width="256"
height="175"
layout="topleft"
left="1"
@@ -252,7 +252,7 @@
layout="topleft"
left_delta="0"
top_pad="5"
- width="96"
+ width="105"
name="roughness_factor_lbl">
Roughness Factor
</text>
@@ -273,7 +273,7 @@
<panel
border="true"
follows="left|top"
- width="246"
+ width="256"
height="175"
layout="topleft"
left="1"
@@ -343,7 +343,7 @@
<panel
border="true"
follows="left|top"
- width="246"
+ width="256"
height="175"
layout="topleft"
left="1"
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index aac4037bb3..e0fec0f5fd 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel
label="General"
- height="420"
+ height="580"
width="304"
class="panel_group_general"
name="general_tab">
@@ -64,8 +64,7 @@ Hover your mouse over the options for more help.
use_ellipses="true"
width="168" />
<text
- font="SansSerifMedium"
- text_color="white"
+ text_color="white"
type="string"
follows="left|top"
height="16"
@@ -86,7 +85,63 @@ Hover your mouse over the options for more help.
name="btn_join"
visible="true"
width="120" />
+ <button
+ follows="left|top"
+ left_pad="6"
+ top_delta="0"
+ height="23"
+ label="Activate"
+ name="btn_activate"
+ visible="true"
+ width="120" />
+ </panel>
+
+ <!-- Nameplate tinting: isolated panel, placed after group_info_top -->
+ <panel
+ name="nametag_color_panel"
+ follows="left|right|top"
+ layout="topleft"
+ left="0"
+ top="129"
+ width="304"
+ height="36"
+ background_visible="false">
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="5"
+ top="2"
+ width="160"
+ name="nametag_color_label"
+ text_color="EmphasisColor">
+ Nameplate Color:
+ </text>
+ <color_swatch
+ can_apply_immediately="false"
+ follows="left|top"
+ height="22"
+ label=""
+ label_height="0"
+ layout="topleft"
+ left="170"
+ top="2"
+ name="group_nametag_color"
+ tool_tip="Click to set nameplate color for this group"
+ width="54" />
+ <button
+ follows="left|top"
+ height="22"
+ label="Clear"
+ layout="topleft"
+ left="230"
+ top="2"
+ name="group_nametag_color_clear"
+ tool_tip="Remove the nameplate color for this group"
+ width="60" />
</panel>
+
<text_editor
type="string"
follows="left|top|right"
@@ -96,7 +151,7 @@ Hover your mouse over the options for more help.
max_length="511"
name="charter"
parse_urls="true"
- top="105"
+ top="170"
right="-4"
bg_readonly_color="DkGray2"
text_readonly_color="White"
diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
index ff6af88707..dff00e4e60 100644
--- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
@@ -44,7 +44,7 @@
layout="topleft"
left_pad="5"
name="group_name"
- top="6"
+ top="4"
use_ellipses="true"
value="Unknown"
width="242" />
diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml
index 1162dcf20d..2ecc4585ba 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml
@@ -28,7 +28,7 @@ You can turn off Notices on the General tab.
left="5"
name="lbl2"
right="-1"
- top="5"
+ top="3"
width="300">
Notices are kept for 14 days.
Maximum 200 per group daily
@@ -42,7 +42,7 @@ Maximum 200 per group daily
left="0"
right="-1"
name="notice_list"
- top_pad="0"
+ top_pad="6"
width="304">
<scroll_list.columns
label=""
@@ -276,7 +276,6 @@ Maximum 200 per group daily
width="313">
<text
type="string"
- font="SansSerifMedium"
height="16"
layout="topleft"
left="10"
diff --git a/indra/newview/skins/default/xui/en/panel_hint.xml b/indra/newview/skins/default/xui/en/panel_hint.xml
index 7442136761..741ed5af41 100644
--- a/indra/newview/skins/default/xui/en/panel_hint.xml
+++ b/indra/newview/skins/default/xui/en/panel_hint.xml
@@ -3,7 +3,6 @@
width="205"
height="34">
<text name="hint_title"
- font="SansSerifMedium"
left="8"
right="180"
top="8"
diff --git a/indra/newview/skins/default/xui/en/panel_hint_image.xml b/indra/newview/skins/default/xui/en/panel_hint_image.xml
index d712245df8..3e3205531f 100644
--- a/indra/newview/skins/default/xui/en/panel_hint_image.xml
+++ b/indra/newview/skins/default/xui/en/panel_hint_image.xml
@@ -4,7 +4,6 @@
height="40"
layout="topleft">
<text name="hint_title"
- font="SansSerifMedium"
left="8"
right="290"
top="8"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 0682a5d680..d856b3f66c 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -6,7 +6,7 @@
name="panel_login"
focus_root="true"
background_visible="true"
- bg_opaque_color="0.0 0.0 0.0 1"
+ bg_opaque_color="DkGrayLogin"
background_opaque="true"
width="1024">
<panel.string
@@ -18,182 +18,379 @@
https://join.secondlife.com/
</panel.string>
<layout_stack
- follows="left|right|top"
- height="172"
- left="0"
- name="ui_stack"
- orientation="horizontal"
- top="10"
- width="1024">
+ follows="all"
+ layout="topleft"
+ orientation="horizontal"
+ name="main_stack"
+ border_size="0"
+ animate="false"
+ top="0"
+ left="0"
+ height="768"
+ width="1024">
+ <layout_panel
+ auto_resize="true"
+ user_resize="false"
+ layout="topleft"
+ name="left_spacer"
+ background_visible="false"
+ min_width="0"
+ expanded_min_dim="0"
+ width="1">
+ </layout_panel>
<layout_panel
- height="172"
- auto_resize="true"
- name="ui_elastic_pad_left"
- width="32" />
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="center_stage"
+ background_visible="true"
+ bg_opaque_color="DkGrayLogin"
+ background_opaque="true"
+ width="1008"
+ height="768">
+ <layout_stack
+ follows="all"
+ layout="topleft"
+ orientation="horizontal"
+ name="ui_stack"
+ border_size="0"
+ animate="false"
+ top="0"
+ left="0"
+ height="768"
+ width="1008">
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="ui_container"
+ width="300"
+ height="768"
+ background_visible="true"
+ bg_opaque_color="PanelDark"
+ background_opaque="true">
+ <icon
+ height="77"
+ width="160"
+ image_name="login_mp_logo_horizontal"
+ layout="topleft"
+ follows="left|top"
+ left="70"
+ top="39"
+ name="mp_logo_small" />
+ <icon
+ left="40"
+ top_pad="30"
+ width="220"
+ height="28"
+ image_name="TextField_Active"
+ layout="topleft"
+ follows="left|top"
+ name="text_field_bg1" />
+ <combo_box
+ left="40"
+ top_delta="0"
+ allow_text_entry="true"
+ follows="left|top"
+ layout="topleft"
+ height="28"
+ label="Username"
+ combo_editor.font="SansSerifLarge"
+ max_chars="128"
+ combo_editor.commit_on_focus_lost="false"
+ combo_editor.prevalidator="ascii"
+ tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
+ name="username_combo"
+ width="220">
+ <combo_box.combo_button
+ image_overlay="ComboButton_Arrow"
+ image_overlay_right_delta="10"
+ image_unselected="ComboButton_Transparent"
+ hover_glow_amount="0"
+ image_selected="ComboButton_Transparent"
+ image_disabled="ComboButton_Transparent" />
+ <combo_box.combo_editor
+ background_image="TextField_Transparent"
+ background_image_disabled="TextField_Transparent"
+ background_image_focused="TextField_Transparent"
+ draw_focus_border="false"
+ text_pad_left="8"
+ bg_image_always_focused="true"/>
+ </combo_box>
+ <check_box
+ follows="left|top"
+ font="SansSerifMedium"
+ label_text.text_color="White"
+ top_pad="3"
+ layout="topleft"
+ height="24"
+ label="Remember username"
+ word_wrap="down"
+ check_button.bottom="3"
+ name="remember_name"
+ tool_tip="Already remembered user can be forgotten from Me &gt; Preferences &gt; Advanced &gt; Remembered Usernames."
+ width="198">
+ <check_box.label_text left="23"/>
+ <check_box.check_button
+ image_selected="Checkbox_Slim_On"
+ image_unselected="Checkbox_Slim_Off"
+ image_pressed="Checkbox_Slim_Off"
+ image_pressed_selected="Checkbox_Slim_Off"/>
+ </check_box>
+ <line_editor
+ follows="left|top"
+ height="28"
+ top_pad="20"
+ max_length_chars="16"
+ text_pad_left="8"
+ name="password_edit"
+ label="Password"
+ bg_image_always_focused="true"
+ font="SansSerifLarge"
+ is_password="true"
+ select_on_focus="true"
+ draw_focus_border="false"
+ commit_on_focus_lost="false"
+ width="220" />
+ <check_box
+ control_name="RememberPassword"
+ follows="left|top"
+ font="SansSerifMedium"
+ label_text.text_color="White"
+ height="24"
+ top_pad="3"
+ label="Remember password"
+ word_wrap="down"
+ check_button.bottom="3"
+ name="remember_password"
+ width="165">
+ <check_box.label_text left="23"/>
+ <check_box.check_button
+ image_selected="Checkbox_Slim_On"
+ image_unselected="Checkbox_Slim_Off"
+ image_pressed="Checkbox_Slim_Off"
+ image_pressed_selected="Checkbox_Slim_Off"/>
+ </check_box>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ text_color="White"
+ height="12"
+ name="location_text"
+ top_pad="18"
+ width="120"
+ valign="center">
+ Start here
+ </text>
+ <icon
+ top_pad="6"
+ width="220"
+ height="28"
+ image_name="TextField_Active"
+ layout="topleft"
+ follows="left|top"
+ name="text_field_bg2" />
+ <combo_box
+ allow_text_entry="true"
+ control_name="NextLoginLocation"
+ follows="left|top"
+ label="My favorite places"
+ height="28"
+ max_chars="128"
+ combo_editor.font="SansSerifLarge"
+ top_delta="0"
+ name="start_location_combo"
+ width="220"
+ combo_button.scale_image="true">
+ <combo_box.combo_button
+ image_overlay="ComboButton_Arrow"
+ hover_glow_amount="0"
+ image_overlay_right_delta="10"
+ image_unselected="ComboButton_Transparent"
+ image_selected="ComboButton_Transparent"
+ image_disabled="ComboButton_Transparent" />
+ <combo_box.combo_editor
+ background_image="TextField_Transparent"
+ background_image_disabled="TextField_Transparent"
+ background_image_focused="TextField_Transparent"
+ draw_focus_border="false"
+ text_pad_left="8"
+ bg_image_always_focused="true"/>
+ <combo_box.item
+ label="My last location"
+ name="MyLastLocation"
+ value="last" />
+ <combo_box.item
+ label="My home"
+ name="MyHome"
+ value="home" />
+ </combo_box>
+ <layout_stack
+ follows="left|top"
+ layout="topleft"
+ orientation="vertical"
+ name="login_stack"
+ border_size="0"
+ animate="false"
+ top_pad="0"
+ left="0"
+ height="218"
+ width="300">
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="grid_panel"
+ background_visible="false"
+ height="64"
+ width="300">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ text_color="white"
+ height="12"
+ name="grid_text"
+ top="18"
+ left="40"
+ width="120"
+ valign="center">
+ Grid
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ font="SansSerifTiny"
+ follows="left|top"
+ height="28"
+ top_pad="6"
+ left="40"
+ max_chars="128"
+ label="Select grid"
+ layout="topleft"
+ name="server_combo"
+ width="220">
+ <combo_box.drop_down_button
+ pad_bottom="1"
+ pad_left="10"
+ font="SansSerifLarge"
+ label_color="Black"
+ label_color_selected="Black"
+ draw_focus_border="false"
+ image_overlay="ComboButton_Arrow"
+ image_overlay_right_delta="10"
+ image_unselected="TextField_Active"
+ image_selected="TextField_Active"
+ image_pressed="TextField_Active"
+ image_pressed_selected="TextField_Active"/>
+ </combo_box>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="login_panel"
+ background_visible="false"
+ height="172"
+ width="300">
+ <button
+ follows="left|top"
+ image_unselected="PushButton_Login"
+ image_pressed="PushButton_Login_Pressed"
+ image_hover_unselected="PushButton_Login_Over"
+ label="Log in"
+ label_color="Black"
+ label_color_disabled="Black"
+ font="SansSerifLarge"
+ font.style="BOLD"
+ name="connect_btn"
+ draw_focus_border="false"
+ hover_hand_cursor="true"
+ enabled="true"
+ width="220"
+ height="30"
+ left="40"
+ top="25"
+ pad_bottom="1" />
+ <text
+ follows="left|top"
+ font="SansSerifMedium"
+ text_color="EmphasisColor"
+ height="15"
+ name="forgot_password_text"
+ left="60"
+ top_pad="9"
+ width="180"
+ halign="center">
+ Need help logging in?
+ </text>
+ <button
+ follows="left|top"
+ image_unselected="PushButton_Sign"
+ image_pressed="PushButton_Sign_Pressed"
+ image_hover_unselected="PushButton_Sign_Over"
+ label="Create account"
+ label_color="White"
+ label_color_disabled="Black"
+ font="SansSerifMedium"
+ font.style="BOLD"
+ name="sign_btn"
+ draw_focus_border="false"
+ hover_hand_cursor="true"
+ width="220"
+ height="35"
+ left="40"
+ top_pad="25"
+ pad_bottom="1" />
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="middle_gutter"
+ min_width="18"
+ max_width="18"
+ expanded_min_dim="18"
+ width="18"
+ height="768"
+ background_visible="true"
+ bg_opaque_color="DkGrayLogin"
+ background_opaque="true">
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ name="web_container"
+ width="690"
+ height="768"
+ background_visible="true"
+ bg_opaque_color="DkGrayLogin"
+ background_opaque="true">
+ <web_browser
+ tab_stop="false"
+ trusted_content="true"
+ bg_opaque_color="DkGrayLogin"
+ border_visible="false"
+ follows="all"
+ left="0"
+ top="0"
+ right="-1"
+ bottom="-1"
+ name="login_html"
+ start_url="" />
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
<layout_panel
- auto_resize="false"
- follows="left|right|top"
- name="ui_container"
- width="1011"
- left="0"
- top="0"
- height="172">
- <icon
- height="73"
- width="165"
- image_name="login_mp_logo"
- left="0"
- top="25"
- name="sl_logo_small" />
- <combo_box
- left_pad="22"
- bottom_delta="-7"
- allow_text_entry="true"
- follows="left|top"
- height="32"
- label="Username"
- combo_editor.font="SansSerifLarge"
- max_chars="128"
- combo_editor.commit_on_focus_lost="false"
- combo_editor.prevalidator="ascii"
- tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
- name="username_combo"
- width="206">
- <combo_box.combo_editor
- text_pad_left="8"
- bg_image_always_focused="true"/>
- </combo_box>
- <line_editor
- follows="left|top"
- height="32"
- left_pad="15"
- max_length_chars="16"
- text_pad_left="8"
- name="password_edit"
- label="Password"
- bg_image_always_focused="true"
- font="SansSerifLarge"
- is_password="true"
- select_on_focus="true"
- commit_on_focus_lost="false"
- bottom_delta="0"
- width="165" />
- <combo_box
- allow_text_entry="true"
- control_name="NextLoginLocation"
- follows="left|top"
- label="My favorite places"
- height="32"
- max_chars="128"
- combo_editor.font="SansSerifLarge"
- left_pad="15"
- bottom_delta="0"
- name="start_location_combo"
- width="175"
- combo_button.scale_image="true">
- <combo_box.combo_editor
- bg_image_always_focused="true"
- text_pad_left="8"/>
- <combo_box.item
- label="My last location"
- name="MyLastLocation"
- value="last" />
- <combo_box.item
- label="My home"
- name="MyHome"
- value="home" />
- </combo_box>
- <button
- follows="left|top"
- image_unselected="PushButton_Login"
- image_pressed="PushButton_Login_Pressed"
- image_hover_unselected="PushButton_Login_Over"
- label="Log In"
- label_color="White"
- font="SansSerifMedium"
- name="connect_btn"
- enabled="true"
- width="120"
- height="32"
- left_pad="15"
- bottom_delta="0" />
- <text
- follows="left|top"
- font="SansSerifLarge"
- font.style="BOLD"
- text_color="EmphasisColor"
- height="34"
- name="sign_up_text"
- left_pad="10"
- width="200"
- valign="center">
- Sign up
- </text>
- <check_box
- follows="left|top"
- font="SansSerifMedium"
- left="185"
- bottom_delta="21"
- height="24"
- label="Remember me"
- word_wrap="down"
- check_button.bottom="3"
- name="remember_name"
- tool_tip="Already remembered user can be forgotten from Me &gt; Preferences &gt; Advanced &gt; Remembered Usernames."
- width="198" />
- <check_box
- control_name="RememberPassword"
- follows="left|top"
- font="SansSerifMedium"
- height="24"
- left="408"
- bottom_delta="0"
- label="Remember password"
- word_wrap="down"
- check_button.bottom="3"
- name="remember_password"
- width="165" />
- <combo_box
- allow_text_entry="false"
- font="SansSerifTiny"
- follows="left|top"
- height="26"
- left="588"
- bottom_delta="8"
- max_chars="128"
- label="Select grid"
- layout="topleft"
- name="server_combo"
- width="149" />
- <text
- follows="left|top"
- font="SansSerifMedium"
- text_color="EmphasisColor"
- height="16"
- name="forgot_password_text"
- left="778"
- bottom_delta="-8"
- width="120"
- halign="center">
- Password help
- </text>
- </layout_panel>
- <layout_panel
- height="172"
- auto_resize="true"
- name="ui_elastic_pad_right"
- width="32" />
+ auto_resize="true"
+ user_resize="false"
+ layout="topleft"
+ name="right_spacer"
+ background_visible="false"
+ min_width="0"
+ expanded_min_dim="0"
+ width="1">
+ </layout_panel>
</layout_stack>
- <web_browser
- tab_stop="false"
- trusted_content="true"
- bg_opaque_color="Black"
- border_visible="false"
- follows="all"
- left="0"
- name="login_html"
- start_url=""
- top="154"
- height="600"
- width="1024" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml
deleted file mode 100644
index d6ac71db94..0000000000
--- a/indra/newview/skins/default/xui/en/panel_login_first.xml
+++ /dev/null
@@ -1,262 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel
- follows="all"
- height="768"
- layout="topleft"
- name="panel_login"
- focus_root="true"
- background_visible="true"
- bg_opaque_color="0.16 0.16 0.16 1"
- background_opaque="true"
- width="1024">
- <panel.string
- name="forgot_password_url">
- http://secondlife.com/account/request.php
- </panel.string>
- <panel.string
- name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack
- follows="left|right|top|bottom"
- width="1024"
- height="768"
- left="0"
- name="logo_stack"
- orientation="vertical"
- top="0">
- <layout_panel
- height="18"
- auto_resize="false"
- name="page_top"
- width="1024" />
- <!-- start of logo stack -->
- <layout_panel
- height="130"
- min_height="10"
- auto_resize="false"
- name="parent_panel"
- width="1024">
- <layout_stack
- follows="left|right|top|bottom"
- height="100"
- left="0"
- name="logo_stack"
- orientation="horizontal"
- top="0"
- width="1024">
- <layout_panel
- height="110"
- min_height="10"
- auto_resize="true"
- name="logo_left"
- width="300" />
- <layout_panel
- auto_resize="false"
- follows="left|right|top"
- name="logo_container"
- width="225"
- left="0"
- top="0"
- height="105">
- <icon
- height="94"
- image_name="login_sl_logo"
- left="0"
- name="sl_logo"
- top="0" />
- </layout_panel>
- <layout_panel
- height="100"
- name="logo_right"
- auto_resize="true"
- width="300" />
- </layout_stack>
- </layout_panel>
- <!-- end of logo stack -->
- <!-- start of widget stack -->
- <layout_panel
- height="100"
- min_height="10"
- auto_resize="false"
- name="parent_panel2"
- width="1024">
- <layout_stack
- follows="left|right|top|bottom"
- height="80"
- left="0"
- name="widget_stack"
- orientation="horizontal"
- top="0"
- width="1024">
- <layout_panel
- height="80"
- min_height="10"
- auto_resize="true"
- name="widget_left"
- width="200" />
- <layout_panel
- auto_resize="false"
- follows="left|right|top"
- name="widget_container"
- width="730"
- left="0"
- top="0"
- height="80">
- <combo_box
- allow_text_entry="true"
- follows="left|bottom"
- height="32"
- left="42"
- label="Username"
- combo_editor.font="SansSerifLarge"
- max_chars="128"
- top="0"
- combo_editor.prevalidator="ascii"
- tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
- name="username_combo"
- width="232">
- <combo_box.combo_editor
- text_pad_left="8" />
- <combo_box.combo_button
- visible ="false"/>
- <combo_box.drop_down_button
- visible ="false"/>
- </combo_box>
- <line_editor
- follows="left|top"
- width="200"
- height="32"
- left="262"
- max_length_chars="16"
- name="password_edit"
- label="Password"
- text_pad_left="8"
- font="SansSerifLarge"
- is_password="true"
- select_on_focus="true"
- commit_on_focus_lost="false"
- top="0" />
- <button
- follows="left|top"
- image_unselected="PushButton_Login"
- image_pressed="PushButton_Login_Pressed"
- image_hover_unselected="PushButton_Login_Over"
- label="Log In"
- label_color="White"
- font="SansSerifLarge"
- name="connect_btn"
- left_pad="15"
- width="120"
- height="32"
- top="0" />
- <text
- follows="left|top"
- font="SansSerifLarge"
- font.style="BOLD"
- text_color="EmphasisColor"
- height="34"
- name="sign_up_text"
- left_pad="10"
- top="0"
- width="200"
- valign="center">
- Sign up
- </text>
- <check_box
- follows="left|top"
- font="SansSerifLarge"
- left="42"
- top="32"
- height="24"
- label="Remember me"
- word_wrap="down"
- check_button.bottom="3"
- name="remember_name"
- tool_tip="Already remembered user can be forgotten from Me &gt; Preferences &gt; Advanced &gt; Remembered Usernames."
- width="198" />
- <check_box
- control_name="RememberPassword"
- follows="left|top"
- font="SansSerifLarge"
- height="24"
- left="262"
- bottom_delta="0"
- label="Remember password"
- word_wrap="down"
- check_button.bottom="3"
- name="remember_password"
- width="198" />
- <text
- follows="left|top"
- font="SansSerifLarge"
- text_color="EmphasisColor"
- height="16"
- name="forgot_password_text"
- left="492"
- top="34"
- width="200">
- Forgotten password
- </text>
- </layout_panel>
- <layout_panel
- height="100"
- name="widget_right"
- auto_resize="true"
- width="200" />
- </layout_stack>
- </layout_panel>
- <!-- end of widget stack -->
- <!-- start of images stack -->
- <layout_panel
- height="500"
- min_height="10"
- auto_resize="false"
- name="parent_panel3"
- width="1024">
- <layout_stack
- follows="left|right|top|bottom"
- height="500"
- left="0"
- name="images_stack"
- orientation="horizontal"
- top="0"
- width="1024">
- <layout_panel
- height="500"
- min_height="10"
- auto_resize="true"
- name="images_left"
- width="96" />
- <layout_panel
- auto_resize="false"
- follows="left|right|top"
- name="images_container"
- width="675"
- left="0"
- top="0"
- height="500">
- <icon
- height="450"
- width="675"
- image_name="first_login_image"
- left="0"
- name="image_left"
- top="0" />
- </layout_panel>
- <layout_panel
- height="100"
- name="images_right"
- auto_resize="true"
- width="96" />
- </layout_stack>
- </layout_panel>
- <!-- end of images stack -->
- <layout_panel
- height="400"
- min_height="10"
- auto_resize="true"
- name="page_bottom"
- width="1024" />
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index 6e1e6facbe..a302d44e83 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -34,7 +34,6 @@
left="12"
right="-12"
name="ItemcountText"
- font="SansSerifMedium"
text_color="InventoryItemLinkColor"
use_ellipses="true"
top_pad="0">
diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml
index 61cd6a83d4..371147b28a 100644
--- a/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml
+++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml
@@ -108,7 +108,6 @@
left="2"
width="306"
halign="center"
- font="SansSerifMedium"
font_shadow="hard"
valign="top">
Drop folders here to create new listings
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 95787c16c5..09bc098437 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -89,7 +89,7 @@
image_hover_unselected="PushButton_Over"
image_bottom_pad="1"
layout="topleft"
- left="10"
+ left="9"
name="back_btn"
tool_tip="Go back to previous location"
top="2"
@@ -102,7 +102,7 @@
image_hover_unselected="PushButton_Over"
image_bottom_pad="1"
layout="topleft"
- left_pad="0"
+ left_pad="1"
name="forward_btn"
tool_tip="Go forward one location"
top_delta="0"
@@ -196,8 +196,8 @@
text_color="LtGray"
tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
top="13"
- valign="bottom"
- width="290">
+ valign="bottom"
+ width="310">
Places you save to your favorites bar will appear here.
</label>
<!-- More button actually is a text box. -->
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index bfe738f472..eaf638d35f 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -49,7 +49,7 @@
embedded_items="false"
enabled="false"
follows="left|right|top|bottom"
- height="85"
+ height="85"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -67,16 +67,16 @@
<panel
background_visible="false"
follows="left|right|bottom"
- height="30"
+ height="30"
width="290"
label="control_panel"
layout="topleft"
left="10"
name="control_panel"
top_pad="5">
- <!--
+ <!--
Notes:
- This panel holds buttons of notification. Change of its size can affect the layout of buttons.
+ This panel holds buttons of notification. Change of its size can affect the layout of buttons.
-->
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml
index 80db209b59..c6e2c124d1 100644
--- a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml
@@ -63,7 +63,8 @@
use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box" visible="false">
Sender: "Resident R e s i d e n t R e s i d e n t"
</text>
- <text allow_scroll="false" font="SansSerifSmall" top="0" right="-5" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
+ <!-- Old DejaVu font is used to avoid overlapping with sender name -->
+ <text allow_scroll="false" font="DejaVu" font.size="LSmall" top="0" right="-5" width="100" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
name="notification_time" value="2014/12/24 23:30" />
</panel>
</panel>
@@ -105,7 +106,8 @@
use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box_exp" visible="false">
Sender: "Resident R e s i d e n t R e s i d e n t"
</text>
- <text allow_scroll="false" font="SansSerifSmall" top="0" right="-1" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
+ <!-- Old DejaVu font is used to avoid overlapping with sender name -->
+ <text allow_scroll="false" font="DejaVu" font.size="LSmall" top="0" right="-1" width="100" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
name="notification_time_exp" value="2014/12/24 23:30" />
</panel>
<panel border="false" left="0" height="115" width="230" bevel_style="none" follows="all" layout="topleft" name="notification_text_panel_exp" visible="true">
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index dc8ac425b6..352eb790a3 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -216,7 +216,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
<button
follows="left|bottom"
height="22"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
is_toggle="true"
@@ -251,7 +251,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
follows="bottom|right"
height="22"
image_overlay="Search_Icon"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
is_toggle="true"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 0766cc06ee..9657d80fc2 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -183,6 +183,7 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip
increment="1"
follows="left|top"
left="5"
+ top_pad="5"
min_val="0"
max_val="4096"
label="Range:"
@@ -199,13 +200,13 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip
<layout_stack
clip="false"
follows="all"
- height="410"
+ height="406"
layout="topleft"
left="0"
mouse_opaque="false"
orientation="vertical"
right="-1"
- top_pad="0">
+ top_pad="3">
<layout_panel
height="142"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml b/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml
index 9f930d1557..1bea605d91 100644
--- a/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml
+++ b/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml
@@ -144,7 +144,7 @@
<button
follows="top|left"
height="22"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
label="Auto-adjust now"
@@ -157,7 +157,7 @@
<button
follows="top|left"
height="22"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
label="Cancel"
@@ -183,7 +183,7 @@
follows="top|left"
height="20"
initial_value="true"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
is_toggle="true"
diff --git a/indra/newview/skins/default/xui/en/panel_performance_preferences.xml b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
index a412543251..07da9b4794 100644
--- a/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
+++ b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
@@ -91,7 +91,7 @@
layout="topleft"
left_pad="40"
name="fastest_lbl"
- width="40">
+ width="42">
Fastest
</text>
<radio_group
@@ -240,7 +240,7 @@
left_pad="10"
top_delta="1"
name="farther_lbl"
- width="40">
+ width="45">
Farther
</text>
<text
@@ -284,7 +284,7 @@
top_delta="0"
left="160"
name="enhancements_desc"
- width="350">
+ width="375">
Shadows significantly improve visual quality but can reduce speed.
</text>
<text
@@ -307,7 +307,8 @@
left_delta="150"
top_delta="0"
name="ShadowDetail"
- width="150">
+ width="153">
+ <combo_box.drop_down_button pad_right="20" />
<combo_box.item
label="None"
name="0"
@@ -417,7 +418,7 @@
top_delta="3"
left_pad="10"
name="photo_dist_det_desc"
- width="180">
+ width="192">
(Enter value between 0.0 and 4.0)
</text>
<text
@@ -426,7 +427,7 @@
height="18"
layout="topleft"
top="80"
- left="213"
+ left="215"
name="0_lbl"
width="7">
0
@@ -446,7 +447,7 @@
font="SansSerifSmall"
height="18"
layout="topleft"
- left_pad="30"
+ left_pad="29"
name="2_lbl"
width="7">
2
@@ -468,7 +469,7 @@
layout="topleft"
left_pad="30"
name="4_lbl"
- width="7">
+ width="8">
4
</text>
<text
@@ -476,7 +477,7 @@
font="SansSerifSmall"
height="18"
layout="topleft"
- left_pad="30"
+ left_pad="29"
name="5_lbl"
width="7">
5
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index b27b6dd73a..86ec799996 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -13,18 +13,6 @@
name="aspect_ratio_text">
[NUM]:[DEN]
</panel.string>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="12"
- layout="topleft"
- left="33"
- name="Cache:"
- top_pad="10"
- width="100">
- Cache:
- </text>
<spinner
control_name="CacheSize"
decimal_digits="0"
@@ -33,14 +21,14 @@
increment="64"
initial_value="1024"
label="Cache size (896 - 32768MB)"
- label_width="150"
+ label_width="170"
layout="topleft"
- left="80"
+ left="33"
max_val="32768"
min_val="896"
top_pad="10"
name="cachesizespinner"
- width="210" />
+ width="230" />
<text
type="string"
length="1"
@@ -59,7 +47,7 @@
label="Clear Cache"
label_selected="Clear Cache"
layout="topleft"
- left_pad="20"
+ left_pad="25"
name="clear_cache"
top_delta="0"
width="100">
@@ -72,7 +60,7 @@
follows="left|top"
height="10"
layout="topleft"
- left="80"
+ left="33"
name="Cache location"
top_pad="5"
width="300">
@@ -86,7 +74,7 @@
font="SansSerif"
height="23"
layout="topleft"
- left="80"
+ left="33"
max_length_bytes="4096"
name="cache_location"
top_pad="5"
@@ -113,7 +101,7 @@
left_pad="3"
name="default_cache_location"
top_delta="0"
- width="100">
+ width="104">
<button.commit_callback
function="Pref.ResetCache" />
</button>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
index df9f467fca..0ff4ef42ce 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
@@ -520,12 +520,21 @@
value="default"
width="75" />
<radio_item
- label="gold"
+ label="classic"
left_pad="0"
layout="topleft"
top_delta="0"
height="16"
name="radio2"
+ value="classic"
+ width="75" />
+ <radio_item
+ label="gold"
+ left_pad="0"
+ layout="topleft"
+ top_delta="0"
+ height="16"
+ name="radio3"
value="gold"
width="75" />
<radio_item
@@ -534,7 +543,7 @@
layout="topleft"
top_delta="0"
height="16"
- name="radio3"
+ name="radio4"
value="contrast"
width="75" />
<radio_item
@@ -543,7 +552,7 @@
layout="topleft"
top_delta="0"
height="16"
- name="radio2"
+ name="radio5"
value="contrast_gold"
width="75" />
<radio_group.commit_callback
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index ddddb4855f..6d1b952639 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -110,10 +110,11 @@
left="255"
max_chars="135"
name="time_format_combobox"
- width="70">
+ width="71">
+ <combo_box.drop_down_button pad_right="22" />
<combo_box.item
enabled="true"
- label="1:00 AM"
+ label="1:00 PM"
name="12H"
value="0" />
<combo_box.item
@@ -244,7 +245,7 @@
height="20"
layout="topleft"
left="35"
- top_pad="0"
+ top_pad="5"
name="Name_Tag_Preference">
<radio_item
label="Off"
@@ -295,16 +296,16 @@
tool_tip="Show username, like bobsmith123"
top_delta="0" />
<check_box
- control_name="NameTagShowGroupTitles"
- enabled_control="AvatarNameTagMode"
+ control_name="UseDisplayNames"
+ follows="top|left"
height="16"
- label="Group titles"
+ label="Display names"
layout="topleft"
left="35"
- width="100"
- name="show_all_title_checkbox1"
- tool_tip="Show group titles, like Officer or Member"
- top_pad="3" />
+ name="display_names_check"
+ width="100"
+ tool_tip="Check to use display names in chat, IM, name tags, etc."
+ top_pad="5"/>
<check_box
control_name="NameTagShowFriends"
enabled_control="AvatarNameTagMode"
@@ -313,19 +314,29 @@
layout="topleft"
left_pad="50"
name="show_friends"
- tool_tip="Highlight the name tags of your friends"/>
- <check_box
- control_name="UseDisplayNames"
- follows="top|left"
- height="16"
- label="View Display Names"
- layout="topleft"
- left="35"
- name="display_names_check"
- width="237"
- tool_tip="Check to use display names in chat, IM, name tags, etc."
- top_pad="3"/>
-
+ tool_tip="Highlight the name tags of your friends"/>
+ <combo_box
+ height="23"
+ layout="topleft"
+ control_name="GroupTitlesTagMode"
+ enabled_control="AvatarNameTagMode"
+ left="38"
+ top_pad="3"
+ name="group_title"
+ width="130">
+ <combo_box.item
+ label="No group tags"
+ name="no_tags"
+ value="0" />
+ <combo_box.item
+ label="Only my group tag"
+ name="my_tag"
+ value="1" />
+ <combo_box.item
+ label="All group tags"
+ name="all_tags"
+ value="2" />
+ </combo_box>
<text
type="string"
length="1"
@@ -334,7 +345,7 @@
layout="topleft"
left="30"
name="inworld_typing_rg_label"
- top_pad="1"
+ top_pad="5"
width="400">
Pressing letter keys:
</text>
@@ -343,7 +354,7 @@
height="34"
layout="topleft"
left="35"
- top_pad="0"
+ top_pad="5"
name="inworld_typing_preference">
<radio_item
label="Starts local chat"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index c78575cf82..9d55db27b8 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -104,7 +104,7 @@
layout="topleft"
left="65"
name="FasterText"
- top_pad="4"
+ top_pad="10"
width="80">
Faster
</text>
@@ -114,14 +114,14 @@
follows="left|top"
height="12"
layout="topleft"
- left_delta="360"
+ left_delta="363"
name="BetterText"
top_delta="0"
width="100">
Better
</text>
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -130,7 +130,7 @@
top_delta="-2"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -138,7 +138,7 @@
name="LowMidGraphicsDivet"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -147,7 +147,7 @@
top_delta="0"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -156,7 +156,7 @@
top_delta="0"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -165,7 +165,7 @@
top_delta="0"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -174,7 +174,7 @@
top_delta="0"
width="2" />
<icon
- color="DkGray"
+ color="DkGray0"
height="14"
image_name="Rounded_Square"
layout="topleft"
@@ -216,15 +216,15 @@
min_val="8"
max_val="512"
name="DrawDistance"
- top_delta="40"
- width="427" />
+ top_delta="34"
+ width="428" />
<text
type="string"
length="1"
follows="left|top"
height="12"
layout="topleft"
- left_delta="427"
+ left_delta="425"
name="DrawDistanceMeterText2"
top_delta="0"
width="128">
@@ -286,7 +286,7 @@
initial_value="101"
increment="1"
label="Avatar maximum complexity:"
- label_width="165"
+ label_width="187"
layout="topleft"
left="30"
min_val="1"
@@ -294,7 +294,7 @@
name="IndirectMaxComplexity"
show_text="false"
top_delta="28"
- width="300">
+ width="394">
<slider.commit_callback
function="Pref.UpdateIndirectMaxComplexity"
parameter="IndirectMaxComlexityText" />
@@ -306,7 +306,7 @@
height="16"
layout="topleft"
top_delta="0"
- left_delta="304"
+ left_delta="398"
text_readonly_color="LabelDisabledColor"
name="IndirectMaxComplexityText"
width="65">
@@ -329,7 +329,7 @@
label_width="240"
left="30"
top_delta="20"
- width="393">
+ width="394">
<slider.commit_callback
function="Pref.UpdateIndirectMaxNonImpostors"
parameter="IndirectNonImpostorsText" />
@@ -341,7 +341,7 @@
height="16"
layout="topleft"
top_delta="0"
- left_delta="397"
+ left_delta="398"
text_readonly_color="LabelDisabledColor"
name="IndirectMaxNonImpostorsText"
width="65">
@@ -369,7 +369,7 @@
increment="0.1"
initial_value="160"
label="Brightness (exposure)"
- label_width="145"
+ label_width="187"
layout="topleft"
left="30"
min_val="0.5"
@@ -377,7 +377,7 @@
name="RenderExposure"
show_text="true"
top_pad="14"
- width="260">
+ width="424">
</slider>
<!-- End of Basic Settings block -->
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
index eee55bd7bc..a0489b37b5 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
@@ -9,6 +9,25 @@
name="move_panel"
top="1"
width="517">
+
+ <tab_container
+ name="move_view_tab_container"
+ enabled="true"
+ top_pad="0"
+ follows="left|top|right|bottom"
+ width="517"
+ height="408"
+ left_delta="0"
+ tab_position="top"
+ tab_stop="false">
+
+ <!-- ── Move & View tab (existing content) ─────────────────────────── -->
+ <panel
+ label="Move &amp; View"
+ name="move_view_panel"
+ layout="topleft"
+ follows="top|left">
+
<icon
follows="left|top"
height="18"
@@ -300,16 +319,7 @@
layout="topleft"
left="83"
name="sound_on_collisions"
- top_pad="0"
- width="200" />
- <check_box
- control_name="DoubleClickZoomIn"
- height="20"
- label="Double click on nearby list to zoom in on avatar"
- layout="topleft"
- left="83"
- name="double_click_zoom_in"
- top_pad="0"
+ top_pad="10"
width="200" />
<button
height="23"
@@ -322,4 +332,198 @@
function="Floater.Show"
parameter="pref_joystick" />
</button>
+
+ </panel>
+
+ <panel
+ label="Clicking"
+ name="clicking_panel"
+ layout="topleft"
+ follows="top|left">
+ <check_box
+ control_name="DoubleClickZoomIn"
+ height="20"
+ label="Double click on nearby list to zoom in on avatar"
+ layout="topleft"
+ left="83"
+ name="double_click_zoom_in"
+ top_pad="10"
+ width="200" />
+ <check_box
+ control_name="PreventClickToSit"
+ height="20"
+ label="Prevent sitting on a chair on a click"
+ layout="topleft"
+ left="83"
+ name="prevent_click_to_sit"
+ top_pad="10"
+ width="200" />
+ </panel>
+
+ <panel
+ label="Jumping"
+ name="jumping_panel"
+ layout="topleft"
+ follows="top|left">
+ <check_box
+ control_name="DisablePreJumpLand"
+ height="20"
+ label="Disable pre-jump and jump animations"
+ layout="topleft"
+ left="83"
+ name="disable_pre_jump_land"
+ top_pad="10"
+ width="200" />
+ </panel>
+
+ <!-- ── Over-The-Shoulder tab ──────────────────────────────────────── -->
+ <panel
+ label="Over-The-Shoulder"
+ name="ots_panel"
+ layout="topleft"
+ follows="top|left">
+
+ <text
+ type="string"
+ follows="left|top"
+ font="SansSerifSmallBold"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="ots_enable_header"
+ top="10"
+ width="490">
+ Over-the-Shoulder Camera
+ </text>
+
+ <check_box
+ control_name="OTSEnabled"
+ follows="left|top"
+ height="20"
+ label="Use Over-The-Shoulder Cam"
+ layout="topleft"
+ left="15"
+ name="ots_enabled_pref"
+ top_pad="5"
+ tool_tip="When checked, pressing M enters over-the-shoulder cam instead of first-person mouselook"
+ width="350" />
+
+ <text
+ type="string"
+ follows="left|top"
+ font="SansSerifSmallBold"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="ots_pos_header"
+ top_pad="12"
+ width="490">
+ Camera Position
+ </text>
+
+ <text type="string" follows="left|top" height="16" layout="topleft"
+ left="15" top_pad="6" width="130" name="dist_label">Distance:</text>
+ <slider
+ control_name="OTSCameraDistance"
+ decimal_digits="1" can_edit_text="true"
+ follows="left|right|top" height="16"
+ increment="0.1" initial_value="3.0" max_val="10.0" min_val="1.0"
+ label_width="0" layout="topleft" left="150" right="-10" top_delta="-2"
+ name="ots_distance"
+ tool_tip="Camera distance behind avatar (1 – 10 m)" />
+
+ <text type="string" follows="left|top" height="16" layout="topleft"
+ left="15" top_pad="6" width="130" name="side_label">Side offset:</text>
+ <slider
+ control_name="OTSCameraSide"
+ decimal_digits="2" can_edit_text="true"
+ follows="left|right|top" height="16"
+ increment="0.05" initial_value="-0.5" max_val="1.0" min_val="-1.0"
+ label_width="0" layout="topleft" left="150" right="-10" top_delta="-2"
+ name="ots_side"
+ tool_tip="Side offset: negative = right shoulder, positive = left shoulder" />
+
+ <text type="string" follows="left|top" height="16" layout="topleft"
+ left="15" top_pad="6" width="130" name="height_label">Height:</text>
+ <slider
+ control_name="OTSCameraHeight"
+ decimal_digits="2" can_edit_text="true"
+ follows="left|right|top" height="16"
+ increment="0.05" initial_value="0.5" max_val="2.0" min_val="0.0"
+ label_width="0" layout="topleft" left="150" right="-10" top_delta="-2"
+ name="ots_height"
+ tool_tip="Camera height above avatar root (0 – 2 m)" />
+
+ <text type="string" follows="left|top" height="16" layout="topleft"
+ left="15" top_pad="6" width="130" name="focus_label">Focus distance:</text>
+ <slider
+ control_name="OTSFocusDistance"
+ decimal_digits="1" can_edit_text="true"
+ follows="left|right|top" height="16"
+ increment="0.5" initial_value="10.0" max_val="30.0" min_val="2.0"
+ label_width="0" layout="topleft" left="150" right="-10" top_delta="-2"
+ name="ots_focus_dist"
+ tool_tip="Focus point distance along camera forward axis (2 – 30 m)" />
+
+ </panel>
+
+ <!-- ── Teleports tab ──────────────────────────────────────────────── -->
+ <panel
+ label="Teleports"
+ name="teleports_panel"
+ layout="topleft"
+ follows="top|left">
+
+ <text
+ type="string"
+ follows="left|top"
+ font="SansSerifSmallBold"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="teleport_header"
+ top="10"
+ width="490">
+ Teleport Options
+ </text>
+
+ <check_box
+ control_name="KeepCameraOnLocalTeleport"
+ follows="left|top"
+ height="20"
+ label="Keep camera position on local teleport"
+ layout="topleft"
+ left="15"
+ name="keep_camera_on_local_teleport"
+ top_pad="8"
+ tool_tip="When teleporting within the same region, do not reset the camera position or mode (stays in mouselook/over-the-shoulder)"
+ width="450" />
+
+ <check_box
+ control_name="DisableTeleportScreens"
+ follows="left|top"
+ height="20"
+ label="Disable teleport progress screen"
+ layout="topleft"
+ left="15"
+ name="disable_teleport_screens"
+ top_pad="6"
+ tool_tip="Do not show the fullscreen progress/black screen during teleports"
+ width="450" />
+
+ <check_box
+ control_name="BlockTeleportOffers"
+ follows="left|top"
+ height="20"
+ label="Block any teleport offer automatically from coming"
+ layout="topleft"
+ left="15"
+ name="block_teleport_offers"
+ top_pad="6"
+ width="450" />
+
+ </panel>
+
+ </tab_container>
+
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 258c49785e..2036ed75ca 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -170,7 +170,7 @@
left="30"
name="Software updates:"
mouse_opaque="false"
- top_pad="5"
+ top_pad="8"
width="300">
Software updates:
</text>
@@ -180,7 +180,7 @@
height="23"
layout="topleft"
left_delta="50"
- top_pad="5"
+ top_pad="10"
name="updater_service_combobox"
width="300">
<combo_box.item
@@ -197,29 +197,29 @@
value="0" />
</combo_box>
<check_box
- top_delta="4"
+ top_pad="10"
enabled="true"
follows="left|top"
+ layout="topleft"
height="14"
control_name="UpdaterWillingToTest"
label="Willing to update to Beta"
left_delta="0"
mouse_opaque="true"
name="update_willing_to_test"
- width="400"
- top_pad="5"/>
+ width="400"/>
<check_box
- top_delta="4"
+ top_pad="8"
enabled="true"
follows="left|top"
+ layout="topleft"
height="14"
control_name="UpdaterShowReleaseNotes"
label="Show Release Notes after update"
left_delta="0"
mouse_opaque="true"
name="update_show_release_notes"
- width="400"
- top_pad="5"/>
+ width="400"/>
<text
type="string"
length="1"
@@ -229,7 +229,7 @@
left="30"
name="Proxy Settings:"
mouse_opaque="false"
- top_pad="5"
+ top_pad="8"
width="300">
Proxy Settings:
</text>
@@ -242,8 +242,7 @@
layout="topleft"
left_delta="50"
name="set_proxy"
- top_pad="5"
- >
+ top_pad="10" >
<button.commit_callback
function="Pref.Proxy" />
</button>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 52413abe74..1dcbf4e666 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -319,7 +319,7 @@
top_delta="25"
name="Listen media from"
height="15"
- width="165"
+ width="180"
halign="right">
Hear media and sounds from
</text>
@@ -327,7 +327,7 @@
control_name="MediaSoundsEarLocation"
follows="left|top"
layout="topleft"
- left_pad="5"
+ left_pad="10"
width="130"
height="23"
top_delta="-4"
@@ -346,7 +346,7 @@
layout="topleft"
height="15"
left="23"
- width="165"
+ width="180"
name="media_autoplay_label"
halign="right">
Auto-play media
@@ -357,7 +357,7 @@
follows="left|top"
layout="topleft"
height="23"
- left_delta="170"
+ left_delta="190"
top_delta="-4"
name="media_auto_play_combo"
width="130">
@@ -379,7 +379,7 @@
layout="topleft"
height="15"
left="23"
- width="165"
+ width="180"
name="media_firstinteract_label"
halign="right">
Media first-interact
@@ -390,11 +390,12 @@
follows="left|top"
layout="topleft"
height="23"
- left_delta="170"
+ left_delta="190"
top_delta="-4"
width="130"
name="media_first_interact_combo"
tool_tip="This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. Each option also inherits the previous ones.">
+ <combo_box.drop_down_button pad_right="19" />
<item
label="Disabled"
name="media_first_click_none"
@@ -457,7 +458,7 @@
layout="topleft"
follows="left"
height="15"
- width="165"
+ width="187"
name="noise_suppression_label"
left="23"
top_delta="22"
@@ -469,7 +470,7 @@
enabled_control="EnableVoiceChat"
follows="left|top"
layout="topleft"
- left_delta="170"
+ left_delta="190"
top_delta="-6"
width="130"
height="23"
@@ -503,7 +504,7 @@
left="23"
top_delta="30"
name="Listen from"
- width="165"
+ width="180"
height="15"
halign="right">
Hear voice from
@@ -513,7 +514,7 @@
control_name="VoiceEarLocation"
follows="left|top"
layout="topleft"
- left_delta="170"
+ left_delta="190"
top_delta="-6"
width="130"
height="23"
@@ -545,7 +546,7 @@
tool_tip="Check to enable voice echo cancellation"
label="Echo Cancellation"
layout="topleft"
- left="260"
+ left="275"
name="enable_echo_cancellation"
top_pad="-15"
width="200"/>
@@ -558,7 +559,7 @@
layout="topleft"
left="20"
name="push_to_talk_toggle_check"
- width="237"
+ width="245"
tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
top_pad="5"/>
<check_box
@@ -569,7 +570,7 @@
label="Automatic Gain Control"
layout="topleft"
name="voice_automatic_gain_control"
- left="260"
+ left="275"
top_pad="-15"
width="200"/>
<check_box
@@ -591,7 +592,7 @@
label="Show voice dot above avatars"
layout="topleft"
name="voice_dot_visualizer"
- left="260"
+ left="275"
top_pad="-15"
width="200"/>
<button
@@ -603,7 +604,7 @@
label="Voice Input/Output devices"
layout="topleft"
left="20"
- top_pad="0"
+ top_pad="1"
name="device_settings_btn"
width="200">
</button>
diff --git a/indra/newview/skins/default/xui/en/panel_region_experiences.xml b/indra/newview/skins/default/xui/en/panel_region_experiences.xml
index 199dca4853..5e9ebabba7 100644
--- a/indra/newview/skins/default/xui/en/panel_region_experiences.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_experiences.xml
@@ -13,7 +13,6 @@
<panel.string
name="trusted_estate_text">
Any Experience may be Key.
-
Key Experiences have permission to run on this estate.
Additionally, if the estate does not allow public access, Residents participating in any Key Experience may enter the estate and can remain as long as they are in a Key Experience.
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index 6ef1b6e44a..4e624276cc 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -33,6 +33,28 @@
unknown
</text>
<text
+ follows="right|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ top_delta="0"
+ right="-100"
+ name="estate_id_lbl"
+ width="80">
+ Estate ID:
+ </text>
+ <line_editor
+ follows="right|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ top_delta="0"
+ name="estate_id"
+ enabled="false"
+ right="-10"
+ initial_value="unknown"
+ width="85" />
+ <text
follows="left|top"
font="SansSerif"
height="20"
@@ -45,16 +67,49 @@
</text>
<text
follows="left|top"
- font="SansSerif"
+ font="SansSerifSmall"
height="20"
layout="topleft"
- left_delta="50"
+ left_delta="53"
name="version_channel_text"
- top_delta="0"
+ top_delta="1"
width="400">
unknown
</text>
<text
+ follows="right|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ top_delta="-1"
+ right="-100"
+ name="grid_position_lbl"
+ width="80">
+ Grid Position:
+ </text>
+ <line_editor
+ follows="right|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ right="-55"
+ name="grid_position_x"
+ enabled="false"
+ top_delta="0"
+ default_text="n/a"
+ width="40" />
+ <line_editor
+ follows="right|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ right="-10"
+ name="grid_position_y"
+ enabled="false"
+ top_delta="0"
+ default_text="n/a"
+ width="40" />
+ <text
follows="left|top"
font="SansSerif"
height="20"
diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
index 73e0a1000f..dd9907dc1f 100644
--- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
@@ -42,7 +42,7 @@
max_val="100"
name="water_height_spin"
top="40"
- width="180" />
+ width="190" />
<spinner
follows="left|top"
height="20"
@@ -54,7 +54,7 @@
max_val="100"
name="terrain_raise_spin"
top="40"
- width="180" />
+ width="190" />
<spinner
follows="left|top"
height="20"
@@ -67,7 +67,7 @@
min_val="-100"
name="terrain_lower_spin"
top="60"
- width="180" />
+ width="190" />
<view_border
bevel_style="none"
follows="top|left"
@@ -330,7 +330,7 @@
follows="left|top"
height="20"
layout="topleft"
- left_pad="10"
+ left_pad="15"
name="height_text_lbl7"
top_delta="0"
width="100">
@@ -349,7 +349,7 @@
min_val="-500"
name="height_start_spin_1"
top_delta="15"
- width="100" />
+ width="105" />
<!-- northeast low-->
<spinner
follows="left|top"
@@ -363,7 +363,7 @@
min_val="-500"
name="height_start_spin_3"
top_delta="0"
- width="100" />
+ width="105" />
<!-- northwest high-->
<spinner
follows="left|top"
@@ -377,7 +377,7 @@
min_val="-500"
name="height_range_spin_1"
top_delta="20"
- width="100" />
+ width="105" />
<!-- northeast high-->
<spinner
follows="left|top"
@@ -391,7 +391,7 @@
min_val="-500"
name="height_range_spin_3"
top_delta="0"
- width="100" />
+ width="105" />
<text
follows="left|top"
height="20"
@@ -406,7 +406,7 @@
follows="left|top"
height="20"
layout="topleft"
- left_pad="10"
+ left_pad="15"
name="height_text_lbl9"
top_delta="0"
width="100">
@@ -425,7 +425,7 @@
min_val="-500"
name="height_start_spin_0"
top_delta="15"
- width="100" />
+ width="105" />
<!-- southeast low-->
<spinner
follows="left|top"
@@ -439,7 +439,7 @@
min_val="-500"
name="height_start_spin_2"
top_delta="0"
- width="100" />
+ width="105" />
<!--southwest high-->
<spinner
follows="left|top"
@@ -453,7 +453,7 @@
min_val="-500"
name="height_range_spin_0"
top_delta="20"
- width="100" />
+ width="105" />
<!-- southeast high-->
<spinner
follows="left|top"
@@ -467,7 +467,7 @@
min_val="-500"
name="height_range_spin_2"
top_delta="0"
- width="100" />
+ width="105" />
<!-- Terrain Download/Upload/Bake buttons -->
<button
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml
index 1b1e31165a..9045e6a8ae 100644
--- a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml
@@ -6,7 +6,7 @@
bg_alpha_color="PanelNotificationBackground"
bg_opaque_color="PanelNotificationBackground"
chrome="true"
- height="270"
+ height="220"
label="script_question_panel"
layout="topleft"
left="0"
@@ -39,9 +39,9 @@
width="285">
</panel>
<text
- follows="all"
+ follows="left|right|top"
font="SansSerifBold"
- height="55"
+ height="15"
layout="topleft"
mouse_opaque="false"
name="bottom_info_message"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
index a29cdb5b41..c03d6a9745 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -35,7 +35,7 @@
layout="topleft"
left_delta="15"
top_pad="15"
- width="80">
+ width="86">
Ambient Color:
</text>
<color_swatch
@@ -53,9 +53,9 @@
follows="left"
height="10"
layout="topleft"
- left_delta="90"
+ left_delta="110"
top_delta="-15"
- width="80">
+ width="86">
Blue Horizon:
</text>
<color_swatch
@@ -73,9 +73,9 @@
follows="left"
height="10"
layout="topleft"
- left_delta="90"
+ left_delta="110"
top_delta="-15"
- width="80">
+ width="86">
Blue Density:
</text>
<color_swatch
@@ -166,7 +166,7 @@
layout="topleft"
left_delta="-5"
top_delta="25"
- width="80">
+ width="90">
Moisture Level:
</text>
<slider
@@ -190,7 +190,7 @@
layout="topleft"
left_delta="-5"
top_delta="25"
- width="80">
+ width="90">
Droplet Radius:
</text>
<slider
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index c58cf97f3e..6045c58e21 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -91,7 +91,7 @@
left="0"
name="balance"
tool_tip="L$ [AMT]&#10;Click to refresh your L$ balance.&#10;Double-click to display or hide your L$ balance."
- v_pad="4"
+ v_pad="2"
top="0"
wrap="false"
value="L$??"
@@ -102,7 +102,7 @@
follows="right|top|bottom"
image_hover_unselected="PushButton_Over"
image_unselected="PushButton_Off"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
height="18"
label="Buy L$"
label_color="White"
@@ -122,7 +122,7 @@
image_overlay_alignment="left"
image_hover_unselected="PushButton_Over"
image_unselected="PushButton_Off"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
height="18"
label="Shop"
label_color="White"
@@ -140,7 +140,7 @@
follows="right|top"
halign="right"
height="16"
- top="5"
+ top="3"
layout="topleft"
left_pad="0"
name="TimeText"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index 1c70383bf9..5ff02de6f6 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -51,7 +51,9 @@
name="color label"
text_readonly_color="LabelDisabledColor"
top="6"
- width="64">
+ width="64"
+ font="DejaVu"
+ font.size="LSmall" >
Color
</text>
<!-- label is blank because control places it below the box -->
@@ -77,7 +79,9 @@
name="color trans"
text_readonly_color="LabelDisabledColor"
top="6"
- width="110">
+ width="110"
+ font="DejaVu"
+ font.size="LSmall" >
Transparency %
</text>
<spinner
@@ -91,7 +95,9 @@
max_val="100"
name="ColorTrans"
top_pad="4"
- width="80" />
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -102,7 +108,9 @@
name="glow label"
text_readonly_color="LabelDisabledColor"
top="6"
- width="80">
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" >
Glow
</text>
<spinner
@@ -114,7 +122,9 @@
left_delta="0"
name="glow"
top_pad="4"
- width="77" />
+ width="77"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Full Bright"
@@ -122,7 +132,9 @@
left="7"
name="checkbox fullbright"
top_pad="4"
- width="81" />
+ width="81"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
height="19"
label="Hide water"
@@ -130,7 +142,9 @@
left="172"
top_delta="0"
name="checkbox_hide_water"
- width="81" />
+ width="81"
+ font="DejaVu"
+ font.size="LSmall" />
<view_border
bevel_style="none"
follows="top|left"
@@ -139,7 +153,9 @@
left="8"
name="object_horizontal"
top_pad="4"
- width="278" />
+ width="278"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -149,7 +165,9 @@
left="12"
top_pad="12"
name="label_matmedia"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" >
Material
</text>
<combo_box
@@ -158,7 +176,9 @@
left="10"
name="combobox matmedia"
top_pad="5"
- width="90">
+ width="90"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Textures"
name="Materials"
@@ -179,7 +199,9 @@
top_delta="-20"
width="150"
visible = "false"
- name="radio_material_type">
+ name="radio_material_type"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
label="Texture (diffuse)"
name="Texture (diffuse)"
@@ -209,7 +231,9 @@
top_delta="0"
width="150"
visible = "false"
- name="radio_pbr_type">
+ name="radio_pbr_type"
+ font="DejaVu"
+ font.size="LSmall" >
<radio_item
label="Complete material"
name="Complete material"
@@ -270,7 +294,9 @@
name="checkbox_sync_settings"
tool_tip="Adjust all maps repeats simultaneously"
top_pad="19"
- width="160" />
+ width="160"
+ font="DejaVu"
+ font.size="LSmall" />
<texture_picker
can_apply_immediately="true"
allow_no_texture="true"
@@ -282,7 +308,9 @@
name="pbr_control"
tool_tip="Click to choose a pbr material"
top_pad="5"
- width="64" />
+ width="64"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<button
follows="left|top"
height="23"
@@ -291,7 +319,9 @@
top_delta="0"
name="pbr_from_inventory"
label="Choose from inventory"
- width="140"/>
+ width="140"
+ font="DejaVu"
+ font.size="LSmall" />
<text
visible="false"
type="string"
@@ -303,7 +333,9 @@
left_delta="0"
name="material_permissions_loading_label"
text_readonly_color="LabelDisabledColor"
- width="160">
+ width="160"
+ font="DejaVu"
+ font.size="LSmall" >
Loading contents...
</text>
<button
@@ -314,7 +346,9 @@
top_delta="0"
name="edit_selected_pbr"
label="Edit Selected"
- width="140"/>
+ width="140"
+ font="DejaVu"
+ font.size="LSmall" />
<button
follows="left|top"
height="23"
@@ -323,7 +357,9 @@
top_pad="4"
name="save_selected_pbr"
label="Save to inventory"
- width="140"/>
+ width="140"
+ font="DejaVu"
+ font.size="LSmall" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
@@ -336,7 +372,9 @@
name="texture control"
tool_tip="Click to choose a picture"
top_delta="-54"
- width="64" />
+ width="64"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<text
type="string"
length="1"
@@ -347,7 +385,9 @@
name="label alphamode"
text_readonly_color="LabelDisabledColor"
top_delta="0"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" >
Alpha mode
</text>
<combo_box
@@ -356,7 +396,9 @@
left_delta="0"
name="combobox alphamode"
top_pad="4"
- width="120">
+ width="120"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall">
<combo_box.item
label="None"
name="None"
@@ -384,7 +426,9 @@
name="label maskcutoff"
text_readonly_color="LabelDisabledColor"
top_pad="4"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" >
Mask cutoff
</text>
<spinner
@@ -399,7 +443,9 @@
left_delta="0"
increment="1"
name="maskcutoff"
- width="80" />
+ width="80"
+ font="DejaVu"
+ font.size="LSmall" />
<texture_picker
allow_no_texture="true"
can_apply_immediately="true"
@@ -413,7 +459,9 @@
name="bumpytexture control"
tool_tip="Click to choose a picture"
top_delta="-55"
- width="64" />
+ width="64"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<text
type="string"
length="1"
@@ -424,7 +472,9 @@
name="label bumpiness"
text_readonly_color="LabelDisabledColor"
top_delta="0"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" >
Bumpiness
</text>
<combo_box
@@ -433,7 +483,9 @@
left_delta="0"
name="combobox bumpiness"
top_pad="4"
- width="90">
+ width="90"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="None"
name="None"
@@ -527,7 +579,9 @@
name="shinytexture control"
tool_tip="Click to choose a picture"
top_delta="-14"
- width="64" />
+ width="64"
+ caption_text.font="DejaVu"
+ caption_text.font.size="LSmall" />
<text
type="string"
length="1"
@@ -538,7 +592,9 @@
left_pad="10"
text_readonly_color="LabelDisabledColor"
top_delta="4"
- width="90">
+ width="90"
+ font="DejaVu"
+ font.size="LSmall" >
Shininess
</text>
<combo_box
@@ -547,7 +603,9 @@
left_pad="10"
name="combobox shininess"
top_delta="-6"
- width="90">
+ width="90"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="None"
name="None"
@@ -582,7 +640,9 @@
name="label glossiness"
text_readonly_color="LabelDisabledColor"
top_pad="7"
- width="116">
+ width="116"
+ font="DejaVu"
+ font.size="LSmall" >
Glossiness
</text>
<spinner
@@ -597,7 +657,9 @@
top_delta="-4"
left_pad="10"
name="glossiness"
- width="64" />
+ width="64"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -608,7 +670,9 @@
name="label environment"
text_readonly_color="LabelDisabledColor"
top_pad="8"
- width="116">
+ width="116"
+ font="DejaVu"
+ font.size="LSmall" >
Environment
</text>
<spinner
@@ -623,7 +687,9 @@
top_delta="-4"
left_pad="10"
name="environment"
- width="64" />
+ width="64"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -634,7 +700,9 @@
name="label shinycolor"
text_readonly_color="LabelDisabledColor"
top_pad="8"
- width="116">
+ width="116"
+ font="DejaVu"
+ font.size="LSmall" >
Color
</text>
<!-- label is blank because control places it below the box -->
@@ -658,7 +726,9 @@
use_ellipses="true"
read_only="true"
name="media_info"
- width="280">
+ width="280"
+ font="DejaVu"
+ font.size="LSmall" >
URL of chosen media, if any, goes here
</text>
<button
@@ -670,7 +740,9 @@
top_pad="4"
tool_tip="Add Media"
label="Choose..."
- width="85"/>
+ width="85"
+ font="DejaVu"
+ font.size="LSmall" />
<button
follows="top|left"
height="18"
@@ -680,7 +752,9 @@
tool_tip="Delete this media texture"
top_delta="0"
label="Remove"
- width="85"/>
+ width="85"
+ font="DejaVu"
+ font.size="LSmall" />
<button
follows="left|top"
height="18"
@@ -691,7 +765,9 @@
name="button align"
top_delta="0"
tool_tip="Align media texture (must load first)"
- width="85" />
+ width="85"
+ font="DejaVu"
+ font.size="LSmall" />
<text
type="string"
length="1"
@@ -702,7 +778,9 @@
name="tex gen"
text_readonly_color="LabelDisabledColor"
top_pad="46"
- width="140">
+ width="140"
+ font="DejaVu"
+ font.size="LSmall" >
Mapping
</text>
<combo_box
@@ -711,7 +789,9 @@
left_pad="0"
name="combobox texgen"
top_pad="-13"
- width="125">
+ width="125"
+ drop_down_button.font="DejaVu"
+ drop_down_button.font.size="LSmall" >
<combo_box.item
label="Default"
name="Default"
@@ -733,7 +813,9 @@
max_val="10000"
name="TexScaleU"
top_pad="5"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -745,7 +827,9 @@
min_val="-10000"
max_val="10000"
name="TexScaleV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="1"
follows="left|top"
@@ -758,7 +842,9 @@
max_val="100"
min_val="-100"
name="rptctrl"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -772,7 +858,9 @@
max_val="360"
min_val="-360"
name="TexRot"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -784,7 +872,9 @@
min_val="-1"
max_val="1"
name="TexOffsetU"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -796,7 +886,9 @@
min_val="-1"
max_val="1"
name="TexOffsetV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -809,7 +901,9 @@
max_val="10000"
name="bumpyScaleU"
top_delta="-115"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -821,7 +915,9 @@
min_val="-10000"
max_val="10000"
name="bumpyScaleV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -836,7 +932,9 @@
max_val="360"
min_val="-360"
name="bumpyRot"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -848,7 +946,9 @@
min_val="-1"
max_val="1"
name="bumpyOffsetU"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -860,7 +960,9 @@
min_val="-1"
max_val="1"
name="bumpyOffsetV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -873,7 +975,9 @@
max_val="10000"
name="shinyScaleU"
top_delta="-115"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -885,7 +989,9 @@
min_val="-10000"
max_val="10000"
name="shinyScaleV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="2"
follows="left|top"
@@ -900,7 +1006,9 @@
max_val="360"
min_val="-360"
name="shinyRot"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -912,7 +1020,9 @@
min_val="-1"
max_val="1"
name="shinyOffsetU"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -924,7 +1034,9 @@
min_val="-1"
max_val="1"
name="shinyOffsetV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<check_box
follows="top|left"
height="16"
@@ -935,7 +1047,9 @@
name="checkbox planar align"
tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping."
top_delta="20"
- width="260" />
+ width="260"
+ font="DejaVu"
+ font.size="LSmall" />
<button
follows="left|top"
layout="topleft"
@@ -946,7 +1060,9 @@
label_selected="Align current texture layers"
name="button align textures"
tool_tip="Align current texture layers"
- width="66" />
+ width="66"
+ font="DejaVu"
+ font.size="LSmall" />
<web_browser
visible="false"
enabled="false"
@@ -972,7 +1088,9 @@
max_val="10000"
name="gltfTextureScaleU"
top_delta="34"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -984,7 +1102,9 @@
min_val="-10000"
max_val="10000"
name="gltfTextureScaleV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
decimal_digits="1"
follows="left|top"
@@ -997,7 +1117,9 @@
max_val="100"
min_val="-100"
name="gltfRptctrl"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1009,7 +1131,9 @@
min_val="-360"
max_val="360"
name="gltfTextureRotation"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1021,7 +1145,9 @@
min_val="-999"
max_val="999"
name="gltfTextureOffsetU"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<spinner
follows="left|top"
height="19"
@@ -1033,6 +1159,8 @@
min_val="-999"
max_val="999"
name="gltfTextureOffsetV"
- width="265" />
+ width="265"
+ font="DejaVu"
+ font.size="LSmall" />
<!-- END PBR Material texture transform parameters -->
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_voice_effect.xml b/indra/newview/skins/default/xui/en/panel_voice_effect.xml
deleted file mode 100644
index 42cd510efd..0000000000
--- a/indra/newview/skins/default/xui/en/panel_voice_effect.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel
- follows="all"
- height="26"
- layout="topleft"
- name="panel_voice_effect"
- width="200">
- <string name="no_voice_effect">
- Voice Morphing Off
- </string>
- <string name="preview_voice_effects">
- Preview Voice Morphing ▶
- </string>
- <string name="get_voice_effects">
- Get Voice Morphing ▶
- </string>
- <combo_box
- enabled="false"
- follows="left|top|right"
- height="23"
- name="voice_effect"
- tool_tip="Select a Voice Morph to change your voice"
- top_pad="0"
- width="200">
- <combo_box.item
- label="Voice Morphing Off"
- name="no_voice_effect"
- top_pad="0"
- value="0" />
- <combo_box.commit_callback
- function="Voice.CommitVoiceEffect" />
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index 3e9efb6f8b..c067c86ba7 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -29,7 +29,7 @@ width="333">
background_visible="false"
bg_opaque_color="DkGray2"
left="10"
- top="5"
+ top="0"
follows="left|top|right"
layout="topleft"
width="307"
@@ -50,25 +50,15 @@ width="333">
layout="topleft"
name="openoutfit_btn"
visible="false" />
- <icon
- follows="top|left"
- height="31"
- image_name="Shirt_Large"
- name="outfit_icon"
- mouse_opaque="false"
- visible="true"
- left="1"
- top="0"
- width="31" />
<text
- font="SansSerifSmall"
+ font="SansSerifSmallBold"
text_color="EmphasisColor"
width="300"
height="13"
follows="top|left|right"
layout="topleft"
- left="35"
- top="3"
+ left="5"
+ top="0"
mouse_opaque="false"
name="currentlook_status" >
(Status)
@@ -76,7 +66,7 @@ width="333">
<text
font="SansSerifLargeBold"
height="20"
- left="35"
+ left="5"
parse_urls="false"
text_color="White"
top="15"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index de47e05291..3fc22d69ca 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -69,7 +69,6 @@
<button
control_name="InventoryInboxToggleState"
label="Received items"
- font="SansSerifMedium"
name="inbox_btn"
height="35"
image_unselected="MarketplaceBtn_Off"
@@ -92,7 +91,6 @@
top="10"
right="-20"
name="inbox_fresh_new_count"
- font="SansSerifMedium"
halign="right"
top_pad="0">
[NUM] new
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b4b4ac4a86..b442024361 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -117,6 +117,8 @@ Voice Server Version: [VOICE_VERSION]
<string name="AgniGridLabel">Second Life Main Grid (Agni)</string>
<string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string>
+ <string name="AgniGridLabelShort">Agni (production)</string>
+ <string name="AditiGridLabelShort">Aditi (beta)</string>
<string name="ViewerDownloadURL">http://secondlife.com/download</string>
<string name="LoginFailedViewerNotPermitted">
@@ -519,6 +521,8 @@ http://secondlife.com/support for help fixing this problem.
<string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string>
<string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string>
<string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string>
+ <string name="ScriptTakeMoneyCaution">The object &apos;&lt;nolink&gt;[OBJECTNAME]&lt;/nolink&gt;&apos; wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings.</string>
+ <string name="PrivilegedLandAccessCaution">The object &apos;&lt;nolink&gt;[OBJECTNAME]&lt;/nolink&gt;&apos; wants privileged access to your land. If you allow access it may sell your land with no additional warnings.</string>
<string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string>
<string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string>
<string name="ActOnControlInputs">Act on your control inputs</string>
@@ -536,6 +540,7 @@ http://secondlife.com/support for help fixing this problem.
<string name="ChangeYourDefaultAnimations">Change your default animations</string>
<string name="ForceSitAvatar">Force your avatar to sit</string>
<string name="ChangeEnvSettings">Change your environment settings</string>
+ <string name="PrivilegedLandAccess">Sell land on your behalf.</string>
<string name="NotConnected">Not Connected</string>
<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
@@ -2331,6 +2336,7 @@ For AI Character: Get the closest navigable point to the point provided.
<string name="InventorySingleFolderEmpty">Folder is empty.</string>
<string name="InventorySingleFolderNoMatches">No matches.</string>
<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
+ <string name="InventoryNoMaterial">You do not have a copy of this material in your inventory</string>
<string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>
<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3</string>
@@ -3005,6 +3011,9 @@ If this message persists, restart your computer.
[APP_NAME] appears to have frozen or crashed on the previous run.
Would you like to send a crash report?
</string>
+ <string name="MBFreezeDetected">
+ [APP_NAME] appears to have frozen. If this issue occurs regularly, please contact support at https://support.secondlife.com.
+ </string>
<string name="MBAlert">Notification</string>
<string name="MBNoDirectX">
[APP_NAME] is unable to detect DirectX 9.0b or greater.
@@ -4211,6 +4220,7 @@ name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_Picks_Label">Picks</string>
<string name="Command_Places_Label">Places</string>
<string name="Command_Preferences_Label">Preferences</string>
+ <string name="Command_QuickPrefs_Label">Quick Prefs</string>
<string name="Command_Profile_Label">Profile</string>
<string name="Command_Report_Abuse_Label">Report Abuse</string>
<string name="Command_Search_Label">Search</string>
@@ -4246,6 +4256,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
<string name="Command_Places_Tooltip">Places you've saved</string>
<string name="Command_Preferences_Tooltip">Preferences</string>
+ <string name="Command_QuickPrefs_Tooltip">Quickly adjust hover height and bandwidth</string>
<string name="Command_Profile_Tooltip">Edit or view your profile</string>
<string name="Command_Report_Abuse_Tooltip">Report Abuse</string>
<string name="Command_Search_Tooltip">Find places, events, people</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index 090447a6a2..c7669e81af 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -11,7 +11,7 @@
image_top_pad="0"
image_bottom_pad="0"
imgoverlay_label_space="1"
- label_color="ButtonLabelColor"
+ label_color="White"
label_color_selected="ButtonLabelSelectedColor"
label_color_disabled="ButtonLabelDisabledColor"
label_color_disabled_selected="ButtonLabelSelectedDisabledColor"
@@ -21,9 +21,10 @@
font="SansSerifSmall"
hover_glow_amount="0.15"
halign="center"
- pad_bottom="1"
+ pad_bottom="2"
height="23"
scale_image="true"
+ label_shadow="false"
handle_right_mouse="true"
use_draw_context_alpha="true"
held_down_delay.seconds="0.5"
diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
index cf995e5833..ebe2fa07e2 100644
--- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
+++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
@@ -9,7 +9,7 @@
left_pad="0"
icon_pad="10"
icon_width="20"
- text_pad="7"
+ text_pad="5"
text_pad_right="4"
arrow_size="12"
max_folder_item_overlap="2"
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index 604f62b099..3a0f43de3d 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -7,10 +7,10 @@
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
highlight_text_field="true"
- background_image="TextField_Search_Off"
- background_image_disabled="TextField_Search_Disabled"
- background_image_focused="TextField_Search_Active"
- background_image_highlight="TextField_Search_Highlight">
+ background_image="TextField_Off"
+ background_image_disabled="TextField_Disabled"
+ background_image_focused="TextField_Active"
+ background_image_highlight="TextField_Highlight">
<search_button label=""
top_pad="4"
left_pad="4"
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
index 11758556d6..73c6dc5d7a 100644
--- a/indra/newview/skins/default/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -9,7 +9,9 @@
bg_alpha_image="Window_Background"
background_visible="true"
background_opaque="false"
+ header_font="SansSerif"
header_height="25"
+ header_vpad="5"
close_image="Icon_Close_Foreground"
restore_image="Icon_Restore_Foreground"
minimize_image="Icon_Minimize_Foreground"
diff --git a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml
index 50c5285e04..671cb37ca3 100644
--- a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml
@@ -3,16 +3,21 @@
folder_arrow_image="Folder_Arrow"
favorite_image="Inv_Favorite_Star_Full"
favorite_content_image="Inv_Favorite_Star_Content"
- folder_indentation="8"
- item_height="20"
+ folder_indentation="10"
+ item_height="21"
item_top_pad="4"
selection_image="Rounded_Square"
mouse_opaque="true"
follows="left|top|right"
left_pad="5"
- icon_pad="2"
+ icon_pad="4"
icon_width="16"
- text_pad="1"
+ text_pad="5"
text_pad_right="4"
+ text_pad_top="0"
arrow_size="12"
max_folder_item_overlap="2"/>
+
+<!-- Potential properties not included above:
+ arrow_pad_top
+-->
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml
index 14cd3e159c..499152f060 100644
--- a/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml
@@ -10,7 +10,7 @@
mouse_opaque="false"
scale_image="true"
image_selected="PushButton_Selected_Press"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_unselected="PushButton_Off"
image_disabled="PushButton_Disabled"
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
index 865c145022..41ef9d2b8a 100644
--- a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
@@ -6,7 +6,7 @@
folder_indentation="8"
item_height="20"
item_top_pad="4"
- selection_image="Rounded_Square"
+ selection_image="Square_Selection"
left_pad="5"
icon_pad="2"
icon_width="16"
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_item.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_item.xml
index 09cbb1d3ab..ad4249da4e 100644
--- a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_item.xml
@@ -2,7 +2,7 @@
<inbox_folder_view_item
item_height="20"
item_top_pad="4"
- selection_image="Rounded_Square"
+ selection_image="Square_Selection"
>
<new_badge
label="New"
diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml b/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
index ce36a39a21..b00b8a241b 100644
--- a/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
@@ -17,7 +17,7 @@
<worn_style
font="SansSerifSmall"
font.style="BOLD"
- color="EmphasisColor" />
+ color="WornOutfitTextColor" />
<item_icon
height="16"
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
index ae642e1da5..cf6dc0a8c0 100644
--- a/indra/newview/skins/default/xui/en/widgets/line_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
@@ -11,7 +11,7 @@
text_pad_left="2"
text_readonly_color="TextFgReadOnlyColor"
text_tentative_color="TextFgTentativeColor"
- highlight_color="EmphasisColor"
+ highlight_color="SelectionColor"
preedit_bg_color="White"
mouse_opaque="true"
name="line_editor"
diff --git a/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml b/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml
index ea49b750d1..6824080b49 100644
--- a/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml
@@ -55,7 +55,6 @@
width="30" />
<panel_camera_item.text
follows="top|left|right"
- font="SansSerifMedium"
height="15"
layout="topleft"
left ="38"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index 51144c92b6..8294b96799 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -8,10 +8,10 @@
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
highlight_text_field="true"
- background_image="TextField_Search_Off"
- background_image_disabled="TextField_Search_Disabled"
- background_image_focused="TextField_Search_Active"
- background_image_highlight="TextField_Search_Highlight">
+ background_image="TextField_Off"
+ background_image_disabled="TextField_Disabled"
+ background_image_focused="TextField_Active"
+ background_image_highlight="TextField_Highlight">
<search_button
top_pad="4"
left_pad="4"
diff --git a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
index b99010e17a..041470d0d2 100644
--- a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
@@ -15,12 +15,12 @@
default_color="TextDefaultColor"
text_color="TextFgColor"
text_readonly_color="TextFgReadOnlyColor"
- text_selected_color="White"
+ text_selected_color="Black"
h_pad="6"
v_pad="4"
bg_visible="true"
bg_readonly_color="TextBgReadOnlyColor"
bg_writeable_color="TextBgWriteableColor"
- bg_selected_color="EmphasisColor"
+ bg_selected_color="SelectionColor"
bg_focus_color="TextBgFocusColor">
</simple_text_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index f565161794..523833d437 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -6,11 +6,12 @@ label_pad_left - padding to the left of tab button labels
<tab_container name="tab_container"
mouse_opaque="false"
tab_min_width="60"
- tab_max_width="150"
+ tab_max_width="160"
use_custom_icon_ctrl="false"
halign="center"
- font="SansSerifSmall"
- tab_height="22"
+ font="SansSerif"
+ font.size="Small"
+ tab_height="24"
label_pad_bottom="1"
label_pad_left="4">
<!--
@@ -19,22 +20,22 @@ label_pad_left - padding to the left of tab button labels
tab_left_image_flash
tab_top_image_flash
-->
- <first_tab tab_top_image_unselected="TabTop_Left_Off"
- tab_top_image_selected="TabTop_Left_Selected"
+ <first_tab tab_top_image_unselected="TabTop_First_Flat_Off"
+ tab_top_image_selected="TabTop_First_Flat_Selected"
tab_bottom_image_unselected="Toolbar_Left_Off"
tab_bottom_image_selected="Toolbar_Left_Selected"
- tab_left_image_unselected="SegmentedBtn_Left_Disabled"
- tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/>
- <middle_tab tab_top_image_unselected="TabTop_Middle_Off"
- tab_top_image_selected="TabTop_Middle_Selected"
+ tab_left_image_unselected="TabLeft_Flat_Off"
+ tab_left_image_selected="TabLeft_Flat_Selected"/>
+ <middle_tab tab_top_image_unselected="TabTop_Middle_Flat_Off"
+ tab_top_image_selected="TabTop_Middle_Flat_Selected"
tab_bottom_image_unselected="Toolbar_Middle_Off"
tab_bottom_image_selected="Toolbar_Middle_Selected"
- tab_left_image_unselected="SegmentedBtn_Left_Disabled"
- tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/>
- <last_tab tab_top_image_unselected="TabTop_Right_Off"
- tab_top_image_selected="TabTop_Right_Selected"
+ tab_left_image_unselected="TabLeft_Flat_Off"
+ tab_left_image_selected="TabLeft_Flat_Selected"/>
+ <last_tab tab_top_image_unselected="TabTop_Last_Flat_Off"
+ tab_top_image_selected="TabTop_Last_Flat_Selected"
tab_bottom_image_unselected="Toolbar_Right_Off"
tab_bottom_image_selected="Toolbar_Right_Selected"
- tab_left_image_unselected="SegmentedBtn_Left_Disabled"
- tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/>
+ tab_left_image_unselected="TabLeft_Flat_Off"
+ tab_left_image_selected="TabLeft_Flat_Selected"/>
</tab_container>
diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml
index 51852dd6dd..0447c18a33 100644
--- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml
+++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml
@@ -15,16 +15,17 @@
<button_icon_and_text imgoverlay_label_space="7"
label_color_selected="White"
halign="left"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
image_disabled_selected="PushButton_Selected_Disabled"
image_disabled="PushButton_Disabled"
button_width.min="70"
- button_width.max="140"
+ button_width.max="172"
desired_height="24"
pad_left="10"
pad_right="10"
+ pad_bottom="1"
follows="left|top"
chrome="true"
image_overlay_alignment="left"
@@ -37,7 +38,7 @@
pad_right="10"
image_bottom_pad="10"
image_top_pad="10"
- image_pressed="PushButton_Press"
+ image_pressed="PushButton_Selected"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
image_disabled_selected="PushButton_Selected_Disabled"
diff --git a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
index aa235e103b..a0b119ed72 100644
--- a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<inventory_list_item
follows="top|right|left"
- height="20"
+ height="21"
name="inventory_item"
tab_stop="false"
hover_image="ListItem_Over"
@@ -17,7 +17,7 @@
<worn_style
font="SansSerifSmall"
font.style="BOLD"
- color="EmphasisColor" />
+ color="WornOutfitTextColor" />
<item_icon
height="16"
follows="top|left"
@@ -25,18 +25,18 @@
layout="topleft"
left="0"
name="item_icon"
- top="0"
+ top="1"
width="16" />
<item_name
follows="left|right"
- height="20"
+ height="21"
layout="topleft"
left="21"
parse_urls="false"
use_ellipses="true"
name="item_name"
text_color="white"
- top="4"
+ top="2"
value="..."
width="359" />
<add_btn
diff --git a/indra/newview/skins/default/xui/es/floater_big_preview.xml b/indra/newview/skins/default/xui/es/floater_big_preview.xml
deleted file mode 100644
index b112243d7a..0000000000
--- a/indra/newview/skins/default/xui/es/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="VISTA PREVIA"/>
diff --git a/indra/newview/skins/default/xui/es/floater_post_process.xml b/indra/newview/skins/default/xui/es/floater_post_process.xml
deleted file mode 100644
index 5c62ccde36..0000000000
--- a/indra/newview/skins/default/xui/es/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="CONFIGURACIÓN DEL PROCESAMIENTO">
- <tab_container name="Post-Process Tabs">
- <panel label="Color del filtro" name="wmiColorFilterPanel">
- <check_box label="Activar" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- Brillo
- </text>
- <text name="wmiColorFilterSaturationText">
- Saturación
- </text>
- <text name="wmiColorFilterContrastText">
- Contraste
- </text>
- <text name="wmiColorFilterBaseText">
- Color base del contraste
- </text>
- <slider label="R" name="wmiColorFilterBaseR"/>
- <slider label="V" name="wmiColorFilterBaseG"/>
- <slider label="A" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="Visión nocturna" name="wmiNightVisionPanel">
- <check_box label="Activar" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- Amplificación de luz
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Cantidad de ruido
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Intensidad del ruido
- </text>
- </panel>
- <panel label="Bloom" name="wmiBloomPanel">
- <check_box label="Activar" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- Extracción de la luminosidad
- </text>
- <text name="wmiBloomSizeText">
- Bloom: cantidad
- </text>
- <text name="wmiBloomStrengthText">
- Bloom: intensidad
- </text>
- </panel>
- <panel label="Extras" name="Extras">
- <button label="Cargar efecto" label_selected="Cargar efecto" name="PPLoadEffect"/>
- <button label="Guardar efecto" label_selected="Guardar efecto" name="PPSaveEffect"/>
- <line_editor label="Nombre del efecto" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_sound_devices.xml b/indra/newview/skins/default/xui/es/floater_sound_devices.xml
deleted file mode 100644
index 0291f9e796..0000000000
--- a/indra/newview/skins/default/xui/es/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="DISPOSITIVOS DE SONIDO">
- <text name="voice_label">
- Chat de voz
- </text>
- <check_box label="Activados" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_voice_effect.xml b/indra/newview/skins/default/xui/es/floater_voice_effect.xml
deleted file mode 100644
index 02ebe80ff7..0000000000
--- a/indra/newview/skins/default/xui/es/floater_voice_effect.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Lugares" name="voice_effects" title="PROBAR TRANSFORMACIÓN DE VOZ">
- <string name="no_voice_effect">
- (Sin transformación de voz)
- </string>
- <string name="active_voice_effect">
- (Activo)
- </string>
- <string name="unsubscribed_voice_effect">
- (Suscripción cancelada)
- </string>
- <string name="new_voice_effect">
- (¡Nuevo!)
- </string>
- <string name="effect_Arena">
- Campo
- </string>
- <string name="effect_Beast">
- Bestia
- </string>
- <string name="effect_Buff">
- Musculoso
- </string>
- <string name="effect_Buzz">
- Murmullo
- </string>
- <string name="effect_Camille">
- Camila
- </string>
- <string name="effect_Creepy">
- Aterrador
- </string>
- <string name="effect_CreepyBot">
- Robot aterrador
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- Robot profundo
- </string>
- <string name="effect_Demon">
- Diablo
- </string>
- <string name="effect_Flirty">
- Coqueta
- </string>
- <string name="effect_Foxy">
- Astuto
- </string>
- <string name="effect_Halloween_2010_Bonus">
- Halloween_2010_Bonus
- </string>
- <string name="effect_Helium">
- Helio
- </string>
- <string name="effect_Husky">
- Corpulento
- </string>
- <string name="effect_Intercom">
- Intercom
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Pesadilla
- </string>
- <string name="effect_PopBot">
- Robot pop
- </string>
- <string name="effect_Rachel">
- Raquel
- </string>
- <string name="effect_Radio">
- Radio
- </string>
- <string name="effect_Robot">
- Robot
- </string>
- <string name="effect_Roxanne">
- Roxana
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samanta
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Bajito
- </string>
- <string name="effect_Sneaky">
- Furtivo
- </string>
- <string name="effect_Stallion">
- Mujeriego
- </string>
- <string name="effect_Sultry">
- Sensual
- </string>
- <string name="effect_Thunder">
- Trueno
- </string>
- <string name="effect_Vixen">
- Tigresa
- </string>
- <string name="effect_WhinyBot">
- Robot llorica
- </string>
- <text name="preview_text">
- Para probarla
- </text>
- <text name="status_text">
- Graba una muestra y pulsa en una voz para escuchar cómo suena.
- </text>
- <button label="Grabar" name="record_btn" tool_tip="Graba una muestra de tu voz."/>
- <button label="Parar" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Suscríbete ahora]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Graba una muestra de tu voz y pulsa en un efecto para ver cómo suena.">
- <scroll_list.columns label="Nombre de la voz" name="name"/>
- <scroll_list.columns label="Caduca" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/es/panel_login_first.xml b/indra/newview/skins/default/xui/es/panel_login_first.xml
deleted file mode 100644
index ccb6858351..0000000000
--- a/indra/newview/skins/default/xui/es/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=es
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Nombre de usuario" name="username_combo" tool_tip="El nombre de usuario que elegiste al registrarte, como bobsmith12 o Steller Sunshine"/>
- <line_editor label="Contraseña" name="password_edit"/>
- <button label="Iniciar sesión" name="connect_btn"/>
- <check_box label="Recordarme" name="remember_check"/>
- <text name="forgot_password_text">
- Contraseña olvidada
- </text>
- <text name="sign_up_text">
- Regístrate
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Tu primer destino es la Isla de aprendizaje. ¡Encuentra el portal de salida!
- </text>
- <text name="image_caption_right">
- A continuación, puedes explorar la Isla social y hablar con otros residentes nuevos.
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_voice_effect.xml b/indra/newview/skins/default/xui/es/panel_voice_effect.xml
deleted file mode 100644
index 94a0428941..0000000000
--- a/indra/newview/skins/default/xui/es/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Transformación de voz desactivada
- </string>
- <string name="preview_voice_effects">
- Probar transformación de voz ▶
- </string>
- <string name="get_voice_effects">
- Obtener transformación de voz ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Selecciona una transformación de voz para cambiar tu voz">
- <combo_box.item label="Transformación de voz desactivada" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/fr/floater_big_preview.xml b/indra/newview/skins/default/xui/fr/floater_big_preview.xml
deleted file mode 100644
index 0c09a4c188..0000000000
--- a/indra/newview/skins/default/xui/fr/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="APERÇU"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_post_process.xml b/indra/newview/skins/default/xui/fr/floater_post_process.xml
deleted file mode 100644
index a22c7512e5..0000000000
--- a/indra/newview/skins/default/xui/fr/floater_post_process.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="PARAMÈTRES POST-TRAITEMENT">
- <tab_container name="Post-Process Tabs">
- <panel label="Filtre couleur" name="wmiColorFilterPanel">
- <check_box label="Activer" name="wmiColorFilterToggle" />
- <text name="wmiColorFilterBrightnessText">
- Luminosité
- </text>
- <text name="wmiColorFilterSaturationText">
- Saturation
- </text>
- <text name="wmiColorFilterContrastText">
- Contraste
- </text>
- <text name="wmiColorFilterBaseText">
- Couleur de base du contraste
- </text>
- <slider label="R" name="wmiColorFilterBaseR" />
- <slider label="V" name="wmiColorFilterBaseG" />
- <slider label="B" name="wmiColorFilterBaseB" />
- <slider label="I" name="wmiColorFilterBaseI" />
- </panel>
- <panel label="Vision de nuit" name="wmiNightVisionPanel">
- <check_box label="Activer" name="wmiNightVisionToggle" />
- <text name="wmiNightVisionBrightMultText">
- Multiple d&apos;amplificateur de lumière
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Taille du bruit
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Force du bruit
- </text>
- </panel>
- <panel label="Éclat" name="wmiBloomPanel">
- <check_box label="Activer" name="wmiBloomToggle" />
- <text name="wmiBloomExtractText">
- Extraction de la luminosité
- </text>
- <text name="wmiBloomSizeText">
- Taille de l&apos;éclat
- </text>
- <text name="wmiBloomStrengthText">
- Force de l&apos;éclat
- </text>
- </panel>
- <panel label="Extras" name="Extras">
- <button label="Charger effet" label_selected="Charger effet" name="PPLoadEffect" />
- <button label="Enregistrer effet" label_selected="Enregistrer effet"
- name="PPSaveEffect" />
- <line_editor label="Nom de l&apos;effet" name="PPEffectNameEditor" />
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_sound_devices.xml b/indra/newview/skins/default/xui/fr/floater_sound_devices.xml
deleted file mode 100644
index 080ade9dd4..0000000000
--- a/indra/newview/skins/default/xui/fr/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="PERIPHERIQUES AUDIO">
- <text name="voice_label">
- Chat vocal
- </text>
- <check_box label="Activé" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml b/indra/newview/skins/default/xui/fr/floater_voice_effect.xml
deleted file mode 100644
index f9a76d127e..0000000000
--- a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Endroits" name="voice_effects" title="APERÇU DES EFFETS DE VOIX">
- <string name="no_voice_effect">
- (Aucun effet de voix)
- </string>
- <string name="active_voice_effect">
- (Actif)
- </string>
- <string name="unsubscribed_voice_effect">
- (Pas d&apos;abonnement)
- </string>
- <string name="new_voice_effect">
- (Nouveau !)
- </string>
- <string name="effect_Arena">
- Stade
- </string>
- <string name="effect_Beast">
- Brute
- </string>
- <string name="effect_Buff">
- Nasal
- </string>
- <string name="effect_Buzz">
- Friture
- </string>
- <string name="effect_Camille">
- Camille
- </string>
- <string name="effect_Creepy">
- Effrayant
- </string>
- <string name="effect_CreepyBot">
- BotEffrayant
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- BotGrave
- </string>
- <string name="effect_Demon">
- Démon
- </string>
- <string name="effect_Female Elf">
- Femme elfe
- </string>
- <string name="effect_Flirty">
- Flirt
- </string>
- <string name="effect_Foxy">
- Séduction
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Halloween_2010_Bonus
- </string>
- <string name="effect_Helium">
- Hélium
- </string>
- <string name="effect_Husky">
- Rauque
- </string>
- <string name="effect_Husky Whisper">
- Murmure rauque
- </string>
- <string name="effect_Intercom">
- Interphone
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Mélodieux
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Modèle
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Cauchemar
- </string>
- <string name="effect_PopBot">
- BotPop
- </string>
- <string name="effect_Rachel">
- Rachel
- </string>
- <string name="effect_Radio">
- Radio
- </string>
- <string name="effect_Robot">
- Robot
- </string>
- <string name="effect_Roxanne">
- Roxanne
- </string>
- <string name="effect_Rumble">
- Grondement
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samantha
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Petite voix
- </string>
- <string name="effect_Smaller">
- Plus faible
- </string>
- <string name="effect_Sneaky">
- Sournois
- </string>
- <string name="effect_Stallion">
- Étalon
- </string>
- <string name="effect_Sultry">
- Sensuel
- </string>
- <string name="effect_Thunder">
- Tonnerre
- </string>
- <string name="effect_Vixen">
- Mégère
- </string>
- <string name="effect_WhinyBot">
- BotPleurnichard
- </string>
- <text name="preview_text">
- Aperçu
- </text>
- <text name="status_text">
- Enregistrez un extrait et cliquez sur un effet pour obtenir un aperçu.
- </text>
- <button label="Enregistrer" name="record_btn" tool_tip="Enregistrez un extrait de votre voix."/>
- <button label="Arrêter" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] S&apos;abonner]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Enregistrez un extrait de votre voix, puis cliquez sur un effet pour obtenir un aperçu.">
- <scroll_list.columns label="Nom de l&apos;effet" name="name"/>
- <scroll_list.columns label="Date d&apos;expiration" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/fr/panel_login_first.xml b/indra/newview/skins/default/xui/fr/panel_login_first.xml
deleted file mode 100644
index 8f40d0230c..0000000000
--- a/indra/newview/skins/default/xui/fr/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=fr
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Nom d&apos;utilisateur" name="username_combo" tool_tip="Nom d&apos;utilisateur que vous avez choisi lors de votre inscription (par exemple, bobsmith12 ou Steller Sunshine)."/>
- <line_editor label="Mot de passe" name="password_edit"/>
- <button label="Connexion" name="connect_btn"/>
- <check_box font="SansSerifSmall" label="Mémoriser mes informations" name="remember_check"/>
- <text name="forgot_password_text">
- Mot de passe oublié
- </text>
- <text name="sign_up_text">
- S&apos;inscrire
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Votre première étape est Learning Island. Trouvez le portail de sortie.
- </text>
- <text name="image_caption_right">
- Puis explorez Social Island et faites la connaissance d&apos;autres résidents.
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_voice_effect.xml b/indra/newview/skins/default/xui/fr/panel_voice_effect.xml
deleted file mode 100644
index a134854706..0000000000
--- a/indra/newview/skins/default/xui/fr/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Effet de voix désactivé
- </string>
- <string name="preview_voice_effects">
- Aperçu des effets de voix ▶
- </string>
- <string name="get_voice_effects">
- Obtenir un effet de voix ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Sélectionner un effet pour modifier le son de votre voix">
- <combo_box.item label="Effet de voix désactivé" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/it/floater_big_preview.xml b/indra/newview/skins/default/xui/it/floater_big_preview.xml
deleted file mode 100644
index 7bc50a6d39..0000000000
--- a/indra/newview/skins/default/xui/it/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="ANTEPRIMA"/>
diff --git a/indra/newview/skins/default/xui/it/floater_post_process.xml b/indra/newview/skins/default/xui/it/floater_post_process.xml
deleted file mode 100644
index 3aa8b29101..0000000000
--- a/indra/newview/skins/default/xui/it/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="IMPOSTAZIONI DI POST-PRODUZIONE">
- <tab_container name="Post-Process Tabs">
- <panel label="Filtro Colore" name="wmiColorFilterPanel">
- <check_box label="Abilita" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- Luminosità
- </text>
- <text name="wmiColorFilterSaturationText">
- Saturazione
- </text>
- <text name="wmiColorFilterContrastText">
- Contrasto
- </text>
- <text name="wmiColorFilterBaseText">
- Colore Base Contrasto
- </text>
- <slider label="R" name="wmiColorFilterBaseR"/>
- <slider label="G" name="wmiColorFilterBaseG"/>
- <slider label="B" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="Visione Notturna" name="wmiNightVisionPanel">
- <check_box label="Abilita" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- Amplificazione Multipla Luce
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Ampiezza disturbo
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Forza disturbo
- </text>
- </panel>
- <panel label="Raggiatura" name="wmiBloomPanel">
- <check_box label="Abilita" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- Estrazione luminosità
- </text>
- <text name="wmiBloomSizeText">
- Dimensione raggiatura
- </text>
- <text name="wmiBloomStrengthText">
- Forza raggiatura
- </text>
- </panel>
- <panel label="Extra" name="Extras">
- <button label="Carica effetto" label_selected="Carica effetto" name="PPLoadEffect"/>
- <button label="Salva effetto" label_selected="Salva effetto" name="PPSaveEffect"/>
- <line_editor label="Nome Effetto" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_sound_devices.xml b/indra/newview/skins/default/xui/it/floater_sound_devices.xml
deleted file mode 100644
index 9799b48d89..0000000000
--- a/indra/newview/skins/default/xui/it/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="DISPOSITIVI AUDIO">
- <text name="voice_label">
- Chat vocale
- </text>
- <check_box label="Abilitato" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_voice_effect.xml b/indra/newview/skins/default/xui/it/floater_voice_effect.xml
deleted file mode 100644
index f102622f5d..0000000000
--- a/indra/newview/skins/default/xui/it/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Luoghi" name="voice_effects" title="ANTEPRIMA MANIPOLAZIONE VOCE">
- <string name="no_voice_effect">
- (Nessuna manipolazione voce)
- </string>
- <string name="active_voice_effect">
- (Attivato)
- </string>
- <string name="unsubscribed_voice_effect">
- (Iscrizione annullata)
- </string>
- <string name="new_voice_effect">
- (Nuovo!)
- </string>
- <string name="effect_Arena">
- Arena
- </string>
- <string name="effect_Beast">
- Bestia
- </string>
- <string name="effect_Buff">
- Appassionato
- </string>
- <string name="effect_Buzz">
- Euforia
- </string>
- <string name="effect_Camille">
- Camilla
- </string>
- <string name="effect_Creepy">
- Terrificante
- </string>
- <string name="effect_CreepyBot">
- TerrificanteBot
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- ProfondoBot
- </string>
- <string name="effect_Demon">
- Demonio
- </string>
- <string name="effect_Female Elf">
- Elfo donna
- </string>
- <string name="effect_Flirty">
- Civettuolo
- </string>
- <string name="effect_Foxy">
- Scaltro
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Halloween_2010_Bonus
- </string>
- <string name="effect_Helium">
- Elio
- </string>
- <string name="effect_Husky">
- Fusto
- </string>
- <string name="effect_Husky Whisper">
- Sospiro rauco
- </string>
- <string name="effect_Intercom">
- Interfono
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Inflessione bassa
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Modella
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Incubo
- </string>
- <string name="effect_PopBot">
- PopBot
- </string>
- <string name="effect_Rachel">
- Rachele
- </string>
- <string name="effect_Radio">
- Radio
- </string>
- <string name="effect_Robot">
- Robot
- </string>
- <string name="effect_Roxanne">
- Rosanna
- </string>
- <string name="effect_Rumble">
- Rombo
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samanta
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Bassotto
- </string>
- <string name="effect_Smaller">
- Più piccolo
- </string>
- <string name="effect_Sneaky">
- Vile
- </string>
- <string name="effect_Stallion">
- Stallone
- </string>
- <string name="effect_Sultry">
- Focoso
- </string>
- <string name="effect_Thunder">
- Tuono
- </string>
- <string name="effect_Vixen">
- Maliziosa
- </string>
- <string name="effect_WhinyBot">
- PiangiBot
- </string>
- <text name="preview_text">
- Per l&apos;anteprima
- </text>
- <text name="status_text">
- Registra un campione di voce, quindi fai clic su un effetto per ascoltare il risultato.
- </text>
- <button label="Registra" name="record_btn" tool_tip="Registra un campione della tua voce."/>
- <button label="Ferma" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Subscribe Now]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Registra un campione della tua voce, quindi fai clic su uno degli effetti per un&apos;anteprima del risultato.">
- <scroll_list.columns label="Nome effetto" name="name"/>
- <scroll_list.columns label="Scade il" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/it/panel_login_first.xml b/indra/newview/skins/default/xui/it/panel_login_first.xml
deleted file mode 100644
index 5b04fd411a..0000000000
--- a/indra/newview/skins/default/xui/it/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=it
- </panel.string>
- <panel.string name="sign_up_url">
- http://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Nome utente" name="username_combo" tool_tip="Il nome utente che hai scelto durante la registrazione, come roby12 o Stella Solare"/>
- <line_editor label="Password" name="password_edit"/>
- <button label="Accedi" name="connect_btn"/>
- <check_box label="Ricordami" name="remember_check"/>
- <text name="forgot_password_text">
- Password dimenticata
- </text>
- <text name="sign_up_text">
- Registrati
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Il primo passo è a Learning Island. Trova il portale di uscita!
- </text>
- <text name="image_caption_right">
- Quindi esplora Social Island e incontra altri nuovi residenti.
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_voice_effect.xml b/indra/newview/skins/default/xui/it/panel_voice_effect.xml
deleted file mode 100644
index b43f766e5e..0000000000
--- a/indra/newview/skins/default/xui/it/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Disattiva manipolazione voce
- </string>
- <string name="preview_voice_effects">
- Anteprima manipolazione voce ▶
- </string>
- <string name="get_voice_effects">
- Ottieni manipolazione voce ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Scegli un effetto di manipolazione per modificare il suono della tua voce">
- <combo_box.item label="Disattiva manipolazione voce" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/ja/floater_big_preview.xml b/indra/newview/skins/default/xui/ja/floater_big_preview.xml
deleted file mode 100644
index e88d6fc488..0000000000
--- a/indra/newview/skins/default/xui/ja/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="プレビュー"/> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/ja/floater_post_process.xml b/indra/newview/skins/default/xui/ja/floater_post_process.xml
deleted file mode 100644
index 91ecbb73a2..0000000000
--- a/indra/newview/skins/default/xui/ja/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="ポストプロセス設定">
- <tab_container name="Post-Process Tabs">
- <panel label="カラー・フィルタ" name="wmiColorFilterPanel">
- <check_box label="有効" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- 明度
- </text>
- <text name="wmiColorFilterSaturationText">
- 彩度
- </text>
- <text name="wmiColorFilterContrastText">
- 輝度
- </text>
- <text name="wmiColorFilterBaseText">
- 輝度の基準色
- </text>
- <slider label="赤" name="wmiColorFilterBaseR"/>
- <slider label="緑" name="wmiColorFilterBaseG"/>
- <slider label="青" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="暗視" name="wmiNightVisionPanel">
- <check_box label="有効" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- 光の増幅(マルチ)
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- ノイズ・サイズ
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- ノイズ強度
- </text>
- </panel>
- <panel label="ブルーム" name="wmiBloomPanel">
- <check_box label="有効" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- 明度の抽出
- </text>
- <text name="wmiBloomSizeText">
- ブルーム・サイズ
- </text>
- <text name="wmiBloomStrengthText">
- ブルーム強度
- </text>
- </panel>
- <panel label="その他" name="Extras">
- <button label="効果読み込み" label_selected="効果読み込み" name="PPLoadEffect"/>
- <button label="効果保存" label_selected="効果保存" name="PPSaveEffect"/>
- <line_editor label="効果名" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_sound_devices.xml b/indra/newview/skins/default/xui/ja/floater_sound_devices.xml
deleted file mode 100644
index 28d2388bed..0000000000
--- a/indra/newview/skins/default/xui/ja/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="サウンドデバイス">
- <text name="voice_label">
- ボイスチャット
- </text>
- <check_box label="有効" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml b/indra/newview/skins/default/xui/ja/floater_voice_effect.xml
deleted file mode 100644
index b38ea9331a..0000000000
--- a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="場所" name="voice_effects" title="ボイスモーフィングのプレビュー">
- <string name="no_voice_effect">
- (ボイスモーフィングなし)
- </string>
- <string name="active_voice_effect">
- (アクティブ)
- </string>
- <string name="unsubscribed_voice_effect">
- (取消し済み)
- </string>
- <string name="new_voice_effect">
- (新登場!)
- </string>
- <string name="effect_Arena">
- アリーナ
- </string>
- <string name="effect_Beast">
- 野獣
- </string>
- <string name="effect_Buff">
- がっしり
- </string>
- <string name="effect_Buzz">
- ブザー
- </string>
- <string name="effect_Camille">
- カミール
- </string>
- <string name="effect_Creepy">
- 気味の悪い
- </string>
- <string name="effect_CreepyBot">
- 気味わるボット
- </string>
- <string name="effect_Cyber">
- サイバー
- </string>
- <string name="effect_DeepBot">
- ディープボット
- </string>
- <string name="effect_Demon">
- デーモン
- </string>
- <string name="effect_Female Elf">
- 女性のエルフ
- </string>
- <string name="effect_Flirty">
- 気のありそうな
- </string>
- <string name="effect_Foxy">
- 魅惑的
- </string>
- <string name="effect_Halloween 2010 Bonus">
- ハロウィン_2010_ボーナス
- </string>
- <string name="effect_Helium">
- ヘリウム
- </string>
- <string name="effect_Husky">
- ハスキー
- </string>
- <string name="effect_Husky Whisper">
- スモーキーウィスパー
- </string>
- <string name="effect_Intercom">
- インターホン
- </string>
- <string name="effect_Julia">
- ジュリア
- </string>
- <string name="effect_Lo Lilt">
- 軽快
- </string>
- <string name="effect_Macho">
- マッチョ
- </string>
- <string name="effect_Micro">
- ミクロ
- </string>
- <string name="effect_Mini">
- ミニ
- </string>
- <string name="effect_Model">
- モデル
- </string>
- <string name="effect_Nano">
- ナノ
- </string>
- <string name="effect_Nightmare">
- 悪夢
- </string>
- <string name="effect_PopBot">
- ポップボット
- </string>
- <string name="effect_Rachel">
- レイチェル
- </string>
- <string name="effect_Radio">
- ラジオ
- </string>
- <string name="effect_Robot">
- ロボット
- </string>
- <string name="effect_Roxanne">
- ロクサン
- </string>
- <string name="effect_Rumble">
- ランブル
- </string>
- <string name="effect_Sabrina">
- サブリナ
- </string>
- <string name="effect_Samantha">
- サマンサ
- </string>
- <string name="effect_Sexy">
- セクシー
- </string>
- <string name="effect_Shorty">
- チビ
- </string>
- <string name="effect_Smaller">
- 小さめ
- </string>
- <string name="effect_Sneaky">
- コソコソ
- </string>
- <string name="effect_Stallion">
- 雄馬
- </string>
- <string name="effect_Sultry">
- 艶かしい
- </string>
- <string name="effect_Thunder">
- サンダー
- </string>
- <string name="effect_Vixen">
- 性悪な
- </string>
- <string name="effect_WhinyBot">
- 不機嫌ボット
- </string>
- <text name="preview_text">
- プレビュー
- </text>
- <text name="status_text">
- 声をテスト録音してからボイスエフェクトを1つクリックして聞いてみます。
- </text>
- <button label="録音" name="record_btn" tool_tip="あなたの声を録音します。"/>
- <button label="停止" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] 今すぐ申し込む]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="声を録音してボイスモーフィングを1つクリックすると、そのエフェクトをプレビューできます。">
- <scroll_list.columns label="ボイス名" name="name"/>
- <scroll_list.columns label="有効期限" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/ja/fonts.xml b/indra/newview/skins/default/xui/ja/fonts.xml
index 2085e916c8..7abb3593b6 100644
--- a/indra/newview/skins/default/xui/ja/fonts.xml
+++ b/indra/newview/skins/default/xui/ja/fonts.xml
@@ -2,11 +2,9 @@
<fonts>
<font name="default" comment="default font files (global fallbacks)">
<file>
- NotoSansCJKjp-Medium.otf
- </file>
- <file>
- DejaVuSans.ttf
+ NotoSansCJKjp-SemiBold.otf
</file>
+ <file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
<os name="Windows">
<file load_collection="true">
YuGothM.ttc
@@ -41,7 +39,7 @@
</os>
<os name="Mac">
<file>
- YuGothic-Medium.otf
+ YuGothic-SemiBold.otf
</file>
<file>
ヒラギノ角ゴシック W3.ttc
@@ -82,9 +80,7 @@
<file>
NotoSansCJKjp-Bold.otf
</file>
- <file>
- DejaVuSans-Bold.ttf
- </file>
+ <file load_collection="true" font_weight="700" flags="bold">InterVariableFont.ttf</file>
<os name="Windows">
<file load_collection="true">
YuGothB.ttc
@@ -104,11 +100,9 @@
</font>
<font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
<file>
- NotoSansCJKjp-Bold.otf
- </file>
- <file>
- DejaVuSans.ttf
+ NotoSansCJKjp-SemiBold.otf
</file>
+ <file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
<os name="Windows">
<file>
arial.ttf
@@ -121,19 +115,13 @@
</os>
</font>
<font name="SansSerif" comment="Name of bold sans-serif font" font_style="BOLD">
- <file>
- DejaVuSans-Bold.ttf
- </file>
+ <file load_collection="true" font_weight="700" flags="bold">InterVariableFont.ttf</file>
</font>
<font name="SansSerif" comment="Name of italic sans-serif font" font_style="ITALIC">
- <file>
- DejaVuSans-Oblique.ttf
- </file>
+ <file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
</font>
<font name="SansSerif" comment="Name of bold italic sans-serif font" font_style="BOLD|ITALIC">
- <file>
- DejaVuSans-BoldOblique.ttf
- </file>
+ <file load_collection="true" flags="bold" font_weight="700">InterItalicVariableFont.ttf</file>
</font>
<font name="Monospace" comment="Name of monospace font">
<file>
@@ -144,29 +132,25 @@
</file>
</font>
<font name="DejaVu" comment="Name of DejaVu font">
- <file>
- DejaVuSans.ttf
- </file>
+ <file>DejaVuSans.ttf</file>
</font>
<font name="DejaVu" comment="Name of DejaVu font (bold)" font_style="BOLD">
- <file>
- DejaVuSans-Bold.ttf
- </file>
+ <file>
+ DejaVuSans-Bold.ttf
+ </file>
</font>
<font name="DejaVu" comment="Name of DejaVu font (italic)" font_style="ITALIC">
- <file>
- DejaVuSans-Oblique.ttf
- </file>
+ <file>
+ DejaVuSans-Oblique.ttf
+ </file>
</font>
<font name="DejaVu" comment="Name of DejaVu font (bold italic)" font_style="BOLD|ITALIC">
- <file>
- DejaVuSans-BoldOblique.ttf
- </file>
+ <file>
+ DejaVuSans-BoldOblique.ttf
+ </file>
</font>
<font name="Helvetica" comment="Name of Helvetica font">
- <file>
- DejaVuSans.ttf
- </file>
+ <file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
<os name="Windows">
<file>
arial.ttf
@@ -179,9 +163,7 @@
</os>
</font>
<font name="Helvetica" comment="Name of Helvetica font (bold)" font_style="BOLD">
- <file>
- DejaVuSans-Bold.ttf
- </file>
+ <file load_collection="true" font_weight="700" flags="bold">InterVariableFont.ttf</file>
<os name="Windows">
<file>
arialbd.ttf
@@ -194,9 +176,7 @@
</os>
</font>
<font name="Helvetica" comment="Name of Helvetica font (italic)" font_style="ITALIC">
- <file>
- DejaVuSans-Oblique.ttf
- </file>
+ <file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
<os name="Windows">
<file>
ariali.ttf
@@ -209,9 +189,7 @@
</os>
</font>
<font name="Helvetica" comment="Name of Helvetica font (bold italic)" font_style="BOLD|ITALIC">
- <file>
- DejaVuSans-BoldOblique.ttf
- </file>
+ <file load_collection="true" flags="bold" font_weight="700">InterItalicVariableFont.ttf</file>
<os name="Windows">
<file>
arialbi.ttf
@@ -227,13 +205,11 @@
<file>
times.ttf
</file>
- <file>
- DejaVuSans.ttf
- </file>
+ <file font_weight="400">InterVariableFont.ttf</file>
</font>
<font_size name="Monospace" comment="Size for monospaced font (points, or 1/72 of an inch)" size="8.0"/>
<font_size name="Huge" comment="Size of huge font (points, or 1/72 of an inch)" size="16.0"/>
- <font_size name="Large" comment="Size of large font (points, or 1/72 of an inch)" size="10.6"/>
- <font_size name="Medium" comment="Size of medium font (points, or 1/72 of an inch)" size="8.6"/>
- <font_size name="Small" comment="Size of small font (points, or 1/72 of an inch)" size="7.6"/>
+ <font_size name="Large" comment="Size of large font (points, or 1/72 of an inch)" size="11"/>
+ <font_size name="Medium" comment="Size of medium font (points, or 1/72 of an inch)" size="9"/>
+ <font_size name="Small" comment="Size of small font (points, or 1/72 of an inch)" size="8"/>
</fonts>
diff --git a/indra/newview/skins/default/xui/ja/panel_login_first.xml b/indra/newview/skins/default/xui/ja/panel_login_first.xml
deleted file mode 100644
index 0f987fc816..0000000000
--- a/indra/newview/skins/default/xui/ja/panel_login_first.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- https://secondlife.com/my/account/request.php?lang=ja-JP
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/?lang=ja
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="page_top"/>
- <layout_panel name="parent_panel">
- <layout_stack name="logo_stack">
- <layout_panel name="logo_left"/>
- <layout_panel name="logo_container">
- <icon name="sl_logo"/>
- </layout_panel>
- <layout_panel auto_resize="true"/>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_left"/>
- <layout_panel name="widget_container">
- <combo_box label="ユーザ名" tool_tip="登録時に自分で選んだユーザー名(例:bobsmith12、Steller Sunshineなど)" name="username_combo">
- <combo_box.combo_editor/>
- <combo_box.combo_button/>
- <combo_box.drop_down_button/>
- </combo_box>
- <line_editor name="password_edit" label="パスワード"/>
- <button label="ログイン" name="connect_btn"/>
- <text name="sign_up_text" valign="center">
- サインアップ
- </text>
- <check_box label="ユーザ名を記憶" name="remember_name" tool_tip="すでに記憶されているユーザーは、「私」>「初期設定」>「詳細設定」>「記憶されたユーザー名」から削除できます。"/>
- <check_box label="パスワード記憶" name="remember_password"/>
- <text name="forgot_password_text">
- パスワードを忘れましたか?
- </text>
- </layout_panel>
- <layout_panel name="widget_right"/>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_left"/>
- <layout_panel name="images_container">
- <icon name="image_left"/>
- </layout_panel>
- <layout_panel name="images_right"/>
- </layout_stack>
- </layout_panel>
- <layout_panel name="page_bottom"/>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_voice_effect.xml b/indra/newview/skins/default/xui/ja/panel_voice_effect.xml
deleted file mode 100644
index 57a1bb7838..0000000000
--- a/indra/newview/skins/default/xui/ja/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- ボイスモーフィングなし
- </string>
- <string name="preview_voice_effects">
- ボイスモーフィングをプレビュー
- </string>
- <string name="get_voice_effects">
- ボイスモーフィングを取得
- </string>
- <combo_box name="voice_effect" tool_tip="ボイスモーフィングを選択してボイスを変更">
- <combo_box.item label="ボイスモーフィングなし" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/pl/floater_big_preview.xml b/indra/newview/skins/default/xui/pl/floater_big_preview.xml
deleted file mode 100644
index e730cff618..0000000000
--- a/indra/newview/skins/default/xui/pl/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<floater name="floater_big_preview" title="PODGLĄD" />
diff --git a/indra/newview/skins/default/xui/pl/floater_post_process.xml b/indra/newview/skins/default/xui/pl/floater_post_process.xml
deleted file mode 100644
index 47c40d2315..0000000000
--- a/indra/newview/skins/default/xui/pl/floater_post_process.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="USTAWIENIA PRZETWARZANIA KOŃCOWEGO">
- <tab_container name="Post-Process Tabs">
- <panel label="Filtr koloru" name="wmiColorFilterPanel">
- <check_box label="Włącz" name="wmiColorFilterToggle" />
- <text name="wmiColorFilterBrightnessText">
- Jasność
- </text>
- <text name="wmiColorFilterSaturationText">
- Nasycenie
- </text>
- <text name="wmiColorFilterContrastText">
- Kontrast
- </text>
- <text name="wmiColorFilterBaseText">
- Kontrast koloru podstawowego
- </text>
- </panel>
- <panel label="Noktowizja" name="wmiNightVisionPanel">
- <check_box label="Włącz" name="wmiNightVisionToggle" />
- <text name="wmiNightVisionBrightMultText">
- Wielokrotne wzmocnienie światła
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Rozmiar szumu
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Moc szumu
- </text>
- </panel>
- <panel label="Poświata" name="wmiBloomPanel">
- <check_box label="Włącz" name="wmiBloomToggle" />
- <text name="wmiBloomExtractText">
- Ekstracja luminacji
- </text>
- <text name="wmiBloomSizeText">
- Rozmiar poświaty
- </text>
- <text name="wmiBloomStrengthText">
- Moc poświaty
- </text>
- </panel>
- <panel label="Dodatki" name="Extras">
- <button label="Wczytaj efekt" label_selected="Wczytaj efekt" name="PPLoadEffect" />
- <button label="Zapisz efekt" label_selected="Zapisz efekt" name="PPSaveEffect" />
- <line_editor label="Nazwa efektu" name="PPEffectNameEditor" />
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_sound_devices.xml b/indra/newview/skins/default/xui/pl/floater_sound_devices.xml
deleted file mode 100644
index 93a27f68a7..0000000000
--- a/indra/newview/skins/default/xui/pl/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_sound_devices" title="URZĄDZENIA DŹWIĘKOWE">
- <text name="voice_label">
- Czat głos.
- </text>
- <check_box name="enable_voice" label="Włączone" />
-</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_voice_effect.xml b/indra/newview/skins/default/xui/pl/floater_voice_effect.xml
deleted file mode 100644
index b02266caa9..0000000000
--- a/indra/newview/skins/default/xui/pl/floater_voice_effect.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="voice_effects" title="PODGLĄD PRZEKSZTAŁCANIA GŁOSU" label="Miejsca">
- <string name="no_voice_effect">
- (Bez Przekształcania)
- </string>
- <string name="active_voice_effect">
- (Aktywny)
- </string>
- <string name="unsubscribed_voice_effect">
- (Bez subskrybcji)
- </string>
- <string name="new_voice_effect">
- (Nowy!)
- </string>
- <string name="effect_Beast">
- Bestia
- </string>
- <string name="effect_Buzz">
- Brzęczenie
- </string>
- <string name="effect_Creepy">
- Przerażający
- </string>
- <string name="effect_Cyber">
- Cybernetyczny
- </string>
- <string name="effect_Female Elf">
- Kobiecy Elf
- </string>
- <string name="effect_Flirty">
- Flirt
- </string>
- <string name="effect_Foxy">
- Ponętny
- </string>
- <string name="effect_Helium">
- Hel
- </string>
- <string name="effect_Husky Whisper">
- Szept Husky
- </string>
- <string name="effect_Macho">
- Maczo
- </string>
- <string name="effect_Micro">
- Mikrus
- </string>
- <string name="effect_Mini">
- Miniaturowy
- </string>
- <string name="effect_Nano">
- Malutki
- </string>
- <string name="effect_Nightmare">
- Koszmar
- </string>
- <string name="effect_Rumble">
- Burczenie
- </string>
- <string name="effect_Sexy">
- Seksowny
- </string>
- <string name="effect_Shorty">
- Krótki
- </string>
- <string name="effect_Smaller">
- Mniejszy
- </string>
- <string name="effect_Sneaky">
- Podstępny
- </string>
- <string name="effect_Stallion">
- Ogier
- </string>
- <string name="effect_Sultry">
- Gorąco
- </string>
- <string name="effect_Thunder">
- Grzmot
- </string>
- <string name="effect_Vixen">
- Lisica
- </string>
- <text name="preview_text">
- Podgląd
- </text>
- <text name="status_text">
- Nagraj próbkę, a następnie kliknij na głos aby usłyszeć jego brzmienie.
- </text>
- <button label="Nagraj" name="record_btn" tool_tip="Nagraj próbkę swojego głosu." />
- <text name="voice_morphing_link">
- [[URL] Subskrybuj teraz]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Nagraj próbkę swojego głosu, a następnie kliknij na efekt aby odsłuchać podgląd.">
- <scroll_list.columns label="Nazwa głosu" name="name" />
- <scroll_list.columns label="Wygasa" name="expires" />
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/pl/panel_login_first.xml b/indra/newview/skins/default/xui/pl/panel_login_first.xml
deleted file mode 100644
index 0604ecbcff..0000000000
--- a/indra/newview/skins/default/xui/pl/panel_login_first.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="panel_login">
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Użytkownik" tool_tip="Nazwa użytkownika wybrana przy rejestracji, np. bobsmith12 lub Steller Sunshine" name="username_combo" />
- <line_editor name="password_edit" label="Hasło" />
- <button label="Zaloguj" name="connect_btn" />
- <check_box label="Zapamiętaj mnie" name="remember_check" />
- <text name="forgot_password_text">
- Zapomniałem/am hasła
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Wyspa Nauki to Twój pierwszy krok. Znajdź portal z wyjściem!
- </text>
- <text name="image_caption_right">
- Potem zwiedź Wyspę Towarzyską i poznaj innych nowych rezydentów!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_voice_effect.xml b/indra/newview/skins/default/xui/pl/panel_voice_effect.xml
deleted file mode 100644
index 94878943a1..0000000000
--- a/indra/newview/skins/default/xui/pl/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Wyłącz Przekształcanie
- </string>
- <string name="preview_voice_effects">
- Przeglądaj Przekształcania ▶
- </string>
- <string name="get_voice_effects">
- Uzyskaj Przekształcanie ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Wybierz odpowienie Przekształcanie Głosu, aby zmienić brzmienie swojego głosu">
- <combo_box.item label="Wyłącz Przekształcanie" name="no_voice_effect" />
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/pt/floater_big_preview.xml b/indra/newview/skins/default/xui/pt/floater_big_preview.xml
deleted file mode 100644
index 76ca176689..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="VISUALIZAR"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_post_process.xml b/indra/newview/skins/default/xui/pt/floater_post_process.xml
deleted file mode 100644
index d4f2e96539..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="AJUSTES DE PÓS-PROCESSAMENTO">
- <tab_container name="Post-Process Tabs">
- <panel label="Filtro de Cor" name="wmiColorFilterPanel">
- <check_box label="Habilitar" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- Brilho
- </text>
- <text name="wmiColorFilterSaturationText">
- Saturação
- </text>
- <text name="wmiColorFilterContrastText">
- Contraste
- </text>
- <text name="wmiColorFilterBaseText">
- Cor Base do Contraste
- </text>
- <slider label="R" name="wmiColorFilterBaseR"/>
- <slider label="G" name="wmiColorFilterBaseG"/>
- <slider label="B" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="visão Noturna" name="wmiNightVisionPanel">
- <check_box label="Habilitar" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- Múltiplo de Amplificação de Luz
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Tamanho de Ruído
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Intensidade de Ruído
- </text>
- </panel>
- <panel label="Florescência" name="wmiBloomPanel">
- <check_box label="Habilitar" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- Extração de Luminosidade
- </text>
- <text name="wmiBloomSizeText">
- Tamanho da florescência
- </text>
- <text name="wmiBloomStrengthText">
- Inensidade da florescência
- </text>
- </panel>
- <panel label="Extras" name="Extras">
- <button label="CarregaEfeito" label_selected="CarregaEfeito" name="PPLoadEffect"/>
- <button label="SalvaEfeito" label_selected="SalvaEfeito" name="PPSaveEffect"/>
- <line_editor label="Nome do Efeito" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml b/indra/newview/skins/default/xui/pt/floater_sound_devices.xml
deleted file mode 100644
index 948d727540..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="DISPOSITIVOS DE SOM">
- <text name="voice_label">
- Bate-papo de voz
- </text>
- <check_box label="Ativado" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
deleted file mode 100644
index 71d3c33ae5..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Lugares" name="voice_effects" title="AMOSTRA DE DISTORÇÃO DE VOZ">
- <string name="no_voice_effect">
- (Não distorcer voz)
- </string>
- <string name="active_voice_effect">
- (Ativo)
- </string>
- <string name="unsubscribed_voice_effect">
- (Cancelou)
- </string>
- <string name="new_voice_effect">
- (Novo!)
- </string>
- <string name="effect_Arena">
- Arena
- </string>
- <string name="effect_Beast">
- Fera
- </string>
- <string name="effect_Buff">
- Entusiasmado
- </string>
- <string name="effect_Buzz">
- Zumbido
- </string>
- <string name="effect_Camille">
- Camille
- </string>
- <string name="effect_Creepy">
- Assustador
- </string>
- <string name="effect_CreepyBot">
- RobôAssustador
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- RobôVozGrossa
- </string>
- <string name="effect_Demon">
- Demônio
- </string>
- <string name="effect_Female Elf">
- Elfa
- </string>
- <string name="effect_Flirty">
- Paquerador
- </string>
- <string name="effect_Foxy">
- Sensual
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Bônus_Halloween_2010
- </string>
- <string name="effect_Helium">
- Hélio
- </string>
- <string name="effect_Husky">
- Rouco
- </string>
- <string name="effect_Husky Whisper">
- Sussurro rouco
- </string>
- <string name="effect_Intercom">
- Interfone
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Cantarolado baixo
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Modelo
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Pesadelo
- </string>
- <string name="effect_PopBot">
- RobôPop
- </string>
- <string name="effect_Rachel">
- Rachel
- </string>
- <string name="effect_Radio">
- Rádio
- </string>
- <string name="effect_Robot">
- Robô
- </string>
- <string name="effect_Roxanne">
- Roxanne
- </string>
- <string name="effect_Rumble">
- Ronco
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samantha
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Baixinho
- </string>
- <string name="effect_Smaller">
- Menor
- </string>
- <string name="effect_Sneaky">
- Sorrateiro
- </string>
- <string name="effect_Stallion">
- Garanhão
- </string>
- <string name="effect_Sultry">
- Ardente
- </string>
- <string name="effect_Thunder">
- Trovão
- </string>
- <string name="effect_Vixen">
- Maliciosa
- </string>
- <string name="effect_WhinyBot">
- RobôReclamão
- </string>
- <text name="preview_text">
- Visualizar
- </text>
- <text name="status_text">
- Grave uma amostra da sua voz, depois clique em um efeito para ouvir o resultado.
- </text>
- <button label="Gravar" name="record_btn" tool_tip="Grave uma amostra da sua voz."/>
- <button label="Parar" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Assine agora]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Grave sua voz por alguns instantes, depois clique num efeito para ouvir a distorção.">
- <scroll_list.columns label="Nome da voz" name="name"/>
- <scroll_list.columns label="Vence em" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/pt/panel_login_first.xml b/indra/newview/skins/default/xui/pt/panel_login_first.xml
deleted file mode 100644
index 86c61163bc..0000000000
--- a/indra/newview/skins/default/xui/pt/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=pt
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Nome de usuário" name="username_combo" tool_tip="O nome de usuário que você escolheu ao fazer seu cadastro, como zecazc12 ou Magia Solar"/>
- <line_editor label="Senha" name="password_edit"/>
- <button label="Login" name="connect_btn"/>
- <check_box label="Lembrar-me" name="remember_check"/>
- <text name="forgot_password_text">
- Senha esquecida
- </text>
- <text name="sign_up_text">
- Cadastre-se
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Sua primeira parada é a Ilha da Educação. Encontre o portal de saída!
- </text>
- <text name="image_caption_right">
- Em seguida, explore a Ilha Social e encontre novos residentes!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml b/indra/newview/skins/default/xui/pt/panel_voice_effect.xml
deleted file mode 100644
index 1d7878408a..0000000000
--- a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Distorção de voz desligada
- </string>
- <string name="preview_voice_effects">
- Checar distorção de voz ▶
- </string>
- <string name="get_voice_effects">
- Distorcer voz ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Selecione um efeito de distorção para mudar sua voz.">
- <combo_box.item label="Distorção de voz desligada" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/ru/floater_big_preview.xml b/indra/newview/skins/default/xui/ru/floater_big_preview.xml
deleted file mode 100644
index cdacebadef..0000000000
--- a/indra/newview/skins/default/xui/ru/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="ПРОСМОТР"/>
diff --git a/indra/newview/skins/default/xui/ru/floater_post_process.xml b/indra/newview/skins/default/xui/ru/floater_post_process.xml
deleted file mode 100644
index ae97670548..0000000000
--- a/indra/newview/skins/default/xui/ru/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="НАСТРОЙКИ ПОСЛЕДУЮЩЕЙ ОБРАБОТКИ">
- <tab_container name="Post-Process Tabs">
- <panel label="Цветовой фильтр" name="wmiColorFilterPanel">
- <check_box label="Вкл." name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- Яркость
- </text>
- <text name="wmiColorFilterSaturationText">
- Насыщенность
- </text>
- <text name="wmiColorFilterContrastText">
- Контрастность
- </text>
- <text name="wmiColorFilterBaseText">
- Основной цвет контрастности
- </text>
- <slider label="К" name="wmiColorFilterBaseR"/>
- <slider label="З" name="wmiColorFilterBaseG"/>
- <slider label="С" name="wmiColorFilterBaseB"/>
- <slider label="И" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="Ночное видение" name="wmiNightVisionPanel">
- <check_box label="Вкл." name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- Коэффициент усиления света
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Размер искажений
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Мощность искажений
- </text>
- </panel>
- <panel label="Ореол" name="wmiBloomPanel">
- <check_box label="Вкл." name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- Яркость света
- </text>
- <text name="wmiBloomSizeText">
- Размер ореола
- </text>
- <text name="wmiBloomStrengthText">
- Мощность ореола
- </text>
- </panel>
- <panel label="Дополнительно" name="Extras">
- <button label="Загрузить эффект" label_selected="Загрузить эффект" name="PPLoadEffect"/>
- <button label="Сохранить эффект" label_selected="Сохранить эффект" name="PPSaveEffect"/>
- <line_editor label="Название эффекта" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_sound_devices.xml b/indra/newview/skins/default/xui/ru/floater_sound_devices.xml
deleted file mode 100644
index fc8de858cd..0000000000
--- a/indra/newview/skins/default/xui/ru/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="ЗВУКОВЫЕ УСТРОЙСТВА">
- <text name="voice_label">
- Голосовой чат
- </text>
- <check_box label="Включен" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml b/indra/newview/skins/default/xui/ru/floater_voice_effect.xml
deleted file mode 100644
index d3cef042a3..0000000000
--- a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Места" name="voice_effects" title="ПРОСМОТР ИЗМЕНЕНИЯ ГОЛОСА">
- <string name="no_voice_effect">
- (Нет изменения голоса)
- </string>
- <string name="active_voice_effect">
- (Активно)
- </string>
- <string name="unsubscribed_voice_effect">
- (Нет подписки)
- </string>
- <string name="new_voice_effect">
- (Новый!)
- </string>
- <string name="effect_Arena">
- Arena
- </string>
- <string name="effect_Beast">
- Beast
- </string>
- <string name="effect_Buff">
- Buff
- </string>
- <string name="effect_Buzz">
- Buzz
- </string>
- <string name="effect_Camille">
- Camille
- </string>
- <string name="effect_Creepy">
- Creepy
- </string>
- <string name="effect_CreepyBot">
- CreepyBot
- </string>
- <string name="effect_Cyber">
- Cyber
- </string>
- <string name="effect_DeepBot">
- DeepBot
- </string>
- <string name="effect_Demon">
- Demon
- </string>
- <string name="effect_Female Elf">
- Фея
- </string>
- <string name="effect_Flirty">
- Flirty
- </string>
- <string name="effect_Foxy">
- Foxy
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Бонус_за_Хэллоуин_2010
- </string>
- <string name="effect_Helium">
- Helium
- </string>
- <string name="effect_Husky">
- Husky
- </string>
- <string name="effect_Husky Whisper">
- Хриплый шепот
- </string>
- <string name="effect_Intercom">
- Внутренняя связь
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Напев
- </string>
- <string name="effect_Macho">
- Macho
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Модель
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Nightmare
- </string>
- <string name="effect_PopBot">
- PopBot
- </string>
- <string name="effect_Rachel">
- Rachel
- </string>
- <string name="effect_Radio">
- Radio
- </string>
- <string name="effect_Robot">
- Robot
- </string>
- <string name="effect_Roxanne">
- Roxanne
- </string>
- <string name="effect_Rumble">
- Урчание
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samantha
- </string>
- <string name="effect_Sexy">
- Sexy
- </string>
- <string name="effect_Shorty">
- Shorty
- </string>
- <string name="effect_Smaller">
- Меньше
- </string>
- <string name="effect_Sneaky">
- Sneaky
- </string>
- <string name="effect_Stallion">
- Stallion
- </string>
- <string name="effect_Sultry">
- Sultry
- </string>
- <string name="effect_Thunder">
- Thunder
- </string>
- <string name="effect_Vixen">
- Vixen
- </string>
- <string name="effect_WhinyBot">
- WhinyBot
- </string>
- <text name="preview_text">
- Прослушивание
- </text>
- <text name="status_text">
- Запишите образец, затем щелкните, чтобы услышать, как будет звучать голос.
- </text>
- <button label="Запись" name="record_btn" tool_tip="Записать образец вашего голоса."/>
- <button label="Стоп" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Подписаться]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Запишите образец вашего голоса, затем щелкните, чтобы прослушать эффект.">
- <scroll_list.columns label="Название голоса" name="name"/>
- <scroll_list.columns label="Истекает" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/ru/panel_login_first.xml b/indra/newview/skins/default/xui/ru/panel_login_first.xml
deleted file mode 100644
index 5db81ea7ca..0000000000
--- a/indra/newview/skins/default/xui/ru/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Имя пользователя" name="username_combo" tool_tip="Имя пользователя, которое вы выбрали при регистрации, например, «bobsmith12» или «Steller Sunshine»"/>
- <line_editor label="Пароль" name="password_edit"/>
- <button label="Войти" name="connect_btn"/>
- <check_box label="Запомнить меня" name="remember_check"/>
- <text name="forgot_password_text">
- Забытый пароль
- </text>
- <text name="sign_up_text">
- Регистрация
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Ваш первый шаг – Учебный остров. Найдите портал выхода!
- </text>
- <text name="image_caption_right">
- Затем исследуйте Социальный остров и познакомьтесь с другими новичками!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_voice_effect.xml b/indra/newview/skins/default/xui/ru/panel_voice_effect.xml
deleted file mode 100644
index de0b38198f..0000000000
--- a/indra/newview/skins/default/xui/ru/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Изменение голоса отключено
- </string>
- <string name="preview_voice_effects">
- Прослушать изменение голоса ▶
- </string>
- <string name="get_voice_effects">
- Приобрести изменение голоса ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Выбор типа изменения для своего голоса">
- <combo_box.item label="Изменение голоса отключено" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/tr/floater_big_preview.xml b/indra/newview/skins/default/xui/tr/floater_big_preview.xml
deleted file mode 100644
index c99a71d3c2..0000000000
--- a/indra/newview/skins/default/xui/tr/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="ÖNİZLEME"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_post_process.xml b/indra/newview/skins/default/xui/tr/floater_post_process.xml
deleted file mode 100644
index 5e419f8ffa..0000000000
--- a/indra/newview/skins/default/xui/tr/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="İŞLEM SONRASI AYARLARI">
- <tab_container name="Post-Process Tabs">
- <panel label="Renk Filtresi" name="wmiColorFilterPanel">
- <check_box label="Etkinleştir" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- Parlaklık
- </text>
- <text name="wmiColorFilterSaturationText">
- Doygunluk
- </text>
- <text name="wmiColorFilterContrastText">
- Kontrast
- </text>
- <text name="wmiColorFilterBaseText">
- Kontrast Baz Rengi
- </text>
- <slider label="R" name="wmiColorFilterBaseR"/>
- <slider label="G" name="wmiColorFilterBaseG"/>
- <slider label="B" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="Gece Görüşü" name="wmiNightVisionPanel">
- <check_box label="Etkinleştir" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- Işık Yükseltme Çarpanı
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- Gürültü Büyüklüğü
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- Gürültü Gücü
- </text>
- </panel>
- <panel label="Işıma" name="wmiBloomPanel">
- <check_box label="Etkinleştir" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- Parlaklık Çıkarma
- </text>
- <text name="wmiBloomSizeText">
- Işıma Büyüklüğü
- </text>
- <text name="wmiBloomStrengthText">
- Işıma Gücü
- </text>
- </panel>
- <panel label="Ekstralar" name="Extras">
- <button label="EfektYükle" label_selected="EfektYükle" name="PPLoadEffect"/>
- <button label="EfektKaydet" label_selected="EfektKaydet" name="PPSaveEffect"/>
- <line_editor label="Efekt Adı" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_sound_devices.xml b/indra/newview/skins/default/xui/tr/floater_sound_devices.xml
deleted file mode 100644
index 470a222d7e..0000000000
--- a/indra/newview/skins/default/xui/tr/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="SES CİHAZLARI">
- <text name="voice_label">
- Sesli Sohbet
- </text>
- <check_box label="Etkin" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml b/indra/newview/skins/default/xui/tr/floater_voice_effect.xml
deleted file mode 100644
index 7a157244cd..0000000000
--- a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Yerler" name="voice_effects" title="SES ŞEKİLLENDİRME ÖNİZLEMESİ">
- <string name="no_voice_effect">
- (Ses Şekillendirme Yok)
- </string>
- <string name="active_voice_effect">
- (Etkin)
- </string>
- <string name="unsubscribed_voice_effect">
- (Abonelik İptal)
- </string>
- <string name="new_voice_effect">
- (Yeni!)
- </string>
- <string name="effect_Arena">
- Arena
- </string>
- <string name="effect_Beast">
- Yaratık
- </string>
- <string name="effect_Buff">
- Yapılı
- </string>
- <string name="effect_Buzz">
- Vızıltı
- </string>
- <string name="effect_Camille">
- Camille
- </string>
- <string name="effect_Creepy">
- Korkutucu
- </string>
- <string name="effect_CreepyBot">
- KorkutucuBot
- </string>
- <string name="effect_Cyber">
- Siber
- </string>
- <string name="effect_DeepBot">
- DerinBot
- </string>
- <string name="effect_Demon">
- İblis
- </string>
- <string name="effect_Female Elf">
- Dişi Cin
- </string>
- <string name="effect_Flirty">
- Cilveli
- </string>
- <string name="effect_Foxy">
- Alımlı
- </string>
- <string name="effect_Halloween 2010 Bonus">
- Halloween_2010_Bonus
- </string>
- <string name="effect_Helium">
- Helyum
- </string>
- <string name="effect_Husky">
- Güçlü
- </string>
- <string name="effect_Husky Whisper">
- Boğuk Fısıltı
- </string>
- <string name="effect_Intercom">
- İnterkom
- </string>
- <string name="effect_Julia">
- Julia
- </string>
- <string name="effect_Lo Lilt">
- Yavaş Mırıltı
- </string>
- <string name="effect_Macho">
- Maço
- </string>
- <string name="effect_Micro">
- Mikro
- </string>
- <string name="effect_Mini">
- Mini
- </string>
- <string name="effect_Model">
- Model
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- Kabus
- </string>
- <string name="effect_PopBot">
- PopBot
- </string>
- <string name="effect_Rachel">
- Rachel
- </string>
- <string name="effect_Radio">
- Radyo
- </string>
- <string name="effect_Robot">
- Robot
- </string>
- <string name="effect_Roxanne">
- Roxanne
- </string>
- <string name="effect_Rumble">
- Gurultu
- </string>
- <string name="effect_Sabrina">
- Sabrina
- </string>
- <string name="effect_Samantha">
- Samantha
- </string>
- <string name="effect_Sexy">
- Seksi
- </string>
- <string name="effect_Shorty">
- Bücür
- </string>
- <string name="effect_Smaller">
- Daha Küçük
- </string>
- <string name="effect_Sneaky">
- Sinsi
- </string>
- <string name="effect_Stallion">
- Maskülen
- </string>
- <string name="effect_Sultry">
- İhtiraslı
- </string>
- <string name="effect_Thunder">
- Gök gürültüsü
- </string>
- <string name="effect_Vixen">
- Çekici
- </string>
- <string name="effect_WhinyBot">
- AğlakBot
- </string>
- <text name="preview_text">
- Önizleme için
- </text>
- <text name="status_text">
- Bir örnek kaydettikten sonra sese tıklayarak nasıl olduğunu duyun.
- </text>
- <button label="Kaydet" name="record_btn" tool_tip="Sesinizin örneğini kaydedin."/>
- <button label="Durdur" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] Hemen Abone Ol]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="Sesinizin örneğini kaydettikten sonra önizleme için bir efekte tıklayın.">
- <scroll_list.columns label="Ses Adı" name="name"/>
- <scroll_list.columns label="Bitiş Tarihi" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/tr/panel_login_first.xml b/indra/newview/skins/default/xui/tr/panel_login_first.xml
deleted file mode 100644
index 1fc80c2b97..0000000000
--- a/indra/newview/skins/default/xui/tr/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </panel.string>
- <panel.string name="sign_up_url">
- https://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="Kullanıcı Adı" name="username_combo" tool_tip="Kaydolduğunuzda seçtiğiniz kullanıcı adı, örn. mustafayalcin12 veya Faruk Gungoren"/>
- <line_editor label="Parola" name="password_edit"/>
- <button label="Oturum Aç" name="connect_btn"/>
- <check_box label="Beni hatırla" name="remember_check"/>
- <text name="forgot_password_text">
- Parolamı unuttum
- </text>
- <text name="sign_up_text">
- Kaydol
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- Başlangıç yeriniz Eğitim Adası. Haydi çıkış portalını bulun!
- </text>
- <text name="image_caption_right">
- Sonra da Sosyal Ada&apos;yı keşfe çıkın ve diğer LS sakinleriyle tanışın!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_voice_effect.xml b/indra/newview/skins/default/xui/tr/panel_voice_effect.xml
deleted file mode 100644
index b46833d7e6..0000000000
--- a/indra/newview/skins/default/xui/tr/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- Ses Şekillendirme Kapalı
- </string>
- <string name="preview_voice_effects">
- Ses Şekillendirme Önizleme ▶
- </string>
- <string name="get_voice_effects">
- Ses Şekillendirmeyi Etkinleştir ▶
- </string>
- <combo_box name="voice_effect" tool_tip="Sesinizi değiştirmek için bir Ses Şekli seçin">
- <combo_box.item label="Ses Şekillendirme Kapalı" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/skins/default/xui/zh/floater_big_preview.xml b/indra/newview/skins/default/xui/zh/floater_big_preview.xml
deleted file mode 100644
index ae68cd7ddf..0000000000
--- a/indra/newview/skins/default/xui/zh/floater_big_preview.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_big_preview" title="預覽"/>
diff --git a/indra/newview/skins/default/xui/zh/floater_post_process.xml b/indra/newview/skins/default/xui/zh/floater_post_process.xml
deleted file mode 100644
index 2908f7c1d0..0000000000
--- a/indra/newview/skins/default/xui/zh/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="後處理設定:">
- <tab_container name="Post-Process Tabs">
- <panel label="顏色過濾" name="wmiColorFilterPanel">
- <check_box label="啟用" name="wmiColorFilterToggle"/>
- <text name="wmiColorFilterBrightnessText">
- 亮度
- </text>
- <text name="wmiColorFilterSaturationText">
- 飽和度
- </text>
- <text name="wmiColorFilterContrastText">
- 對比
- </text>
- <text name="wmiColorFilterBaseText">
- 對比基本色
- </text>
- <slider label="R" name="wmiColorFilterBaseR"/>
- <slider label="G" name="wmiColorFilterBaseG"/>
- <slider label="B" name="wmiColorFilterBaseB"/>
- <slider label="I" name="wmiColorFilterBaseI"/>
- </panel>
- <panel label="夜視" name="wmiNightVisionPanel">
- <check_box label="啟用" name="wmiNightVisionToggle"/>
- <text name="wmiNightVisionBrightMultText">
- 光放大倍數
- </text>
- <text name="wmiNightVisionNoiseSizeText">
- 噪音規模
- </text>
- <text name="wmiNightVisionNoiseStrengthText">
- 噪音強度
- </text>
- </panel>
- <panel label="開花" name="wmiBloomPanel">
- <check_box label="啟用" name="wmiBloomToggle"/>
- <text name="wmiBloomExtractText">
- 光度萃取
- </text>
- <text name="wmiBloomSizeText">
- 開花大小
- </text>
- <text name="wmiBloomStrengthText">
- 開花強度
- </text>
- </panel>
- <panel label="其他" name="Extras">
- <button label="LoadEffect" label_selected="LoadEffect" name="PPLoadEffect"/>
- <button label="SaveEffect" label_selected="SaveEffect" name="PPSaveEffect"/>
- <line_editor label="效果名稱" name="PPEffectNameEditor"/>
- </panel>
- </tab_container>
-</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_sound_devices.xml b/indra/newview/skins/default/xui/zh/floater_sound_devices.xml
deleted file mode 100644
index 0374c74f8f..0000000000
--- a/indra/newview/skins/default/xui/zh/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_sound_devices" title="聲音裝置">
- <text name="voice_label">
- 語音聊天
- </text>
- <check_box label="已啟用" name="enable_voice"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_voice_effect.xml b/indra/newview/skins/default/xui/zh/floater_voice_effect.xml
deleted file mode 100644
index aab5fa6028..0000000000
--- a/indra/newview/skins/default/xui/zh/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="地點" name="voice_effects" title="語音變聲試聽">
- <string name="no_voice_effect">
- (無變聲效果)
- </string>
- <string name="active_voice_effect">
- (使用中)
- </string>
- <string name="unsubscribed_voice_effect">
- (已停止訂用)
- </string>
- <string name="new_voice_effect">
- (新的!)
- </string>
- <string name="effect_Arena">
- 競技場
- </string>
- <string name="effect_Beast">
- 野獸
- </string>
- <string name="effect_Buff">
- Buff
- </string>
- <string name="effect_Buzz">
- Buzz
- </string>
- <string name="effect_Camille">
- 卡蜜兒
- </string>
- <string name="effect_Creepy">
- 怪異
- </string>
- <string name="effect_CreepyBot">
- 怪異機器人
- </string>
- <string name="effect_Cyber">
- 科幻
- </string>
- <string name="effect_DeepBot">
- 深沉機器人
- </string>
- <string name="effect_Demon">
- 魔鬼
- </string>
- <string name="effect_Female Elf">
- 女性 - 小精靈
- </string>
- <string name="effect_Flirty">
- 調情
- </string>
- <string name="effect_Foxy">
- 香豔
- </string>
- <string name="effect_Halloween 2010 Bonus">
- 2010萬聖節加贈
- </string>
- <string name="effect_Helium">
- 氦氣
- </string>
- <string name="effect_Husky">
- 沙啞
- </string>
- <string name="effect_Husky Whisper">
- 沙啞耳語
- </string>
- <string name="effect_Intercom">
- 對講機
- </string>
- <string name="effect_Julia">
- 茱莉亞
- </string>
- <string name="effect_Lo Lilt">
- 輕微抑揚頓挫
- </string>
- <string name="effect_Macho">
- 陽剛
- </string>
- <string name="effect_Micro">
- Micro
- </string>
- <string name="effect_Mini">
- 迷你
- </string>
- <string name="effect_Model">
- 模型
- </string>
- <string name="effect_Nano">
- Nano
- </string>
- <string name="effect_Nightmare">
- 惡夢
- </string>
- <string name="effect_PopBot">
- PopBot
- </string>
- <string name="effect_Rachel">
- 瑞秋
- </string>
- <string name="effect_Radio">
- 收音機
- </string>
- <string name="effect_Robot">
- 機器人
- </string>
- <string name="effect_Roxanne">
- 蘿姍
- </string>
- <string name="effect_Rumble">
- 低沉隆隆聲
- </string>
- <string name="effect_Sabrina">
- 薩賓娜
- </string>
- <string name="effect_Samantha">
- 姍曼莎
- </string>
- <string name="effect_Sexy">
- 性感
- </string>
- <string name="effect_Shorty">
- 矮個兒
- </string>
- <string name="effect_Smaller">
- 較小
- </string>
- <string name="effect_Sneaky">
- 鬼祟
- </string>
- <string name="effect_Stallion">
- 種馬
- </string>
- <string name="effect_Sultry">
- 勾魂
- </string>
- <string name="effect_Thunder">
- 雷聲
- </string>
- <string name="effect_Vixen">
- 潑婦
- </string>
- <string name="effect_WhinyBot">
- 哭鬧機器人
- </string>
- <text name="preview_text">
- 預覽
- </text>
- <text name="status_text">
- 錄下一段樣本,再點按聲音檢查結果。
- </text>
- <button label="錄音" name="record_btn" tool_tip="錄下一段你的聲音。"/>
- <button label="停止" name="record_stop_btn"/>
- <text name="voice_morphing_link">
- [[URL] 現在訂用]
- </text>
- <scroll_list name="voice_effect_list" tool_tip="錄下一段你的聲音,再點選一個效果試聽。">
- <scroll_list.columns label="語音名稱" name="name"/>
- <scroll_list.columns label="過期" name="expires"/>
- </scroll_list>
-</floater>
diff --git a/indra/newview/skins/default/xui/zh/panel_login_first.xml b/indra/newview/skins/default/xui/zh/panel_login_first.xml
deleted file mode 100644
index 4d72fcdd03..0000000000
--- a/indra/newview/skins/default/xui/zh/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<panel name="panel_login">
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </panel.string>
- <panel.string name="sign_up_url">
- http://join.secondlife.com/
- </panel.string>
- <layout_stack name="logo_stack">
- <layout_panel name="parent_panel2">
- <layout_stack name="widget_stack">
- <layout_panel name="widget_container">
- <combo_box label="使用者名稱" name="username_combo" tool_tip="使用者名稱是你註冊時所挑選的,例如 bobsmith12 或 Steller Sunshine"/>
- <line_editor label="密碼" name="password_edit"/>
- <button label="登入" name="connect_btn"/>
- <check_box label="記得我" name="remember_check"/>
- <text name="forgot_password_text">
- 忘記密碼
- </text>
- <text name="sign_up_text">
- 註冊
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel name="parent_panel3">
- <layout_stack name="images_stack">
- <layout_panel name="images_container">
- <text name="image_caption_left">
- 你在「學習島」的第一步。 找到離開的傳送門!
- </text>
- <text name="image_caption_right">
- 接著,到「社交島」探索,認識新的居民朋友!
- </text>
- </layout_panel>
- </layout_stack>
- </layout_panel>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_voice_effect.xml b/indra/newview/skins/default/xui/zh/panel_voice_effect.xml
deleted file mode 100644
index 6c8a452014..0000000000
--- a/indra/newview/skins/default/xui/zh/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel name="panel_voice_effect">
- <string name="no_voice_effect">
- 關閉變聲效果
- </string>
- <string name="preview_voice_effects">
- 預覽變聲效果 ▶
- </string>
- <string name="get_voice_effects">
- 取得變聲效果 ▶
- </string>
- <combo_box name="voice_effect" tool_tip="選取一個變聲效果來改變你的聲音">
- <combo_box.item label="關閉變聲效果" name="no_voice_effect"/>
- </combo_box>
-</panel>
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
index acbf019034..3e2e5e70a2 100644
--- a/indra/newview/tests/lldateutil_test.cpp
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -34,16 +34,16 @@
#include "lltrans.h"
#include "llui.h"
-#include <map>
+#include <unordered_map>
// Baked-in return values for getString()
-std::map< std::string, std::string, std::less<>> gString;
+std::unordered_map< std::string, std::string, ll::string_hash, std::equal_to<>> gString;
// Baked-in return values for getCountString()
// map of pairs of input xml_desc and integer count
typedef std::pair< std::string, int > count_string_t;
-std::map< count_string_t, std::string > gCountString;
+std::map<count_string_t, std::string> gCountString;
std::string LLTrans::getString(const std::string_view xml_desc, const LLStringUtil::format_map_t& args, bool def_string)
{
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
index 94cf0fcf10..1cbb8b50eb 100644
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ b/indra/newview/tests/llviewernetwork_test.cpp
@@ -236,7 +236,7 @@ namespace tut
std::string("https://secondlife.com/helpers/"));
ensure_equals("Agni login page",
LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"),
- std::string("https://viewer-splash.secondlife.com/"));
+ std::string("https://viewer-splash-v2.secondlife.com/"));
ensure("Agni is a system grid",
LLGridManager::getInstance()->isSystemGrid("util.agni.lindenlab.com"));
@@ -261,7 +261,7 @@ namespace tut
std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
ensure_equals("Aditi login page",
LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
- std::string("https://viewer-splash.secondlife.com/"));
+ std::string("https://viewer-splash-v2.secondlife.com/"));
ensure("Aditi is a system grid",
LLGridManager::getInstance()->isSystemGrid("util.aditi.lindenlab.com"));
}
@@ -309,7 +309,7 @@ namespace tut
std::string("https://secondlife.com/helpers/"));
ensure_equals("Agni login page",
LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"),
- std::string("https://viewer-splash.secondlife.com/"));
+ std::string("https://viewer-splash-v2.secondlife.com/"));
ensure("Agni is a system grid",
LLGridManager::getInstance()->isSystemGrid("util.agni.lindenlab.com"));
@@ -333,7 +333,7 @@ namespace tut
std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
ensure_equals("Aditi login page",
LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
- std::string("https://viewer-splash.secondlife.com/"));
+ std::string("https://viewer-splash-v2.secondlife.com/"));
ensure("Aditi is a system grid",
LLGridManager::getInstance()->isSystemGrid("util.aditi.lindenlab.com"));
@@ -422,7 +422,7 @@ namespace tut
std::string("https://secondlife.com/helpers/"));
ensure_equals("getLoginPage",
LLGridManager::getInstance()->getLoginPage(),
- std::string("https://viewer-splash.secondlife.com/"));
+ std::string("https://viewer-splash-v2.secondlife.com/"));
ensure_equals("update url base for Agni", // relies on agni being the default
std::string("https://update.secondlife.com/update"),
LLGridManager::getInstance()->getUpdateServiceURL());
diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp
index 60172b3960..692dd5638c 100644
--- a/indra/newview/tests/llworldmap_test.cpp
+++ b/indra/newview/tests/llworldmap_test.cpp
@@ -54,10 +54,22 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&,
LLGLint, LLGLenum, LLHost ) { return NULL; }
// Stub related map calls
+
+// Records each sendMapBlockRequest call for inspection in tests
+struct MapBlockRequest
+{
+ U16 min_x, min_y, max_x, max_y;
+};
+static std::vector<MapBlockRequest> gMapBlockRequests;
+
LLWorldMapMessage::LLWorldMapMessage() { }
LLWorldMapMessage::~LLWorldMapMessage() { }
void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { }
-void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { }
+void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
+{
+ MapBlockRequest req = { min_x, min_y, max_x, max_y };
+ gMapBlockRequests.push_back(req);
+}
LLWorldMipmap::LLWorldMipmap() { }
LLWorldMipmap::~LLWorldMipmap() { }
@@ -518,4 +530,63 @@ namespace tut
mWorld->cancelTracking();
ensure("LLWorldMap::cancelTracking() at end test failed", mWorld->isTracking() == false);
}
+ // Test updateRegions() request grouping, size limits, and bounds
+ template<> template<>
+ void worldmap_object_t::test<4>()
+ {
+ // Test 27 : 1x1 block (4x4 = 16 regions) - single small request within bounds
+ mWorld->reset();
+ gMapBlockRequests.clear();
+ mWorld->updateRegions(0, 0, 3, 3);
+ ensure("updateRegions 1x1 block: expected 1 request", gMapBlockRequests.size() == 1);
+ {
+ const MapBlockRequest& req = gMapBlockRequests[0];
+ ensure("updateRegions 1x1 block: min_x", req.min_x == 0);
+ ensure("updateRegions 1x1 block: min_y", req.min_y == 0);
+ ensure("updateRegions 1x1 block: max_x", req.max_x == 3);
+ ensure("updateRegions 1x1 block: max_y", req.max_y == 3);
+ S32 regions = (req.max_x - req.min_x + 1) * (req.max_y - req.min_y + 1);
+ ensure("updateRegions 1x1 block: must not exceed 64 regions", regions <= 64);
+ }
+
+ // Test 28 : 2x2 blocks (8x8 = 64 regions) - single request at the 64-region limit
+ mWorld->reset();
+ gMapBlockRequests.clear();
+ mWorld->updateRegions(0, 0, 7, 7);
+ ensure("updateRegions 2x2 blocks: expected 1 request", gMapBlockRequests.size() == 1);
+ {
+ const MapBlockRequest& req = gMapBlockRequests[0];
+ ensure("updateRegions 2x2 blocks: min_x", req.min_x == 0);
+ ensure("updateRegions 2x2 blocks: min_y", req.min_y == 0);
+ ensure("updateRegions 2x2 blocks: max_x", req.max_x == 7);
+ ensure("updateRegions 2x2 blocks: max_y", req.max_y == 7);
+ S32 regions = (req.max_x - req.min_x + 1) * (req.max_y - req.min_y + 1);
+ ensure("updateRegions 2x2 blocks: must not exceed 64 regions", regions <= 64);
+ }
+
+ // Test 29 : 4x4 blocks (16x16 = 256 total regions) - must split into multiple requests
+ // each spanning a 4x1 strip (64 regions), none exceeding the server limit
+ mWorld->reset();
+ gMapBlockRequests.clear();
+ mWorld->updateRegions(0, 0, 15, 15);
+ ensure("updateRegions 4x4 blocks: expected 4 requests", gMapBlockRequests.size() == 4);
+ for (size_t i = 0; i < gMapBlockRequests.size(); ++i)
+ {
+ const MapBlockRequest& req = gMapBlockRequests[i];
+ S32 regions = (req.max_x - req.min_x + 1) * (req.max_y - req.min_y + 1);
+ ensure("updateRegions 4x4 blocks: each request must not exceed 64 regions", regions <= 64);
+ // Requests must stay within the requested area (0..15)
+ ensure("updateRegions 4x4 blocks: max_x in bounds", req.max_x <= 15);
+ ensure("updateRegions 4x4 blocks: max_y in bounds", req.max_y <= 15);
+ }
+ // Each request covers one horizontal strip of 4 blocks (rows 0..3, 4..7, 8..11, 12..15)
+ ensure("updateRegions 4x4 blocks: request[0] min_y", gMapBlockRequests[0].min_y == 0);
+ ensure("updateRegions 4x4 blocks: request[0] max_y", gMapBlockRequests[0].max_y == 3);
+ ensure("updateRegions 4x4 blocks: request[1] min_y", gMapBlockRequests[1].min_y == 4);
+ ensure("updateRegions 4x4 blocks: request[1] max_y", gMapBlockRequests[1].max_y == 7);
+ ensure("updateRegions 4x4 blocks: request[2] min_y", gMapBlockRequests[2].min_y == 8);
+ ensure("updateRegions 4x4 blocks: request[2] max_y", gMapBlockRequests[2].max_y == 11);
+ ensure("updateRegions 4x4 blocks: request[3] min_y", gMapBlockRequests[3].min_y == 12);
+ ensure("updateRegions 4x4 blocks: request[3] max_y", gMapBlockRequests[3].max_y == 15);
+ }
}
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 3a0df626f1..a8bbfe636f 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -578,14 +578,6 @@ class Windows_x86_64_Manifest(ViewerManifest):
self.path_optional("vcruntime140_1.dll")
self.path_optional("vcruntime140_threads.dll")
- # SLVoice executable
- with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
- self.path("SLVoice.exe")
-
- # Vivox libraries
- self.path("vivoxsdk_x64.dll")
- self.path("ortp_x64.dll")
-
# BugSplat
if self.args.get('bugsplat'):
self.path("BsSndRpt64.exe")
@@ -774,7 +766,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
pack_version = '.'.join(self.args['version'][:3])
if len(self.args['version']) > 3 and self.args['version'][3]:
pack_version += '-' + self.args['version'][3]
- pack_title = self.app_name() # Display name with spaces
+ pack_title = pack_id #Wrapper exe, don't use spaces
pack_dir = self.get_dst_prefix()
main_exe = self.final_exe()
installer_base = self.installer_base_name()
@@ -1141,16 +1133,6 @@ class Darwin_x86_64_Manifest(ViewerManifest):
# Need to get the llcommon dll from any of the build directories as well.
libfile_parent = self.get_dst_prefix()
dylibs=[]
- # SLVoice executable
- with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
- self.path("SLVoice")
-
- # Vivox libraries
- for libfile in (
- 'libortp.dylib',
- 'libvivoxsdk.dylib',
- ):
- self.path2basename(relpkgdir, libfile)
# Discord social SDK
if self.args['discord'] == 'ON':
@@ -1954,16 +1936,34 @@ class Linux_x86_64_Manifest(LinuxManifest):
self.path("libdirect-1.4.so.5*")
self.path("libalut.so*")
self.path("libopenal.so*")
- self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
+ # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs
+ # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1
+ # and libfontconfig.so. Before we added support for library-file
+ # wildcards, though, this self.path() call specifically named
+ # libfontconfig.so.1.4.4 WITHOUT also copying the symlinks. When I
+ # (nat) changed the call to self.path("libfontconfig.so.*"), we
+ # ended up with the libfontconfig.so.1 symlink in the target
+ # directory as well. But guess what! At least on Ubuntu 10.04,
+ # certain viewer fonts look terrible with libfontconfig.so.1
+ # present in the target directory. Removing that symlink suffices
+ # to improve them. I suspect that means we actually do better when
+ # the viewer fails to find our packaged libfontconfig.so*, falling
+ # back on the system one instead -- but diagnosing and fixing that
+ # is a bit out of scope for the present project. Meanwhile, this
+ # particular wildcard specification gets us exactly what the
+ # previous call did, without having to explicitly state the
+ # version number.
+ self.path("libfontconfig.so.*.*")
- # Vivox runtimes
- with self.prefix(src=relpkgdir, dst="bin"):
- self.path("SLVoice")
- with self.prefix(src=relpkgdir, dst="lib"):
- self.path("libortp.so")
- self.path("libsndfile.so.1")
- #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib
- self.path("libvivoxsdk.so")
+ # Include libfreetype.so. but have it work as libfontconfig does.
+ self.path("libfreetype.so.*.*")
+
+ try:
+ self.path("libtcmalloc.so*") #formerly called google perf tools
+ pass
+ except:
+ print("tcmalloc files not found, skipping")
+ pass
self.strip_binaries()
################################################################
diff --git a/indra/test/lldatapacker_tut.cpp b/indra/test/lldatapacker_tut.cpp
index 2e975ee637..5aa5233806 100644
--- a/indra/test/lldatapacker_tut.cpp
+++ b/indra/test/lldatapacker_tut.cpp
@@ -127,7 +127,7 @@ namespace tut
LLDataPackerBinaryBuffer lldp1(packbuf, cur_size);
lldp1.unpackString(unpkstr , "linden_lab_str");
- lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
@@ -286,7 +286,7 @@ namespace tut
LLDataPackerAsciiBuffer lldp1(packbuf, cur_size);
lldp1.unpackString(unpkstr , "linden_lab_str");
- lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
@@ -431,7 +431,7 @@ namespace tut
LLDataPackerAsciiFile lldp1(fp,2);
lldp1.unpackString(unpkstr , "linden_lab_str");
- lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
@@ -538,7 +538,7 @@ namespace tut
LLDataPackerAsciiFile lldp1(istr,2);
lldp1.unpackString(unpkstr , "linden_lab_str");
- lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");